diff options
| author | Charlie Stanton <charlie@shtanton.xyz> | 2023-04-24 19:02:23 +0100 | 
|---|---|---|
| committer | Charlie Stanton <charlie@shtanton.xyz> | 2023-04-24 19:02:23 +0100 | 
| commit | 1e092ec62cf591e57f0b0bfb80b4484dd90c9c8c (patch) | |
| tree | 38ef5e079cacdb860a12f92cd9921246d1be106c | |
| parent | 8e80185508a697ddfcfed4a04d3f4e1ac5a330a9 (diff) | |
| download | stred-go-1e092ec62cf591e57f0b0bfb80b4484dd90c9c8c.tar | |
Improves performance of reading JSON strings
| -rw-r--r-- | walk/walk.go | 81 | 
1 files changed, 39 insertions, 42 deletions
| diff --git a/walk/walk.go b/walk/walk.go index 008713b..0719d1c 100644 --- a/walk/walk.go +++ b/walk/walk.go @@ -228,7 +228,7 @@ type JSONIn struct {  func NewJSONIn(reader *bufio.Reader) JSONIn {  	return JSONIn { -		path: nil, +		path: make([]Atom, 0, 256),  		reader: reader,  		structure: []JSONInStructure{JSONInRoot},  	} @@ -297,6 +297,41 @@ func (in *JSONIn) require(criterion rune) {  	}  } +func (in *JSONIn) readString(out []Atom) []Atom { +	// TODO: improve +	out = append(out, NewAtomStringTerminal()) +	for { +		r, _, err := in.reader.ReadRune() +		if err != nil { +			panic("Missing closing terminal in string input: " + err.Error()) +		} +		if r == '"' { +			break +		} +		if r == '\\' { +			r, _, err = in.reader.ReadRune() +			if err != nil { +				panic("Missing rune after \\") +			} +			if len(out) == cap(out) { +				newOut := make([]Atom, len(out), cap(out) * 2) +				copy(newOut, out) +				out = newOut +			} +			out = append(out, NewAtomStringRune(r)) +			continue +		} +		if len(out) == cap(out) { +			newOut := make([]Atom, len(out), cap(out) * 2) +			copy(newOut, out) +			out = newOut +		} +		out = append(out, NewAtomStringRune(r)) +	} +	out = append(out, NewAtomStringTerminal()) +	return out +} +  func (in *JSONIn) Read() (WalkItem, error) {  	item, err := in.read()  	if err != nil { @@ -331,26 +366,7 @@ func (in *JSONIn) read() (WalkItem, error) {  			if r != '"' {  				panic("Expected key, found something else")  			} -			in.path = append(in.path, NewAtomStringTerminal()) -			for { -				r, _, err = in.reader.ReadRune() -				if err != nil { -					return WalkItem {}, err -				} -				if r == '"' { -					break -				} -				if r == '\\' { -					r, _, err = in.reader.ReadRune() -					if err != nil { -						panic("Missing rune after \\") -					} -					in.path = append(in.path, NewAtomStringRune(r)) -					continue -				} -				in.path = append(in.path, NewAtomStringRune(r)) -			} -			in.path = append(in.path, NewAtomStringTerminal()) +			in.path = in.readString(in.path)  			r, err = in.nextNonWsRune()  			if err != nil {  				panic("Expected : got: " + err.Error()) @@ -432,27 +448,8 @@ func (in *JSONIn) read() (WalkItem, error) {  				Path: in.path,  			}, nil  		case '"': -			value := make([]Atom, 0, 2) -			value = append(value, NewAtomStringTerminal()) -			for { -				r, _, err = in.reader.ReadRune() -				if err != nil { -					panic("Missing closing terminal in string input: " + err.Error()) -				} -				if r == '"' { -					break -				} -				if r == '\\' { -					r, _, err = in.reader.ReadRune() -					if err != nil { -						panic("Missing rune after \\") -					} -					value = append(value, NewAtomStringRune(r)) -					continue -				} -				value = append(value, NewAtomStringRune(r)) -			} -			value = append(value, NewAtomStringTerminal()) +			value := make([]Atom, 0, 64) +			value = in.readString(value)  			in.structure = append(in.structure, JSONInValueEnd)  			return WalkItem {  				Value: value, | 
