2019-05-13 01:27:26 +02:00
|
|
|
package jsn
|
2019-05-09 01:03:18 +02:00
|
|
|
|
|
|
|
import (
|
2019-05-12 07:36:52 +02:00
|
|
|
"github.com/cespare/xxhash/v2"
|
2019-05-09 01:03:18 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
expectKey int = iota
|
|
|
|
expectKeyClose
|
|
|
|
expectColon
|
|
|
|
expectValue
|
|
|
|
expectString
|
2019-05-13 06:05:08 +02:00
|
|
|
expectNull
|
2019-05-09 01:03:18 +02:00
|
|
|
expectListClose
|
|
|
|
expectObjClose
|
|
|
|
expectBoolClose
|
|
|
|
expectNumClose
|
|
|
|
)
|
|
|
|
|
|
|
|
type Field struct {
|
|
|
|
Key []byte
|
|
|
|
Value []byte
|
|
|
|
}
|
|
|
|
|
2019-05-12 07:36:52 +02:00
|
|
|
func Value(b []byte) []byte {
|
|
|
|
e := (len(b) - 1)
|
|
|
|
switch {
|
|
|
|
case b[0] == '"' && b[e] == '"':
|
|
|
|
return b[1:(len(b) - 1)]
|
|
|
|
case b[0] == '[' && b[e] == ']':
|
|
|
|
return nil
|
|
|
|
case b[0] == '{' && b[e] == '}':
|
|
|
|
return nil
|
|
|
|
default:
|
|
|
|
return b
|
|
|
|
}
|
|
|
|
}
|
2019-05-09 01:03:18 +02:00
|
|
|
|
2019-05-12 07:36:52 +02:00
|
|
|
func Get(b []byte, keys [][]byte) []Field {
|
|
|
|
kmap := make(map[uint64]struct{}, len(keys))
|
2019-05-09 01:03:18 +02:00
|
|
|
|
2019-05-12 07:36:52 +02:00
|
|
|
for i := range keys {
|
|
|
|
kmap[xxhash.Sum64(keys[i])] = struct{}{}
|
2019-05-09 01:03:18 +02:00
|
|
|
}
|
|
|
|
|
2019-09-05 06:09:56 +02:00
|
|
|
res := make([]Field, 0, 20)
|
2019-05-09 05:52:04 +02:00
|
|
|
|
|
|
|
s, e, d := 0, 0, 0
|
|
|
|
|
|
|
|
var k []byte
|
2019-05-12 07:36:52 +02:00
|
|
|
state := expectKey
|
2019-05-09 01:03:18 +02:00
|
|
|
|
2019-05-12 07:36:52 +02:00
|
|
|
n := 0
|
2020-02-23 21:29:50 +01:00
|
|
|
instr := false
|
|
|
|
|
2019-05-09 01:03:18 +02:00
|
|
|
for i := 0; i < len(b); i++ {
|
2019-05-09 05:52:04 +02:00
|
|
|
if state == expectObjClose || state == expectListClose {
|
2020-02-23 21:29:50 +01:00
|
|
|
if b[i-1] != '\\' && b[i] == '"' {
|
|
|
|
instr = !instr
|
|
|
|
}
|
|
|
|
if !instr {
|
|
|
|
switch b[i] {
|
|
|
|
case '{', '[':
|
|
|
|
d++
|
|
|
|
case '}', ']':
|
|
|
|
d--
|
|
|
|
}
|
2019-05-09 05:52:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-09 01:03:18 +02:00
|
|
|
switch {
|
|
|
|
case state == expectKey && b[i] == '"':
|
|
|
|
state = expectKeyClose
|
2019-05-09 05:52:04 +02:00
|
|
|
s = i
|
2019-05-09 01:03:18 +02:00
|
|
|
|
2020-01-15 05:16:55 +01:00
|
|
|
case state == expectKeyClose && (b[i-1] != '\\' && b[i] == '"'):
|
2019-05-09 01:03:18 +02:00
|
|
|
state = expectColon
|
2019-05-09 05:52:04 +02:00
|
|
|
k = b[(s + 1):i]
|
|
|
|
|
|
|
|
case state == expectColon && b[i] == ':':
|
|
|
|
state = expectValue
|
|
|
|
|
|
|
|
case state == expectValue && b[i] == '"':
|
|
|
|
state = expectString
|
|
|
|
s = i
|
|
|
|
|
2020-01-15 05:16:55 +01:00
|
|
|
case state == expectString && (b[i-1] != '\\' && b[i] == '"'):
|
2019-05-09 05:52:04 +02:00
|
|
|
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] != '-')):
|
2019-10-26 09:02:05 +02:00
|
|
|
e = i - 1
|
2019-05-09 05:52:04 +02:00
|
|
|
|
|
|
|
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
|
2019-05-13 06:05:08 +02:00
|
|
|
|
|
|
|
case state == expectValue && b[i] == 'n':
|
|
|
|
state = expectNull
|
2020-02-10 07:45:37 +01:00
|
|
|
s = i
|
2019-05-13 06:05:08 +02:00
|
|
|
|
2020-02-10 07:45:37 +01:00
|
|
|
case state == expectNull && (b[i-1] == 'l' && b[i] == 'l'):
|
2019-05-13 06:05:08 +02:00
|
|
|
e = i
|
2019-05-09 01:03:18 +02:00
|
|
|
}
|
|
|
|
|
2019-05-09 05:52:04 +02:00
|
|
|
if e != 0 {
|
2019-05-12 07:36:52 +02:00
|
|
|
_, ok := kmap[xxhash.Sum64(k)]
|
|
|
|
|
|
|
|
if ok {
|
2019-09-05 06:09:56 +02:00
|
|
|
res = append(res, Field{k, b[s:(e + 1)]})
|
2019-05-12 07:36:52 +02:00
|
|
|
n++
|
2019-05-09 01:03:18 +02:00
|
|
|
}
|
|
|
|
|
2020-01-19 09:12:51 +01:00
|
|
|
if state == expectListClose {
|
|
|
|
loop:
|
|
|
|
for j := i + 1; j < len(b); j++ {
|
|
|
|
switch b[j] {
|
|
|
|
case ' ', '\t', '\n':
|
|
|
|
continue
|
|
|
|
case '{':
|
|
|
|
break loop
|
|
|
|
}
|
|
|
|
i = e
|
|
|
|
break loop
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-09 05:52:04 +02:00
|
|
|
state = expectKey
|
|
|
|
e = 0
|
2019-05-09 01:03:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-12 07:36:52 +02:00
|
|
|
return res[:n]
|
2019-05-09 01:03:18 +02:00
|
|
|
}
|