github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/yaml/scanner/context.go (about) 1 package scanner 2 3 import ( 4 "sync" 5 6 "github.com/bingoohuang/gg/pkg/yaml/token" 7 ) 8 9 // Context context at scanning 10 type Context struct { 11 idx int 12 size int 13 notSpaceCharPos int 14 notSpaceOrgCharPos int 15 src []rune 16 buf []rune 17 obuf []rune 18 tokens token.Tokens 19 isRawFolded bool 20 isLiteral bool 21 isFolded bool 22 isSingleLine bool 23 literalOpt string 24 } 25 26 var ctxPool = sync.Pool{ 27 New: func() interface{} { 28 return createContext() 29 }, 30 } 31 32 func createContext() *Context { 33 return &Context{ 34 idx: 0, 35 tokens: token.Tokens{}, 36 isSingleLine: true, 37 } 38 } 39 40 func newContext(src []rune) *Context { 41 ctx := ctxPool.Get().(*Context) 42 ctx.reset(src) 43 return ctx 44 } 45 46 func (c *Context) release() { 47 ctxPool.Put(c) 48 } 49 50 func (c *Context) reset(src []rune) { 51 c.idx = 0 52 c.size = len(src) 53 c.src = src 54 c.tokens = c.tokens[:0] 55 c.resetBuffer() 56 c.isSingleLine = true 57 } 58 59 func (c *Context) resetBuffer() { 60 c.buf = c.buf[:0] 61 c.obuf = c.obuf[:0] 62 c.notSpaceCharPos = 0 63 c.notSpaceOrgCharPos = 0 64 } 65 66 func (c *Context) isSaveIndentMode() bool { 67 return c.isLiteral || c.isFolded || c.isRawFolded 68 } 69 70 func (c *Context) breakLiteral() { 71 c.isLiteral = false 72 c.isRawFolded = false 73 c.isFolded = false 74 c.literalOpt = "" 75 } 76 77 func (c *Context) addToken(tk *token.Token) { 78 if tk == nil { 79 return 80 } 81 c.tokens = append(c.tokens, tk) 82 } 83 84 func (c *Context) addBuf(r rune) { 85 if len(c.buf) == 0 && r == ' ' { 86 return 87 } 88 c.buf = append(c.buf, r) 89 if r != ' ' && r != '\t' { 90 c.notSpaceCharPos = len(c.buf) 91 } 92 } 93 94 func (c *Context) addOriginBuf(r rune) { 95 c.obuf = append(c.obuf, r) 96 if r != ' ' && r != '\t' { 97 c.notSpaceOrgCharPos = len(c.obuf) 98 } 99 } 100 101 func (c *Context) removeRightSpaceFromBuf() int { 102 trimmedBuf := c.obuf[:c.notSpaceOrgCharPos] 103 buflen := len(trimmedBuf) 104 diff := len(c.obuf) - buflen 105 if diff > 0 { 106 c.obuf = c.obuf[:buflen] 107 c.buf = c.bufferedSrc() 108 } 109 return diff 110 } 111 112 func (c *Context) isDocument() bool { 113 return c.isLiteral || c.isFolded || c.isRawFolded 114 } 115 116 func (c *Context) isEOS() bool { 117 return len(c.src)-1 <= c.idx 118 } 119 120 func (c *Context) isNextEOS() bool { 121 return len(c.src)-1 <= c.idx+1 122 } 123 124 func (c *Context) next() bool { 125 return c.idx < c.size 126 } 127 128 func (c *Context) source(s, e int) string { 129 return string(c.src[s:e]) 130 } 131 132 func (c *Context) previousChar() rune { 133 if c.idx > 0 { 134 return c.src[c.idx-1] 135 } 136 return rune(0) 137 } 138 139 func (c *Context) currentChar() rune { 140 return c.src[c.idx] 141 } 142 143 func (c *Context) nextChar() rune { 144 if c.size > c.idx+1 { 145 return c.src[c.idx+1] 146 } 147 return rune(0) 148 } 149 150 func (c *Context) repeatNum(r rune) int { 151 cnt := 0 152 for i := c.idx; i < c.size; i++ { 153 if c.src[i] == r { 154 cnt++ 155 } else { 156 break 157 } 158 } 159 return cnt 160 } 161 162 func (c *Context) progress(num int) { 163 c.idx += num 164 } 165 166 func (c *Context) nextPos() int { 167 return c.idx + 1 168 } 169 170 func (c *Context) existsBuffer() bool { 171 return len(c.bufferedSrc()) != 0 172 } 173 174 func (c *Context) bufferedSrc() []rune { 175 src := c.buf[:c.notSpaceCharPos] 176 if len(src) > 0 && src[len(src)-1] == '\n' && c.isDocument() && c.literalOpt == "-" { 177 // remove end '\n' character 178 src = src[:len(src)-1] 179 } 180 return src 181 } 182 183 func (c *Context) bufferedToken(pos *token.Position) *token.Token { 184 if c.idx == 0 { 185 return nil 186 } 187 source := c.bufferedSrc() 188 if len(source) == 0 { 189 return nil 190 } 191 var tk *token.Token 192 if c.isDocument() { 193 tk = token.String(string(source), string(c.obuf), pos) 194 } else { 195 tk = token.New(string(source), string(c.obuf), pos) 196 } 197 c.resetBuffer() 198 return tk 199 }