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

View File

@ -34,104 +34,93 @@ func Get(b []byte, keys [][]byte) []Field {
} }
} }
l := 10 prealloc := 20
res := make([]Field, l) res := make([]Field, prealloc)
s, e, d := 0, 0, 0
var kf bool
var k []byte
for i := 0; i < len(b); i++ { for i := 0; i < len(b); i++ {
if state == expectObjClose || state == expectListClose {
switch b[i] {
case '{', '[':
d++
case '}', ']':
d--
}
}
switch { switch {
case state == expectKey && b[i] == '"': case state == expectKey && b[i] == '"':
state = expectKeyClose state = expectKeyClose
s = i + 1 s = i
continue
case state == expectKeyClose && b[i] == '"': case state == expectKeyClose && b[i] == '"':
state = expectColon state = expectColon
k = b[(s + 1):i]
_, kf = kmap[sha1.Sum(k)]
case state == expectColon && b[i] == ':':
state = expectValue
case state == expectValue && b[i] == '"':
state = expectString
s = i
case state == expectString && b[i] == '"':
e = i
case state == expectValue && b[i] == '[':
state = expectListClose
s = i
d++
case state == expectListClose && d == 0 && b[i] == ']':
e = i
i = s
case state == expectValue && b[i] == '{':
state = expectObjClose
s = i
d++
case state == expectObjClose && d == 0 && b[i] == '}':
e = i
i = s
case state == expectValue && (b[i] >= '0' && b[i] <= '9'):
state = expectNumClose
s = i
case state == expectNumClose &&
((b[i] < '0' || b[i] > '9') &&
(b[i] != '.' && b[i] != 'e' && b[i] != 'E' && b[i] != '+' && b[i] != '-')):
i--
e = i
case state == expectValue &&
(b[i] == 'f' || b[i] == 'F' || b[i] == 't' || b[i] == 'T'):
state = expectBoolClose
s = i
case state == expectBoolClose && (b[i] == 'e' || b[i] == 'E'):
e = i
} }
if state != expectColon { if e != 0 {
continue if kf {
} if len(res) == cap(res) {
r := make([]Field, 0, (len(res) * 2))
k := b[s:i] copy(r, res)
h := sha1.Sum(k) res = r
_, kf := kmap[h]
e := 0
d := 0
for ; i < len(b); i++ {
if state == expectObjClose || state == expectListClose {
switch b[i] {
case '{', '[':
d++
case '}', ']':
d--
} }
res = append(res, Field{k, b[s:(e + 1)]})
} }
switch { state = expectKey
case state == expectColon && b[i] == ':': e = 0
state = expectValue
case state == expectValue && b[i] == '"':
state = expectString
s = i
case state == expectString && b[i] == '"':
e = i
case state == expectValue && b[i] == '[':
state = expectListClose
s = i
d++
case state == expectListClose && d == 0 && b[i] == ']':
e = i
i = s
case state == expectValue && b[i] == '{':
state = expectObjClose
s = i
d++
case state == expectObjClose && d == 0 && b[i] == '}':
e = i
i = s
case state == expectValue && (b[i] >= '0' && b[i] <= '9'):
state = expectNumClose
s = i
case state == expectNumClose &&
((b[i] < '0' || b[i] > '9') &&
(b[i] != '.' && b[i] != 'e' && b[i] != 'E' && b[i] != '+' && b[i] != '-')):
i--
e = i
case state == expectValue &&
(b[i] == 'f' || b[i] == 'F' || b[i] == 't' || b[i] == 'T'):
state = expectBoolClose
s = i
case state == expectBoolClose && (b[i] == 'e' || b[i] == 'E'):
e = i
}
if e != 0 {
e++
if kf {
if len(res) == cap(res) {
r := make([]Field, 0, (len(res) + l))
copy(r, res)
res = r
}
res = append(res, Field{k, b[s:e]})
}
state = expectKey
break
}
} }
} }

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") 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)) fmap := make(map[[20]byte]int, (len(from) * 2))
tmap := make(map[[20]byte]int, (len(from))) tmap := make(map[[20]byte]int, (len(from)))
@ -33,124 +27,122 @@ func Replace(w *bytes.Buffer, b []byte, from, to []Field) error {
tmap[h2] = i tmap[h2] = i
} }
for i := 0; i < len(b); i++ { state := expectKey
switch { ws, we := 0, len(b)
case ws == 0 && b[i] == '{' || b[i] == '[':
ws = i
s, e, d := 0, 0, 0
fi := -1
for i := 0; i < len(b); i++ {
// skip any left padding whitespace
if ws == 0 && (b[i] == '{' || b[i] == '[') {
ws = i
}
if state == expectObjClose || state == expectListClose {
switch b[i] {
case '{', '[':
d++
case '}', ']':
d--
}
}
switch {
case state == expectKey && b[i] == '"': case state == expectKey && b[i] == '"':
state = expectKeyClose state = expectKeyClose
s = i + 1 s = i
continue
case state == expectKeyClose && b[i] == '"': case state == expectKeyClose && b[i] == '"':
state = expectColon state = expectColon
h1 := sha1.Sum(b[(s + 1):i])
default: if n, ok := fmap[h1]; ok {
continue we = s
} fi = n
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 '{', '[':
d++
case '}', ']':
d--
}
} }
switch { case state == expectColon && b[i] == ':':
case state == expectColon && b[i] == ':': state = expectValue
state = expectValue
case state == expectValue && b[i] == '"': case state == expectValue && b[i] == '"':
state = expectString state = expectString
s = i s = i
case state == expectString && b[i] == '"': case state == expectString && b[i] == '"':
e = i e = i
case state == expectValue && b[i] == '[': case state == expectValue && b[i] == '[':
state = expectListClose state = expectListClose
s = i s = i
d++ d++
case state == expectListClose && d == 0 && b[i] == ']': case state == expectListClose && d == 0 && b[i] == ']':
e = i e = i
case state == expectValue && b[i] == '{': case state == expectValue && b[i] == '{':
state = expectObjClose state = expectObjClose
s = i s = i
d++ d++
case state == expectObjClose && d == 0 && b[i] == '}': case state == expectObjClose && d == 0 && b[i] == '}':
e = i e = i
case state == expectValue && (b[i] >= '0' && b[i] <= '9'): case state == expectValue && (b[i] >= '0' && b[i] <= '9'):
state = expectNumClose state = expectNumClose
s = i s = i
case state == expectNumClose && case state == expectNumClose &&
((b[i] < '0' || b[i] > '9') && ((b[i] < '0' || b[i] > '9') &&
(b[i] != '.' && b[i] != 'e' && b[i] != 'E' && b[i] != '+' && b[i] != '-')): (b[i] != '.' && b[i] != 'e' && b[i] != 'E' && b[i] != '+' && b[i] != '-')):
i-- i--
e = i e = i
case state == expectValue && case state == expectValue &&
(b[i] == 'f' || b[i] == 'F' || b[i] == 't' || b[i] == 'T'): (b[i] == 'f' || b[i] == 'F' || b[i] == 't' || b[i] == 'T'):
state = expectBoolClose state = expectBoolClose
s = i s = i
case state == expectBoolClose && (b[i] == 'e' || b[i] == 'E'): case state == expectBoolClose && (b[i] == 'e' || b[i] == 'E'):
e = i e = i
} }
if e != 0 { if e != 0 {
e++ e++
h2 := sha1.Sum(b[s:e])
if n, ok1 := fmap[h2]; ok1 && n == fi { h2 := sha1.Sum(b[s:e])
ti, ok2 := tmap[h2] replace := false
if ok2 { if n, ok1 := fmap[h2]; ok1 && n == fi {
if _, err := w.Write(b[ws:we]); err != nil { ti, ok2 := tmap[h2]
return err
} if ok2 {
if _, err := w.Write(to[ti].Key); err != nil { if _, err := w.Write(b[ws:(we + 1)]); err != nil {
return err return err
}
if _, err := w.WriteString(`":`); err != nil {
return err
}
if _, err := w.Write(to[ti].Value); err != nil {
return err
}
ws = e
} }
if _, err := w.Write(to[ti].Key); err != nil {
return err
}
if _, err := w.WriteString(`":`); err != nil {
return err
}
if _, err := w.Write(to[ti].Value); err != nil {
return err
}
replace = true
ws = e
} }
if ws != e && (b[s] == '[' || b[s] == '{') {
i = s - 1
}
state = expectKey
we = len(b)
fi = -1
break
} }
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
e = 0
d = 0
} }
} }

