Apply .gitignore rules
This commit is contained in:
@@ -0,0 +1,284 @@
|
||||
package parse
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
type itemType int
|
||||
|
||||
const (
|
||||
itemComma itemType = iota // ','
|
||||
itemSlash // '/'
|
||||
itemAt // '@'
|
||||
itemDot // '.'
|
||||
itemLParens // '('
|
||||
itemRParens // ')'
|
||||
itemLBracket // '['
|
||||
itemRBracket // ']'
|
||||
itemStar // '*'
|
||||
itemPlus // '+'
|
||||
itemMinus // '-'
|
||||
itemEq // '='
|
||||
itemLt // '<'
|
||||
itemGt // '>'
|
||||
itemBang // '!'
|
||||
itemDollar // '$'
|
||||
itemApos // '\''
|
||||
itemQuote // '"'
|
||||
itemUnion // '|'
|
||||
itemNe // '!='
|
||||
itemLe // '<='
|
||||
itemGe // '>='
|
||||
itemAnd // '&&'
|
||||
itemOr // '||'
|
||||
itemDotDot // '..'
|
||||
itemSlashSlash // '//'
|
||||
itemName // XML Name
|
||||
itemString // Quoted string constant
|
||||
itemNumber // Number constant
|
||||
itemAxe // Axe (like child::)
|
||||
itemEof // END
|
||||
)
|
||||
|
||||
type scanner struct {
|
||||
text, name, prefix string
|
||||
|
||||
pos int
|
||||
curr rune
|
||||
typ itemType
|
||||
strval string // text value at current pos
|
||||
numval float64 // number value at current pos
|
||||
canBeFunc bool
|
||||
}
|
||||
|
||||
func (s *scanner) nextChar() bool {
|
||||
if s.pos >= len(s.text) {
|
||||
s.curr = rune(0)
|
||||
return false
|
||||
}
|
||||
s.curr = rune(s.text[s.pos])
|
||||
s.pos += 1
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *scanner) nextItem() bool {
|
||||
s.skipSpace()
|
||||
switch s.curr {
|
||||
case 0:
|
||||
s.typ = itemEof
|
||||
return false
|
||||
case ',', '@', '(', ')', '|', '*', '[', ']', '+', '-', '=', '#', '$':
|
||||
s.typ = asItemType(s.curr)
|
||||
s.nextChar()
|
||||
case '<':
|
||||
s.typ = itemLt
|
||||
s.nextChar()
|
||||
if s.curr == '=' {
|
||||
s.typ = itemLe
|
||||
s.nextChar()
|
||||
}
|
||||
case '>':
|
||||
s.typ = itemGt
|
||||
s.nextChar()
|
||||
if s.curr == '=' {
|
||||
s.typ = itemGe
|
||||
s.nextChar()
|
||||
}
|
||||
case '!':
|
||||
s.typ = itemBang
|
||||
s.nextChar()
|
||||
if s.curr == '=' {
|
||||
s.typ = itemNe
|
||||
s.nextChar()
|
||||
}
|
||||
case '.':
|
||||
s.typ = itemDot
|
||||
s.nextChar()
|
||||
if s.curr == '.' {
|
||||
s.typ = itemDotDot
|
||||
s.nextChar()
|
||||
} else if isDigit(s.curr) {
|
||||
s.typ = itemNumber
|
||||
s.numval = s.scanFraction()
|
||||
}
|
||||
case '/':
|
||||
s.typ = itemSlash
|
||||
s.nextChar()
|
||||
if s.curr == '/' {
|
||||
s.typ = itemSlashSlash
|
||||
s.nextChar()
|
||||
}
|
||||
case '"', '\'':
|
||||
s.typ = itemString
|
||||
s.strval = s.scanString()
|
||||
default:
|
||||
if isDigit(s.curr) {
|
||||
s.typ = itemNumber
|
||||
s.numval = s.scanNumber()
|
||||
} else if isName(s.curr) {
|
||||
s.typ = itemName
|
||||
s.name = s.scanName()
|
||||
s.prefix = ""
|
||||
// "foo:bar" is one itemem not three because it doesn't allow spaces in between
|
||||
// We should distinct it from "foo::" and need process "foo ::" as well
|
||||
if s.curr == ':' {
|
||||
s.nextChar()
|
||||
// can be "foo:bar" or "foo::"
|
||||
if s.curr == ':' {
|
||||
// "foo::"
|
||||
s.nextChar()
|
||||
s.typ = itemAxe
|
||||
} else { // "foo:*", "foo:bar" or "foo: "
|
||||
s.prefix = s.name
|
||||
if s.curr == '*' {
|
||||
s.nextChar()
|
||||
s.name = "*"
|
||||
} else if isName(s.curr) {
|
||||
s.name = s.scanName()
|
||||
} else {
|
||||
panic(fmt.Sprintf("%s has an invalid qualified name.", s.text))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
s.skipSpace()
|
||||
if s.curr == ':' {
|
||||
s.nextChar()
|
||||
// it can be "foo ::" or just "foo :"
|
||||
if s.curr == ':' {
|
||||
s.nextChar()
|
||||
s.typ = itemAxe
|
||||
} else {
|
||||
panic(fmt.Sprintf("%s has an invalid qualified name.", s.text))
|
||||
}
|
||||
}
|
||||
}
|
||||
s.skipSpace()
|
||||
s.canBeFunc = s.curr == '('
|
||||
} else {
|
||||
panic(fmt.Sprintf("%s has an invalid token.", s.text))
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *scanner) skipSpace() {
|
||||
Loop:
|
||||
for {
|
||||
if !unicode.IsSpace(s.curr) || !s.nextChar() {
|
||||
break Loop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *scanner) scanFraction() float64 {
|
||||
var (
|
||||
i = s.pos - 2
|
||||
c = 1 // '.'
|
||||
)
|
||||
for isDigit(s.curr) {
|
||||
s.nextChar()
|
||||
c++
|
||||
}
|
||||
v, err := strconv.ParseFloat(s.text[i:i+c], 64)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("xpath: scanFraction parse float got error: %v", err))
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func (s *scanner) scanNumber() float64 {
|
||||
var (
|
||||
c int
|
||||
i = s.pos - 1
|
||||
)
|
||||
for isDigit(s.curr) {
|
||||
s.nextChar()
|
||||
c++
|
||||
}
|
||||
if s.curr == '.' {
|
||||
s.nextChar()
|
||||
c++
|
||||
for isDigit(s.curr) {
|
||||
s.nextChar()
|
||||
c++
|
||||
}
|
||||
}
|
||||
v, err := strconv.ParseFloat(s.text[i:i+c], 64)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("xpath: scanNumber parse float got error: %v", err))
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func (s *scanner) scanString() string {
|
||||
var (
|
||||
c = 0
|
||||
end = s.curr
|
||||
)
|
||||
s.nextChar()
|
||||
i := s.pos - 1
|
||||
for s.curr != end {
|
||||
if !s.nextChar() {
|
||||
panic(errors.New("xpath: scanString got unclosed string"))
|
||||
}
|
||||
c++
|
||||
}
|
||||
s.nextChar()
|
||||
return s.text[i : i+c]
|
||||
}
|
||||
|
||||
func (s *scanner) scanName() string {
|
||||
var (
|
||||
c int
|
||||
i = s.pos - 1
|
||||
)
|
||||
for isName(s.curr) {
|
||||
c++
|
||||
if !s.nextChar() {
|
||||
break
|
||||
}
|
||||
}
|
||||
return s.text[i : i+c]
|
||||
}
|
||||
|
||||
func isName(r rune) bool {
|
||||
return string(r) != ":" && string(r) != "/" &&
|
||||
(unicode.Is(first, r) || unicode.Is(second, r) || string(r) == "*")
|
||||
}
|
||||
|
||||
func isDigit(r rune) bool {
|
||||
return unicode.IsDigit(r)
|
||||
}
|
||||
|
||||
func asItemType(r rune) itemType {
|
||||
switch r {
|
||||
case ',':
|
||||
return itemComma
|
||||
case '@':
|
||||
return itemAt
|
||||
case '(':
|
||||
return itemLParens
|
||||
case ')':
|
||||
return itemRParens
|
||||
case '|':
|
||||
return itemUnion
|
||||
case '*':
|
||||
return itemStar
|
||||
case '[':
|
||||
return itemLBracket
|
||||
case ']':
|
||||
return itemRBracket
|
||||
case '+':
|
||||
return itemPlus
|
||||
case '-':
|
||||
return itemMinus
|
||||
case '=':
|
||||
return itemEq
|
||||
case '$':
|
||||
return itemDollar
|
||||
}
|
||||
panic(fmt.Errorf("unknown item: %v", r))
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package goroutineMgr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"goutil/logUtil"
|
||||
)
|
||||
|
||||
var (
|
||||
goroutineCountMap = make(map[string]int)
|
||||
goroutineCountMutex sync.RWMutex
|
||||
)
|
||||
|
||||
// 增加指定名称的goroutine的数量
|
||||
// goroutineName:goroutine名称
|
||||
func increaseCount(goroutineName string) {
|
||||
goroutineCountMutex.Lock()
|
||||
defer goroutineCountMutex.Unlock()
|
||||
|
||||
newCount := 1
|
||||
if currCount, exist := goroutineCountMap[goroutineName]; exist {
|
||||
newCount = currCount + 1
|
||||
}
|
||||
|
||||
goroutineCountMap[goroutineName] = newCount
|
||||
}
|
||||
|
||||
// 减少指定名称的goroutine的数量
|
||||
// goroutineName:goroutine名称
|
||||
func decreaseCount(goroutineName string) {
|
||||
goroutineCountMutex.Lock()
|
||||
defer goroutineCountMutex.Unlock()
|
||||
|
||||
newCount := -1
|
||||
if currCount, exist := goroutineCountMap[goroutineName]; exist {
|
||||
newCount = currCount - 1
|
||||
}
|
||||
|
||||
if newCount <= 0 {
|
||||
delete(goroutineCountMap, goroutineName)
|
||||
} else {
|
||||
goroutineCountMap[goroutineName] = newCount
|
||||
}
|
||||
}
|
||||
|
||||
// 获取指定名称的goroutine的数量
|
||||
// goroutineName:goroutine名称
|
||||
// 返回值:
|
||||
// 对应数量
|
||||
func getGoroutineCount(goroutineName string) int {
|
||||
goroutineCountMutex.RLock()
|
||||
defer goroutineCountMutex.RUnlock()
|
||||
|
||||
if currCount, exist := goroutineCountMap[goroutineName]; exist {
|
||||
return currCount
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// 转化成字符串
|
||||
func toString() string {
|
||||
goroutineCountMutex.RLock()
|
||||
defer goroutineCountMutex.RUnlock()
|
||||
|
||||
keys := make([]string, 0, 16)
|
||||
for key := range goroutineCountMap {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
|
||||
sort.Slice(keys, func(i, j int) bool {
|
||||
return keys[i] < keys[j]
|
||||
})
|
||||
|
||||
str := fmt.Sprintf("Goroutine Info:(%s,%d)", "NumGoroutine", runtime.NumGoroutine())
|
||||
for _, key := range keys {
|
||||
str += fmt.Sprintf("(%s,%d)", key, goroutineCountMap[key])
|
||||
}
|
||||
|
||||
return str
|
||||
}
|
||||
|
||||
// 记录goroutine数量信息
|
||||
func logGoroutineCountInfo() {
|
||||
logUtil.DebugLog(toString())
|
||||
}
|
||||
|
||||
func Test() {
|
||||
logGoroutineCountInfo()
|
||||
}
|
||||
Reference in New Issue
Block a user