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  }