You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
201 lines
3.5 KiB
201 lines
3.5 KiB
package scanner |
|
|
|
import ( |
|
"sync" |
|
|
|
"github.com/goccy/go-yaml/token" |
|
) |
|
|
|
// Context context at scanning |
|
type Context struct { |
|
idx int |
|
size int |
|
notSpaceCharPos int |
|
notSpaceOrgCharPos int |
|
src []rune |
|
buf []rune |
|
obuf []rune |
|
tokens token.Tokens |
|
isRawFolded bool |
|
isLiteral bool |
|
isFolded bool |
|
isSingleLine bool |
|
literalOpt string |
|
} |
|
|
|
var ( |
|
ctxPool = sync.Pool{ |
|
New: func() interface{} { |
|
return createContext() |
|
}, |
|
} |
|
) |
|
|
|
func createContext() *Context { |
|
return &Context{ |
|
idx: 0, |
|
tokens: token.Tokens{}, |
|
isSingleLine: true, |
|
} |
|
} |
|
|
|
func newContext(src []rune) *Context { |
|
ctx := ctxPool.Get().(*Context) |
|
ctx.reset(src) |
|
return ctx |
|
} |
|
|
|
func (c *Context) release() { |
|
ctxPool.Put(c) |
|
} |
|
|
|
func (c *Context) reset(src []rune) { |
|
c.idx = 0 |
|
c.size = len(src) |
|
c.src = src |
|
c.tokens = c.tokens[:0] |
|
c.resetBuffer() |
|
c.isSingleLine = true |
|
} |
|
|
|
func (c *Context) resetBuffer() { |
|
c.buf = c.buf[:0] |
|
c.obuf = c.obuf[:0] |
|
c.notSpaceCharPos = 0 |
|
c.notSpaceOrgCharPos = 0 |
|
} |
|
|
|
func (c *Context) isSaveIndentMode() bool { |
|
return c.isLiteral || c.isFolded || c.isRawFolded |
|
} |
|
|
|
func (c *Context) breakLiteral() { |
|
c.isLiteral = false |
|
c.isRawFolded = false |
|
c.isFolded = false |
|
c.literalOpt = "" |
|
} |
|
|
|
func (c *Context) addToken(tk *token.Token) { |
|
if tk == nil { |
|
return |
|
} |
|
c.tokens = append(c.tokens, tk) |
|
} |
|
|
|
func (c *Context) addBuf(r rune) { |
|
if len(c.buf) == 0 && r == ' ' { |
|
return |
|
} |
|
c.buf = append(c.buf, r) |
|
if r != ' ' && r != '\t' { |
|
c.notSpaceCharPos = len(c.buf) |
|
} |
|
} |
|
|
|
func (c *Context) addOriginBuf(r rune) { |
|
c.obuf = append(c.obuf, r) |
|
if r != ' ' && r != '\t' { |
|
c.notSpaceOrgCharPos = len(c.obuf) |
|
} |
|
} |
|
|
|
func (c *Context) removeRightSpaceFromBuf() int { |
|
trimmedBuf := c.obuf[:c.notSpaceOrgCharPos] |
|
buflen := len(trimmedBuf) |
|
diff := len(c.obuf) - buflen |
|
if diff > 0 { |
|
c.obuf = c.obuf[:buflen] |
|
c.buf = c.bufferedSrc() |
|
} |
|
return diff |
|
} |
|
|
|
func (c *Context) isDocument() bool { |
|
return c.isLiteral || c.isFolded || c.isRawFolded |
|
} |
|
|
|
func (c *Context) isEOS() bool { |
|
return len(c.src)-1 <= c.idx |
|
} |
|
|
|
func (c *Context) isNextEOS() bool { |
|
return len(c.src)-1 <= c.idx+1 |
|
} |
|
|
|
func (c *Context) next() bool { |
|
return c.idx < c.size |
|
} |
|
|
|
func (c *Context) source(s, e int) string { |
|
return string(c.src[s:e]) |
|
} |
|
|
|
func (c *Context) previousChar() rune { |
|
if c.idx > 0 { |
|
return c.src[c.idx-1] |
|
} |
|
return rune(0) |
|
} |
|
|
|
func (c *Context) currentChar() rune { |
|
return c.src[c.idx] |
|
} |
|
|
|
func (c *Context) nextChar() rune { |
|
if c.size > c.idx+1 { |
|
return c.src[c.idx+1] |
|
} |
|
return rune(0) |
|
} |
|
|
|
func (c *Context) repeatNum(r rune) int { |
|
cnt := 0 |
|
for i := c.idx; i < c.size; i++ { |
|
if c.src[i] == r { |
|
cnt++ |
|
} else { |
|
break |
|
} |
|
} |
|
return cnt |
|
} |
|
|
|
func (c *Context) progress(num int) { |
|
c.idx += num |
|
} |
|
|
|
func (c *Context) nextPos() int { |
|
return c.idx + 1 |
|
} |
|
|
|
func (c *Context) existsBuffer() bool { |
|
return len(c.bufferedSrc()) != 0 |
|
} |
|
|
|
func (c *Context) bufferedSrc() []rune { |
|
src := c.buf[:c.notSpaceCharPos] |
|
if len(src) > 0 && src[len(src)-1] == '\n' && c.isDocument() && c.literalOpt == "-" { |
|
// remove end '\n' character |
|
src = src[:len(src)-1] |
|
} |
|
return src |
|
} |
|
|
|
func (c *Context) bufferedToken(pos *token.Position) *token.Token { |
|
if c.idx == 0 { |
|
return nil |
|
} |
|
source := c.bufferedSrc() |
|
if len(source) == 0 { |
|
return nil |
|
} |
|
var tk *token.Token |
|
if c.isDocument() { |
|
tk = token.String(string(source), string(c.obuf), pos) |
|
} else { |
|
tk = token.New(string(source), string(c.obuf), pos) |
|
} |
|
c.resetBuffer() |
|
return tk |
|
}
|
|
|