diff options
| author | Charlie Stanton <charlie@shtanton.xyz> | 2023-04-26 10:30:40 +0100 | 
|---|---|---|
| committer | Charlie Stanton <charlie@shtanton.xyz> | 2023-04-26 10:30:40 +0100 | 
| commit | 88b60b7e1e43f88701c2ad0dafdcd2aa4f5fc454 (patch) | |
| tree | 16b9102442c4d0344c981faf368b031b991fea37 /walk | |
| parent | e4c2e0165d349167a736e7f44a6b66bf8a4d668f (diff) | |
| download | stred-go-88b60b7e1e43f88701c2ad0dafdcd2aa4f5fc454.tar | |
Improve the way state is tracked in fillReadBuffer
Diffstat (limited to 'walk')
| -rw-r--r-- | walk/read.go | 177 | 
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  		} | 