View File

@ -9,108 +9,96 @@ func Strip(b []byte, path []string) []byte {
state := expectKey state := expectKey
kb := make([][]byte, 0, len(path)) kb := make([][]byte, 0, len(path))
ki := 0
for _, k := range path { for _, k := range path {
kb = append(kb, []byte(k)) kb = append(kb, []byte(k))
} }
s, e, d := 0, 0, 0
ki := 0
pm := false
for i := 0; i < len(b); i++ { for i := 0; i < len(b); i++ {
if state == expectObjClose || state == expectListClose {
switch b[i] {
case '{', '[':
d++
case '}', ']':
d--
}
}
switch { switch {
case state == expectKey && b[i] == '"': case state == expectKey && b[i] == '"':
state = expectKeyClose state = expectKeyClose
s = i + 1 s = i
continue
case state == expectKeyClose && b[i] == '"': case state == expectKeyClose && b[i] == '"':
state = expectColon state = expectColon
} if ki == len(kb) {
ki = 0
if state != expectColon { }
continue pm = bytes.Equal(b[(s+1):i], kb[ki])
} if pm {
ki++
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 '{', '[':
d++
case '}', ']':
d--
}
} }
switch { case state == expectColon && b[i] == ':':
case state == expectColon && b[i] == ':': state = expectValue
state = expectValue
case state == expectValue && b[i] == '"': case state == expectValue && b[i] == '"':
state = expectString state = expectString
s = i s = i
case state == expectString && b[i] == '"': case state == expectString && b[i] == '"':
e = i e = i
case state == expectValue && b[i] == '[': case state == expectValue && b[i] == '[':
state = expectListClose state = expectListClose
s = i s = i
d++ d++
case state == expectListClose && d == 0 && b[i] == ']': case state == expectListClose && d == 0 && b[i] == ']':
e = i e = i
case state == expectValue && b[i] == '{': case state == expectValue && b[i] == '{':
state = expectObjClose state = expectObjClose
s = i s = i
d++ d++
case state == expectObjClose && d == 0 && b[i] == '}': case state == expectObjClose && d == 0 && b[i] == '}':
e = i e = i
case state == expectValue && (b[i] >= '0' && b[i] <= '9'): case state == expectValue && (b[i] >= '0' && b[i] <= '9'):
state = expectNumClose state = expectNumClose
s = i s = i
case state == expectNumClose && case state == expectNumClose &&
((b[i] < '0' || b[i] > '9') && ((b[i] < '0' || b[i] > '9') &&
(b[i] != '.' && b[i] != 'e' && b[i] != 'E' && b[i] != '+' && b[i] != '-')): (b[i] != '.' && b[i] != 'e' && b[i] != 'E' && b[i] != '+' && b[i] != '-')):
i-- i--
e = i e = i
case state == expectValue && case state == expectValue &&
(b[i] == 'f' || b[i] == 'F' || b[i] == 't' || b[i] == 'T'): (b[i] == 'f' || b[i] == 'F' || b[i] == 't' || b[i] == 'T'):
state = expectBoolClose state = expectBoolClose
s = i s = i
case state == expectBoolClose && (b[i] == 'e' || b[i] == 'E'): case state == expectBoolClose && (b[i] == 'e' || b[i] == 'E'):
e = i e = i
} }
if e != 0 && (b[s] == '[' || b[s] == '{') { if e != 0 {
e++ if pm && (b[s] == '[' || b[s] == '{') {
b = b[s:e] b = b[s:(e + 1)]
i = 0 i = 0
if ki == len(kb) { if ki == len(kb) {
return b return b
} }
state = expectKey
break
} }
state = expectKey
e = 0
} }
} }