<- Back to shtanton's homepage
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharlie Stanton <charlie@shtanton.xyz>2023-04-26 10:30:40 +0100
committerCharlie Stanton <charlie@shtanton.xyz>2023-04-26 10:30:40 +0100
commit88b60b7e1e43f88701c2ad0dafdcd2aa4f5fc454 (patch)
tree16b9102442c4d0344c981faf368b031b991fea37
parente4c2e0165d349167a736e7f44a6b66bf8a4d668f (diff)
downloadstred-go-88b60b7e1e43f88701c2ad0dafdcd2aa4f5fc454.tar
Improve the way state is tracked in fillReadBuffer
-rw-r--r--walk/read.go177
1 files changed, 103 insertions, 74 deletions
diff --git a/walk/read.go b/walk/read.go
index 00be010..f123369 100644
--- a/walk/read.go
+++ b/walk/read.go
@@ -22,16 +22,22 @@ const (
JSONInRoot JSONInStructure = iota
JSONInMap
JSONInArray
+)
+
+type JSONInState int
+const (
+ JSONInValueEnd JSONInState = iota
+ JSONInValue
+ JSONInValueStart
JSONInString
- JSONInValueEnd
JSONInKey
- JSONInKeyEnd
)
type JSONIn struct {
path []Atom
reader *bufio.Reader
structure []JSONInStructure
+ state JSONInState
readBuffer []Atom
readIndex int
readBufferCapacity int
@@ -44,6 +50,7 @@ func NewJSONIn(reader *bufio.Reader) JSONIn {
path: make([]Atom, 0, 256),
reader: reader,
structure: []JSONInStructure{JSONInRoot},
+ state: JSONInValueStart,
readBuffer: make([]Atom, 0, 256),
readIndex: 0,
readBufferCapacity: 256,
@@ -142,8 +149,7 @@ func (in *JSONIn) Read() (WalkItem, error) {
in.readIndex = 0
in.actionBuffer = in.actionBuffer[:0]
in.readBuffer = in.readBuffer[:0]
- structure, err := in.fillReadBuffer(in.structure)
- in.structure = structure
+ err := in.fillReadBuffer()
if len(in.actionBuffer) == 0 {
return WalkItem{}, err
}
@@ -158,8 +164,7 @@ func (in *JSONIn) Read() (WalkItem, error) {
in.readBufferCapacity *= 2
copy(newReadBuffer, in.readBuffer)
in.readBuffer = newReadBuffer
- structure, _ := in.fillReadBuffer(in.structure)
- in.structure = structure
+ in.fillReadBuffer()
continue actionLoop
}
copy(in.readBuffer, in.readBuffer[in.readIndex:])
@@ -168,8 +173,7 @@ func (in *JSONIn) Read() (WalkItem, error) {
copy(in.actionBuffer, in.actionBuffer[in.actionIndex:])
in.actionBuffer = in.actionBuffer[:len(in.actionBuffer) - in.actionIndex]
in.actionIndex = 0
- structure, _ := in.fillReadBuffer(in.structure)
- in.structure = structure
+ in.fillReadBuffer()
continue actionLoop
}
in.readIndex += len(value)
@@ -186,8 +190,7 @@ func (in *JSONIn) Read() (WalkItem, error) {
in.readBufferCapacity *= 2
copy(newReadBuffer, in.readBuffer)
in.readBuffer = newReadBuffer
- structure, _ := in.fillReadBuffer(in.structure)
- in.structure = structure
+ in.fillReadBuffer()
continue actionLoop
}
copy(in.readBuffer, in.readBuffer[in.readIndex:])
@@ -196,8 +199,7 @@ func (in *JSONIn) Read() (WalkItem, error) {
copy(in.actionBuffer, in.actionBuffer[in.actionIndex:])
in.actionBuffer = in.actionBuffer[:len(in.actionBuffer) - in.actionIndex]
in.actionIndex = 0
- structure, _ := in.fillReadBuffer(in.structure)
- in.structure = structure
+ in.fillReadBuffer()
continue actionLoop
}
in.readIndex += len(value)
@@ -239,28 +241,34 @@ func (in *JSONIn) pushActionBuffer(action ReadAction) {
in.actionBuffer = append(in.actionBuffer, action)
}
-func (in *JSONIn) fillReadBuffer(structure []JSONInStructure) ([]JSONInStructure, error) {
+// Appends to the readBuffer until it has reached capacity
+// Also appends to the actionBuffer as needed
+func (in *JSONIn) fillReadBuffer() error {
+ switch in.state {
+ case JSONInValueStart:
+ goto valueStart
+ case JSONInValue:
+ goto value
+ case JSONInValueEnd:
+ goto valueEnd
+ case JSONInString:
+ goto string
+ case JSONInKey:
+ goto key
+ default:
+ panic("Invalid JSONInState")
+ }
valueStart: {
- state := structure[len(structure) - 1]
- switch state {
- case JSONInString:
- structure = structure[:len(structure) - 1]
- goto string
- case JSONInValueEnd:
- structure = structure[:len(structure) - 1]
- goto valueEnd
- case JSONInKey:
- structure = structure[:len(structure) - 1]
- goto key
- case JSONInKeyEnd:
- structure = structure[:len(structure) - 1]
- goto keyEnd
+ innermost := in.structure[len(in.structure) - 1]
+ switch innermost {
case JSONInMap:
goto mapValue
case JSONInArray:
goto arrayValue
case JSONInRoot:
goto value
+ default:
+ panic("Invalid JSONInStructure")
}
}
value: {
@@ -273,43 +281,49 @@ func (in *JSONIn) fillReadBuffer(structure []JSONInStructure) ([]JSONInStructure
in.requireString("ull")
in.pushActionBuffer(ActionReadValue)
if in.pushReadBuffer(NewAtomNull()) {
- return append(structure, JSONInValueEnd), nil
+ in.state = JSONInValueEnd
+ return nil
}
goto valueEnd
case 'f':
in.requireString("alse")
in.pushActionBuffer(ActionReadValue)
if in.pushReadBuffer(NewAtomBool(false)) {
- return append(structure, JSONInValueEnd), nil
+ in.state = JSONInValueEnd
+ return nil
}
goto valueEnd
case 't':
in.requireString("rue")
in.pushActionBuffer(ActionReadValue)
if in.pushReadBuffer(NewAtomBool(true)) {
- return append(structure, JSONInValueEnd), nil
+ in.state = JSONInValueEnd
+ return nil
}
goto valueEnd
case '"':
in.pushActionBuffer(ActionReadValue)
if in.pushReadBuffer(NewAtomStringTerminal()) {
- return append(structure, JSONInString), nil
+ in.state = JSONInString
+ return nil
}
goto string
case '{':
- structure = append(structure, JSONInMap)
+ in.structure = append(in.structure, JSONInMap)
in.pushActionBuffer(ActionReadValue)
in.pushActionBuffer(ActionAppendPathNull)
if in.pushReadBuffer(NewAtomTerminal(MapBegin)) {
- return structure, nil
+ in.state = JSONInValueStart
+ return nil
}
goto mapValue
case '[':
- structure = append(structure, JSONInArray)
+ in.structure = append(in.structure, JSONInArray)
in.pushActionBuffer(ActionReadValue)
in.pushActionBuffer(ActionAppendPathNull)
if in.pushReadBuffer(NewAtomTerminal(ArrayBegin)) {
- return structure, nil
+ in.state = JSONInValueStart
+ return nil
}
goto arrayValue
}
@@ -333,7 +347,8 @@ func (in *JSONIn) fillReadBuffer(structure []JSONInStructure) ([]JSONInStructure
}
in.pushActionBuffer(ActionReadValue)
if in.pushReadBuffer(NewAtomNumber(number)) {
- return append(structure, JSONInValueEnd), nil
+ in.state = JSONInValueEnd
+ return nil
}
goto valueEnd
}
@@ -346,7 +361,8 @@ func (in *JSONIn) fillReadBuffer(structure []JSONInStructure) ([]JSONInStructure
}
if r == '"' {
if in.pushReadBuffer(NewAtomStringTerminal()) {
- return append(structure, JSONInValueEnd), nil
+ in.state = JSONInValueEnd
+ return nil
}
goto valueEnd
}
@@ -356,42 +372,45 @@ func (in *JSONIn) fillReadBuffer(structure []JSONInStructure) ([]JSONInStructure
panic("Missing rune after \\")
}
if in.pushReadBuffer(NewAtomStringRune(r)) {
- return append(structure, JSONInString), nil
+ in.state = JSONInString
+ return nil
}
goto string
}
if in.pushReadBuffer(NewAtomStringRune(r)) {
- return append(structure, JSONInString), nil
+ in.state = JSONInString
+ return nil
}
goto string
}
key: {
- r, _, err := in.reader.ReadRune()
- if err != nil {
- panic("Missing closing terminal in string input: " + err.Error())
- }
- if r == '"' {
- if in.pushReadBuffer(NewAtomStringTerminal()) {
- return append(structure, JSONInKeyEnd), nil
- }
- goto keyEnd
- }
- if r == '\\' {
- r, _, err = in.reader.ReadRune()
+ var full bool
+ for {
+ r, _, err := in.reader.ReadRune()
if err != nil {
- panic("Missing rune after \\")
+ panic("Missing closing terminal in string input: " + err.Error())
+ }
+ if r == '"' {
+ full = in.pushReadBuffer(NewAtomStringTerminal())
+ break
+ }
+ if r == '\\' {
+ r, _, err = in.reader.ReadRune()
+ if err != nil {
+ panic("Missing rune after \\")
+ }
+ if in.pushReadBuffer(NewAtomStringRune(r)) {
+ in.state = JSONInKey
+ return nil
+ }
+ continue
}
if in.pushReadBuffer(NewAtomStringRune(r)) {
- return append(structure, JSONInKey), nil
+ in.state = JSONInKey
+ return nil
}
- goto key
- }
- if in.pushReadBuffer(NewAtomStringRune(r)) {
- return append(structure, JSONInKey), nil
+ continue
}
- goto key
- }
- keyEnd: {
r, err := in.nextNonWsRune()
if err != nil {
panic("Expected : got: " + err.Error())
@@ -399,30 +418,37 @@ func (in *JSONIn) fillReadBuffer(structure []JSONInStructure) ([]JSONInStructure
if r != ':' {
panic("Expected : after key")
}
+ if full {
+ in.state = JSONInValue
+ return nil
+ }
goto value
}
valueEnd: {
r, err := in.nextNonWsRune()
if err != nil {
- return append(structure, JSONInValueEnd), err
+ in.state = JSONInValueEnd
+ return err
}
- underState := structure[len(structure) - 1]
- if underState == JSONInRoot {
+ innermost := in.structure[len(in.structure) - 1]
+ if innermost == JSONInRoot {
panic("More input after root JSON object ends")
- } else if underState == JSONInMap && r == '}' {
- structure = structure[:len(structure) - 1]
+ } else if innermost == JSONInMap && r == '}' {
+ in.structure = in.structure[:len(in.structure) - 1]
in.pushActionBuffer(ActionPopPath)
in.pushActionBuffer(ActionReadValue)
if in.pushReadBuffer(NewAtomTerminal(MapEnd)) {
- return append(structure, JSONInValueEnd), nil
+ in.state = JSONInValueEnd
+ return nil
}
goto valueEnd
- } else if underState == JSONInArray && r == ']' {
- structure = structure[:len(structure) - 1]
+ } else if innermost == JSONInArray && r == ']' {
+ in.structure = in.structure[:len(in.structure) - 1]
in.pushActionBuffer(ActionPopPath)
in.pushActionBuffer(ActionReadValue)
if in.pushReadBuffer(NewAtomTerminal(ArrayEnd)) {
- return append(structure, JSONInValueEnd), nil
+ in.state = JSONInValueEnd
+ return nil
}
goto valueEnd
}
@@ -438,10 +464,11 @@ func (in *JSONIn) fillReadBuffer(structure []JSONInStructure) ([]JSONInStructure
panic("Missing value inside object")
}
if r == '}' {
- structure = structure[:len(structure) - 1]
+ in.structure = in.structure[:len(in.structure) - 1]
in.pushActionBuffer(ActionReadValue)
if in.pushReadBuffer(NewAtomTerminal(MapEnd)) {
- return append(structure, JSONInValueEnd), nil
+ in.state = JSONInValueEnd
+ return nil
}
goto valueEnd
}
@@ -450,7 +477,8 @@ func (in *JSONIn) fillReadBuffer(structure []JSONInStructure) ([]JSONInStructure
}
in.pushActionBuffer(ActionAppendPath)
if in.pushReadBuffer(NewAtomStringTerminal()) {
- return append(structure, JSONInKey), nil
+ in.state = JSONInKey
+ return nil
}
goto key
}
@@ -460,11 +488,12 @@ func (in *JSONIn) fillReadBuffer(structure []JSONInStructure) ([]JSONInStructure
panic("Missing value inside array")
}
if r == ']' {
- structure = structure[:len(structure) - 1]
+ in.structure = in.structure[:len(in.structure) - 1]
in.pushActionBuffer(ActionPopPath)
in.pushActionBuffer(ActionReadValue)
if in.pushReadBuffer(NewAtomTerminal(ArrayEnd)) {
- return append(structure, JSONInValueEnd), nil
+ in.state = JSONInValueEnd
+ return nil
}
goto valueEnd
}