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,36 +62,14 @@ 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)]
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] == ':': case state == expectColon && b[i] == ':':
state = expectValue state = expectValue
@ -115,14 +111,20 @@ func Filter(w *bytes.Buffer, b []byte, keys []string) error {
} }
if e != 0 { if e != 0 {
if kf { state = expectKey
cb := b[s:(e + 1)]
e = 0
if !kf {
continue
}
if field != 0 { if field != 0 {
if err := w.WriteByte(','); err != nil { if err := w.WriteByte(','); err != nil {
return err return err
} }
} }
cb := b[s:(e + 1)]
sk := 0 sk := 0
for i := 0; i < len(cb); i++ { for i := 0; i < len(cb); i++ {
if cb[i] == '\n' || cb[i] == '\t' { if cb[i] == '\n' || cb[i] == '\t' {
@ -138,21 +140,20 @@ func Filter(w *bytes.Buffer, b []byte, keys []string) error {
} else { } else {
_, err = w.Write(cb) _, err = w.Write(cb)
} }
if err != nil { if err != nil {
return err return err
} }
field++ field++
} }
state = expectKey
break
}
}
} }
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,31 +34,15 @@ 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++ {
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 { if state == expectObjClose || state == expectListClose {
switch b[i] { switch b[i] {
case '{', '[': case '{', '[':
@ -69,6 +53,15 @@ func Get(b []byte, keys [][]byte) []Field {
} }
switch { 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] == ':': case state == expectColon && b[i] == ':':
state = expectValue state = expectValue
@ -117,21 +110,17 @@ func Get(b []byte, keys [][]byte) []Field {
} }
if e != 0 { if e != 0 {
e++
if kf { if kf {
if len(res) == cap(res) { if len(res) == cap(res) {
r := make([]Field, 0, (len(res) + l)) r := make([]Field, 0, (len(res) * 2))
copy(r, res) copy(r, res)
res = r res = r
} }
res = append(res, Field{k, b[s:(e + 1)]})
res = append(res, Field{k, b[s:e]})
} }
state = expectKey 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") 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,36 +27,18 @@ func Replace(w *bytes.Buffer, b []byte, from, to []Field) error {
tmap[h2] = i 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++ { for i := 0; i < len(b); i++ {
switch { // skip any left padding whitespace
case ws == 0 && b[i] == '{' || b[i] == '[': if ws == 0 && (b[i] == '{' || b[i] == '[') {
ws = 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 { if state == expectObjClose || state == expectListClose {
switch b[i] { switch b[i] {
case '{', '[': case '{', '[':
@ -73,6 +49,18 @@ func Replace(w *bytes.Buffer, b []byte, from, to []Field) error {
} }
switch { 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] == ':': case state == expectColon && b[i] == ':':
state = expectValue state = expectValue
@ -120,13 +108,15 @@ func Replace(w *bytes.Buffer, b []byte, from, to []Field) error {
if e != 0 { if e != 0 {
e++ e++
h2 := sha1.Sum(b[s:e]) h2 := sha1.Sum(b[s:e])
replace := false
if n, ok1 := fmap[h2]; ok1 && n == fi { if n, ok1 := fmap[h2]; ok1 && n == fi {
ti, ok2 := tmap[h2] ti, ok2 := tmap[h2]
if ok2 { if ok2 {
if _, err := w.Write(b[ws:we]); err != nil { if _, err := w.Write(b[ws:(we + 1)]); err != nil {
return err return err
} }
if _, err := w.Write(to[ti].Key); err != nil { 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 { if _, err := w.Write(to[ti].Value); err != nil {
return err return err
} }
replace = true
ws = e 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 i = s - 1
} }
state = expectKey state = expectKey
we = len(b) we = len(b)
fi = -1 fi = -1
break e = 0
} d = 0
} }
} }

View File

@ -9,41 +9,15 @@ 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++ {
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 { if state == expectObjClose || state == expectListClose {
switch b[i] { switch b[i] {
case '{', '[': case '{', '[':
@ -54,6 +28,20 @@ func Strip(b []byte, path []string) []byte {
} }
switch { 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] == ':': case state == expectColon && b[i] == ':':
state = expectValue state = expectValue
@ -99,18 +87,18 @@ func Strip(b []byte, path []string) []byte {
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 state = expectKey
break e = 0
}
} }
} }