NBT convert part 1

This commit is contained in:
Tnze
2021-05-25 20:10:57 +08:00
parent 69601cec28
commit c44af2bf34
4 changed files with 181 additions and 7 deletions

View File

@ -2,10 +2,12 @@ package nbt
import (
"errors"
"sync"
)
const (
scanContinue = iota // uninteresting byte
scanBeginLiteral // end implied by next result != scanContinue
scanBeginCompound // begin TAG_Compound (after left-brace )
scanBeginList // begin TAG_List (after left-brack)
scanListValue // just finished read list value
@ -35,6 +37,7 @@ type scanner struct {
step func(c byte) int
parseState []int
err error
endTop bool
}
// reset prepares the scanner for use.
@ -44,6 +47,28 @@ func (s *scanner) reset() {
s.parseState = s.parseState[0:0]
}
var scannerPool = sync.Pool{
New: func() interface{} {
return &scanner{}
},
}
func newScanner() *scanner {
scan := scannerPool.Get().(*scanner)
// scan.reset by design doesn't set bytes to zero
//scan.bytes = 0
scan.reset()
return scan
}
func freeScanner(scan *scanner) {
// Avoid hanging on to too much memory in extreme cases.
if len(scan.parseState) > 1024 {
scan.parseState = nil
}
scannerPool.Put(scan)
}
// pushParseState pushes a new parse state p onto the parse stack.
// an error state is returned if maxNestingDepth was exceeded, otherwise successState is returned.
func (s *scanner) pushParseState(c byte, newParseState int, successState int) int {
@ -67,6 +92,25 @@ func (s *scanner) popParseState() {
}
}
// eof tells the scanner that the end of input has been reached.
// It returns a scan status just as s.step does.
func (s *scanner) eof() int {
if s.err != nil {
return scanError
}
if s.endTop {
return scanEnd
}
s.step(' ')
if s.endTop {
return scanEnd
}
if s.err == nil {
s.err = errors.New("unexpected end of JSON input")
}
return scanError
}
// stateEndTop is the state after finishing the top-level value,
// such as after reading `{}` or `[1,2,3]`.
// Only space characters should be seen now.
@ -94,10 +138,11 @@ func (s *scanner) stateBeginValue(c byte) int {
return s.stateBeginString(c)
case '-': // beginning of negative number
s.step = s.stateNeg
return scanContinue
return scanBeginLiteral
default:
if isNumber(c) {
return s.stateNum1(c)
s.stateNum0(c)
return scanBeginLiteral
}
if isAllowedInUnquotedString(c) {
return s.stateBeginString(c)
@ -125,14 +170,14 @@ func (s *scanner) stateBeginString(c byte) int {
switch c {
case '\'':
s.step = s.stateInSingleQuotedString
return scanContinue
return scanBeginLiteral
case '"':
s.step = s.stateInDoubleQuotedString
return scanContinue
return scanBeginLiteral
default:
if isAllowedInUnquotedString(c) {
s.step = s.stateInUnquotedString
return scanContinue
return scanBeginLiteral
}
}
return s.error(c, "looking for beginning of string")
@ -211,6 +256,18 @@ func (s *scanner) stateListOrArrayT(c byte) int {
}
func (s *scanner) stateNeg(c byte) int {
if isNumber(c) {
s.step = s.stateNum0
return scanBeginLiteral
}
if isAllowedInUnquotedString(c) {
s.step = s.stateInUnquotedString
return scanBeginLiteral
}
return s.error(c, "not a number after '-'")
}
func (s *scanner) stateNum0(c byte) int {
if isNumber(c) {
s.step = s.stateNum1
return scanContinue
@ -219,7 +276,7 @@ func (s *scanner) stateNeg(c byte) int {
s.step = s.stateInUnquotedString
return scanContinue
}
return s.error(c, "not a number after '-'")
return s.stateEndNumValue(c)
}
func (s *scanner) stateNum1(c byte) int {
@ -304,7 +361,7 @@ func (s *scanner) stateEndValue(c byte) int {
if n == 0 {
// Completed top-level before the current byte.
s.step = s.stateEndTop
//s.endTop = true
s.endTop = true
return s.stateEndTop(c)
}
if isSpace(c) {