Improve readability of json parser code

This commit is contained in:
Vikram Rangnekar 2019-05-08 23:52:04 -04:00
parent b405dafb89
commit 1e78491cb2
4 changed files with 318 additions and 348 deletions

View File

@ -6,7 +6,6 @@ import (
)
func Filter(w *bytes.Buffer, b []byte, keys []string) error {
s := 0
state := expectKey
var err error
@ -19,10 +18,29 @@ func Filter(w *bytes.Buffer, b []byte, keys []string) error {
}
}
// is an list
isList := false
// list item
item := 0
// field in an object
field := 0
s, e, d := 0, 0, 0
kf := false
for i := 0; i < len(b); i++ {
if state == expectObjClose || state == expectListClose {
switch b[i] {
case '{', '[':
d++
case '}', ']':
d--
}
}
switch {
case state == expectKey:
switch b[i] {
@ -35,7 +53,7 @@ func Filter(w *bytes.Buffer, b []byte, keys []string) error {
if item == 0 {
err = w.WriteByte('{')
} else {
_, err = w.WriteString("},{")
_, err = w.Write([]byte("},{"))
}
item++
field = 0
@ -44,36 +62,14 @@ func Filter(w *bytes.Buffer, b []byte, keys []string) error {
s = i
i++
}
if err != nil {
return err
}
case state == expectKeyClose && b[i] == '"':
state = expectColon
i++
}
k := b[(s + 1):i]
_, kf = kmap[sha1.Sum(k)]
if err != nil {
return nil
}
if state != expectColon {
continue
}
k := b[(s + 1):(i - 1)]
h := sha1.Sum(k)
_, kf := kmap[h]
e := 0
d := 0
for ; i < len(b); i++ {
if state == expectObjClose || state == expectListClose {
switch b[i] {
case '{', '[':
d++
case '}', ']':
d--
}
}
switch {
case state == expectColon && b[i] == ':':
state = expectValue
@ -115,14 +111,20 @@ func Filter(w *bytes.Buffer, b []byte, keys []string) error {
}
if e != 0 {
if kf {
state = expectKey
cb := b[s:(e + 1)]
e = 0
if !kf {
continue
}
if field != 0 {
if err := w.WriteByte(','); err != nil {
return err
}
}
cb := b[s:(e + 1)]
sk := 0
for i := 0; i < len(cb); i++ {
if cb[i] == '\n' || cb[i] == '\t' {
@ -138,21 +140,20 @@ func Filter(w *bytes.Buffer, b []byte, keys []string) error {
} else {
_, err = w.Write(cb)
}
if err != nil {
return err
}
field++
}
state = expectKey
break
}
}
}
if item != 0 {
if err := w.WriteByte('}'); err != nil {
return err
}
}
if isList {
if err := w.WriteByte(']'); err != nil {
return err

View File

@ -34,31 +34,15 @@ func Get(b []byte, keys [][]byte) []Field {
}
}
l := 10
res := make([]Field, l)
prealloc := 20
res := make([]Field, prealloc)
s, e, d := 0, 0, 0
var kf bool
var k []byte
for i := 0; i < len(b); i++ {
switch {
case state == expectKey && b[i] == '"':
state = expectKeyClose
s = i + 1
continue
case state == expectKeyClose && b[i] == '"':
state = expectColon
}
if state != expectColon {
continue
}
k := b[s:i]
h := sha1.Sum(k)
_, kf := kmap[h]
e := 0
d := 0
for ; i < len(b); i++ {
if state == expectObjClose || state == expectListClose {
switch b[i] {
case '{', '[':
@ -69,6 +53,15 @@ func Get(b []byte, keys [][]byte) []Field {
}
switch {
case state == expectKey && b[i] == '"':
state = expectKeyClose
s = i
case state == expectKeyClose && b[i] == '"':
state = expectColon
k = b[(s + 1):i]
_, kf = kmap[sha1.Sum(k)]
case state == expectColon && b[i] == ':':
state = expectValue
@ -117,21 +110,17 @@ func Get(b []byte, keys [][]byte) []Field {
}
if e != 0 {
e++
if kf {
if len(res) == cap(res) {
r := make([]Field, 0, (len(res) + l))
r := make([]Field, 0, (len(res) * 2))
copy(r, res)
res = r
}
res = append(res, Field{k, b[s:e]})
res = append(res, Field{k, b[s:(e + 1)]})
}
state = expectKey
break
}
e = 0
}
}

View File

@ -11,12 +11,6 @@ func Replace(w *bytes.Buffer, b []byte, from, to []Field) error {
return errors.New("'from' and 'to' must be of the same length")
}
state := expectKey
ws, we := 0, len(b)
s := 0
fi := -1
fmap := make(map[[20]byte]int, (len(from) * 2))
tmap := make(map[[20]byte]int, (len(from)))
@ -33,36 +27,18 @@ func Replace(w *bytes.Buffer, b []byte, from, to []Field) error {
tmap[h2] = i
}
state := expectKey
ws, we := 0, len(b)
s, e, d := 0, 0, 0
fi := -1
for i := 0; i < len(b); i++ {
switch {
case ws == 0 && b[i] == '{' || b[i] == '[':
// skip any left padding whitespace
if ws == 0 && (b[i] == '{' || b[i] == '[') {
ws = i
case state == expectKey && b[i] == '"':
state = expectKeyClose
s = i + 1
continue
case state == expectKeyClose && b[i] == '"':
state = expectColon
default:
continue
}
if state != expectColon {
continue
}
h1 := sha1.Sum(b[s:i])
if n, ok := fmap[h1]; ok {
we = s
fi = n
}
e := 0
d := 0
for ; i < len(b); i++ {
if state == expectObjClose || state == expectListClose {
switch b[i] {
case '{', '[':
@ -73,6 +49,18 @@ func Replace(w *bytes.Buffer, b []byte, from, to []Field) error {
}
switch {
case state == expectKey && b[i] == '"':
state = expectKeyClose
s = i
case state == expectKeyClose && b[i] == '"':
state = expectColon
h1 := sha1.Sum(b[(s + 1):i])
if n, ok := fmap[h1]; ok {
we = s
fi = n
}
case state == expectColon && b[i] == ':':
state = expectValue
@ -120,13 +108,15 @@ func Replace(w *bytes.Buffer, b []byte, from, to []Field) error {
if e != 0 {
e++
h2 := sha1.Sum(b[s:e])
replace := false
if n, ok1 := fmap[h2]; ok1 && n == fi {
ti, ok2 := tmap[h2]
if ok2 {
if _, err := w.Write(b[ws:we]); err != nil {
if _, err := w.Write(b[ws:(we + 1)]); err != nil {
return err
}
if _, err := w.Write(to[ti].Key); err != nil {
@ -138,19 +128,21 @@ func Replace(w *bytes.Buffer, b []byte, from, to []Field) error {
if _, err := w.Write(to[ti].Value); err != nil {
return err
}
replace = true
ws = e
}
}
if ws != e && (b[s] == '[' || b[s] == '{') {
if !replace && (b[s] == '[' || b[s] == '{') {
// the i++ in the for loop will add 1 so we account for that (s - 1)
i = s - 1
}
state = expectKey
we = len(b)
fi = -1
break
}
e = 0
d = 0
}
}

View File

@ -9,41 +9,15 @@ func Strip(b []byte, path []string) []byte {
state := expectKey
kb := make([][]byte, 0, len(path))
ki := 0
for _, k := range path {
kb = append(kb, []byte(k))
}
s, e, d := 0, 0, 0
ki := 0
pm := false
for i := 0; i < len(b); i++ {
switch {
case state == expectKey && b[i] == '"':
state = expectKeyClose
s = i + 1
continue
case state == expectKeyClose && b[i] == '"':
state = expectColon
}
if state != expectColon {
continue
}
if ki >= len(kb) {
return nil
}
if !bytes.Equal(b[s:i], kb[ki]) {
state = expectKey
continue
}
ki++
e := 0
d := 0
s := 0
for ; i < len(b); i++ {
if state == expectObjClose || state == expectListClose {
switch b[i] {
case '{', '[':
@ -54,6 +28,20 @@ func Strip(b []byte, path []string) []byte {
}
switch {
case state == expectKey && b[i] == '"':
state = expectKeyClose
s = i
case state == expectKeyClose && b[i] == '"':
state = expectColon
if ki == len(kb) {
ki = 0
}
pm = bytes.Equal(b[(s+1):i], kb[ki])
if pm {
ki++
}
case state == expectColon && b[i] == ':':
state = expectValue
@ -99,18 +87,18 @@ func Strip(b []byte, path []string) []byte {
e = i
}
if e != 0 && (b[s] == '[' || b[s] == '{') {
e++
b = b[s:e]
if e != 0 {
if pm && (b[s] == '[' || b[s] == '{') {
b = b[s:(e + 1)]
i = 0
if ki == len(kb) {
return b
}
}
state = expectKey
break
}
e = 0
}
}