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,115 +62,98 @@ 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)]
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 {
return nil
}
if e != 0 {
state = expectKey
cb := b[s:(e + 1)]
e = 0
if state != expectColon {
continue
}
if !kf {
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--
if field != 0 {
if err := w.WriteByte(','); err != nil {
return err
}
}
switch {
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 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 {
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
}
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 err := w.WriteByte('}'); err != nil {
return err
}
}
if isList {
if err := w.WriteByte(']'); err != nil {
return err

View File

@ -34,104 +34,93 @@ 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++ {
if state == expectObjClose || state == expectListClose {
switch b[i] {
case '{', '[':
d++
case '}', ']':
d--
}
}
switch {
case state == expectKey && b[i] == '"':
state = expectKeyClose
s = i + 1
continue
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
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 {
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 '{', '[':
d++
case '}', ']':
d--
if e != 0 {
if kf {
if len(res) == cap(res) {
r := make([]Field, 0, (len(res) * 2))
copy(r, res)
res = r
}
res = append(res, Field{k, b[s:(e + 1)]})
}
switch {
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 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
}
state = expectKey
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,124 +27,122 @@ func Replace(w *bytes.Buffer, b []byte, from, to []Field) error {
tmap[h2] = i
}
for i := 0; i < len(b); i++ {
switch {
case ws == 0 && b[i] == '{' || b[i] == '[':
ws = i
state := expectKey
ws, we := 0, len(b)
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] == '"':
state = expectKeyClose
s = i + 1
continue
s = i
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 '{', '[':
d++
case '}', ']':
d--
}
h1 := sha1.Sum(b[(s + 1):i])
if n, ok := fmap[h1]; ok {
we = s
fi = n
}
switch {
case state == expectColon && b[i] == ':':
state = expectValue
case state == expectColon && b[i] == ':':
state = expectValue
case state == expectValue && b[i] == '"':
state = expectString
s = i
case state == expectValue && b[i] == '"':
state = expectString
s = i
case state == expectString && b[i] == '"':
e = i
case state == expectString && b[i] == '"':
e = i
case state == expectValue && b[i] == '[':
state = expectListClose
s = i
d++
case state == expectValue && b[i] == '[':
state = expectListClose
s = i
d++
case state == expectListClose && d == 0 && b[i] == ']':
e = i
case state == expectListClose && d == 0 && b[i] == ']':
e = i
case state == expectValue && b[i] == '{':
state = expectObjClose
s = i
d++
case state == expectValue && b[i] == '{':
state = expectObjClose
s = i
d++
case state == expectObjClose && d == 0 && b[i] == '}':
e = i
case state == expectObjClose && d == 0 && b[i] == '}':
e = i
case state == expectValue && (b[i] >= '0' && b[i] <= '9'):
state = expectNumClose
s = i
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 == 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 == 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
}
case state == expectBoolClose && (b[i] == 'e' || b[i] == 'E'):
e = i
}
if e != 0 {
e++
h2 := sha1.Sum(b[s:e])
if e != 0 {
e++
if n, ok1 := fmap[h2]; ok1 && n == fi {
ti, ok2 := tmap[h2]
h2 := sha1.Sum(b[s:e])
replace := false
if ok2 {
if _, err := w.Write(b[ws:we]); err != nil {
return err
}
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
}
ws = e
if n, ok1 := fmap[h2]; ok1 && n == fi {
ti, ok2 := tmap[h2]
if ok2 {
if _, err := w.Write(b[ws:(we + 1)]); err != nil {
return err
}
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
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++ {
if state == expectObjClose || state == expectListClose {
switch b[i] {
case '{', '[':
d++
case '}', ']':
d--
}
}
switch {
case state == expectKey && b[i] == '"':
state = expectKeyClose
s = i + 1
continue
s = i
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 '{', '[':
d++
case '}', ']':
d--
}
if ki == len(kb) {
ki = 0
}
pm = bytes.Equal(b[(s+1):i], kb[ki])
if pm {
ki++
}
switch {
case state == expectColon && b[i] == ':':
state = expectValue
case state == expectColon && b[i] == ':':
state = expectValue
case state == expectValue && b[i] == '"':
state = expectString
s = i
case state == expectValue && b[i] == '"':
state = expectString
s = i
case state == expectString && b[i] == '"':
e = i
case state == expectString && b[i] == '"':
e = i
case state == expectValue && b[i] == '[':
state = expectListClose
s = i
d++
case state == expectValue && b[i] == '[':
state = expectListClose
s = i
d++
case state == expectListClose && d == 0 && b[i] == ']':
e = i
case state == expectListClose && d == 0 && b[i] == ']':
e = i
case state == expectValue && b[i] == '{':
state = expectObjClose
s = i
d++
case state == expectValue && b[i] == '{':
state = expectObjClose
s = i
d++
case state == expectObjClose && d == 0 && b[i] == '}':
e = i
case state == expectObjClose && d == 0 && b[i] == '}':
e = i
case state == expectValue && (b[i] >= '0' && b[i] <= '9'):
state = expectNumClose
s = i
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 == 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 == 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
}
case state == expectBoolClose && (b[i] == 'e' || b[i] == 'E'):
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
}
state = expectKey
e = 0
}
}