Fix bugs with escape char handling
This commit is contained in:
parent
01e488b69d
commit
d96eaf14f4
|
@ -28,12 +28,19 @@ func Filter(w *bytes.Buffer, b []byte, keys []string) error {
|
|||
var k []byte
|
||||
state := expectKey
|
||||
instr := false
|
||||
slash := 0
|
||||
|
||||
for i := 0; i < len(b); i++ {
|
||||
if state == expectObjClose || state == expectListClose {
|
||||
if b[i-1] != '\\' && b[i] == '"' {
|
||||
if instr && b[i] == '\\' {
|
||||
slash++
|
||||
continue
|
||||
}
|
||||
|
||||
if b[i] == '"' && (slash%2 == 0) {
|
||||
instr = !instr
|
||||
}
|
||||
|
||||
if state == expectObjClose || state == expectListClose {
|
||||
if !instr {
|
||||
switch b[i] {
|
||||
case '{', '[':
|
||||
|
@ -70,7 +77,7 @@ func Filter(w *bytes.Buffer, b []byte, keys []string) error {
|
|||
state = expectKeyClose
|
||||
s = i
|
||||
|
||||
case state == expectKeyClose && (b[i-1] != '\\' && b[i] == '"'):
|
||||
case state == expectKeyClose && (b[i] == '"' && (slash%2 == 0)):
|
||||
state = expectColon
|
||||
k = b[(s + 1):i]
|
||||
|
||||
|
@ -80,7 +87,7 @@ func Filter(w *bytes.Buffer, b []byte, keys []string) error {
|
|||
case state == expectValue && b[i] == '"':
|
||||
state = expectString
|
||||
|
||||
case state == expectString && (b[i-1] != '\\' && b[i] == '"'):
|
||||
case state == expectString && (b[i] == '"' && (slash%2 == 0)):
|
||||
e = i
|
||||
|
||||
case state == expectValue && b[i] == '[':
|
||||
|
|
17
jsn/get.go
17
jsn/get.go
|
@ -52,12 +52,19 @@ func Get(b []byte, keys [][]byte) []Field {
|
|||
|
||||
n := 0
|
||||
instr := false
|
||||
slash := 0
|
||||
|
||||
for i := 0; i < len(b); i++ {
|
||||
if state == expectObjClose || state == expectListClose {
|
||||
if b[i-1] != '\\' && b[i] == '"' {
|
||||
if instr && b[i] == '\\' {
|
||||
slash++
|
||||
continue
|
||||
}
|
||||
|
||||
if b[i] == '"' && (slash%2 == 0) {
|
||||
instr = !instr
|
||||
}
|
||||
|
||||
if state == expectObjClose || state == expectListClose {
|
||||
if !instr {
|
||||
switch b[i] {
|
||||
case '{', '[':
|
||||
|
@ -73,7 +80,7 @@ func Get(b []byte, keys [][]byte) []Field {
|
|||
state = expectKeyClose
|
||||
s = i
|
||||
|
||||
case state == expectKeyClose && (b[i-1] != '\\' && b[i] == '"'):
|
||||
case state == expectKeyClose && (b[i] == '"' && (slash%2 == 0)):
|
||||
state = expectColon
|
||||
k = b[(s + 1):i]
|
||||
|
||||
|
@ -84,7 +91,7 @@ func Get(b []byte, keys [][]byte) []Field {
|
|||
state = expectString
|
||||
s = i
|
||||
|
||||
case state == expectString && (b[i-1] != '\\' && b[i] == '"'):
|
||||
case state == expectString && (b[i] == '"' && (slash%2 == 0)):
|
||||
e = i
|
||||
|
||||
case state == expectValue && b[i] == '[':
|
||||
|
@ -155,6 +162,8 @@ func Get(b []byte, keys [][]byte) []Field {
|
|||
state = expectKey
|
||||
e = 0
|
||||
}
|
||||
|
||||
slash = 0
|
||||
}
|
||||
|
||||
return res[:n]
|
||||
|
|
|
@ -2,7 +2,9 @@ package jsn
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -163,7 +165,9 @@ var (
|
|||
input6 = `
|
||||
{"users" : [{"id" : 1, "email" : "vicram@gmail.com", "slug" : "vikram-rangnekar", "threads" : [], "threads_cursor" : null}, {"id" : 3, "email" : "marareilly@lang.name", "slug" : "raymundo-corwin", "threads" : [{"id" : 9, "title" : "Et alias et aut porro praesentium nam in voluptatem reiciendis quisquam perspiciatis inventore eos quia et et enim qui amet."}, {"id" : 25, "title" : "Ipsam quam nemo culpa tempore amet optio sit sed eligendi autem consequatur quaerat rem velit quibusdam quibusdam optio a voluptatem."}], "threads_cursor" : 25}], "users_cursor" : 3}`
|
||||
|
||||
input7, _ = ioutil.ReadFile("test.json")
|
||||
input7, _ = ioutil.ReadFile("test7.json")
|
||||
|
||||
input8, _ = ioutil.ReadFile("test8.json")
|
||||
)
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
|
@ -268,6 +272,23 @@ func TestGet3(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestGet4(t *testing.T) {
|
||||
exp := `"# \n\n@@@java\npackage main\n\nimport (\n \"net/http\"\n \"strings\"\n\n \"github.com/gin-gonic/gin\"\n)\n\nfunc main() {\n r := gin.Default()\n r.LoadHTMLGlob(\"templates/*\")\n\n r.GET(\"/\", handleIndex)\n r.GET(\"/to/:name\", handleIndex)\n r.Run()\n}\n\n// Hello is page data for the template\ntype Hello struct {\n Name string\n}\n\nfunc handleIndex(c *gin.Context) {\n name := c.Param(\"name\")\n if name != \"\" {\n name = strings.TrimPrefix(c.Param(\"name\"), \"/\")\n }\n c.HTML(http.StatusOK, \"hellofly.tmpl\", gin.H{\"Name\": name})\n}\n@@@\n\n\\"`
|
||||
|
||||
exp = strings.ReplaceAll(exp, "@", "`")
|
||||
|
||||
values := Get(input8, [][]byte{[]byte("body")})
|
||||
|
||||
if string(values[0].Key) != "body" {
|
||||
t.Fatal("unexpected key")
|
||||
}
|
||||
|
||||
if string(values[0].Value) != exp {
|
||||
fmt.Println(string(values[0].Value))
|
||||
t.Fatal("unexpected value")
|
||||
}
|
||||
}
|
||||
|
||||
func TestValue(t *testing.T) {
|
||||
v1 := []byte("12345")
|
||||
if !bytes.Equal(Value(v1), v1) {
|
||||
|
|
16
jsn/keys.go
16
jsn/keys.go
|
@ -11,12 +11,19 @@ func Keys(b []byte) [][]byte {
|
|||
st := NewStack()
|
||||
ae := 0
|
||||
instr := false
|
||||
slash := 0
|
||||
|
||||
for i := 0; i < len(b); i++ {
|
||||
if state == expectObjClose || state == expectListClose {
|
||||
if b[i-1] != '\\' && b[i] == '"' {
|
||||
if instr && b[i] == '\\' {
|
||||
slash++
|
||||
continue
|
||||
}
|
||||
|
||||
if b[i] == '"' && (slash%2 == 0) {
|
||||
instr = !instr
|
||||
}
|
||||
|
||||
if state == expectObjClose || state == expectListClose {
|
||||
if !instr {
|
||||
switch b[i] {
|
||||
case '{', '[':
|
||||
|
@ -52,7 +59,7 @@ func Keys(b []byte) [][]byte {
|
|||
state = expectKeyClose
|
||||
s = i
|
||||
|
||||
case state == expectKeyClose && (b[i-1] != '\\' && b[i] == '"'):
|
||||
case state == expectKeyClose && (b[i] == '"' && (slash%2 == 0)):
|
||||
state = expectColon
|
||||
k = b[(s + 1):i]
|
||||
|
||||
|
@ -63,7 +70,7 @@ func Keys(b []byte) [][]byte {
|
|||
state = expectString
|
||||
s = i
|
||||
|
||||
case state == expectString && (b[i-1] != '\\' && b[i] == '"'):
|
||||
case state == expectString && (b[i] == '"' && (slash%2 == 0)):
|
||||
e = i
|
||||
|
||||
case state == expectValue && b[i] == '{':
|
||||
|
@ -135,6 +142,7 @@ func Keys(b []byte) [][]byte {
|
|||
e = 0
|
||||
}
|
||||
|
||||
slash = 0
|
||||
}
|
||||
|
||||
return res
|
||||
|
|
|
@ -12,6 +12,11 @@ func Replace(w *bytes.Buffer, b []byte, from, to []Field) error {
|
|||
return errors.New("'from' and 'to' must be of the same length")
|
||||
}
|
||||
|
||||
if len(from) == 0 || len(to) == 0 {
|
||||
_, err := w.Write(b)
|
||||
return err
|
||||
}
|
||||
|
||||
h := xxhash.New()
|
||||
tmap := make(map[uint64]int, len(from))
|
||||
|
||||
|
@ -33,17 +38,24 @@ func Replace(w *bytes.Buffer, b []byte, from, to []Field) error {
|
|||
ws, we := -1, len(b)
|
||||
|
||||
instr := false
|
||||
slash := 0
|
||||
|
||||
for i := 0; i < len(b); i++ {
|
||||
if instr && b[i] == '\\' {
|
||||
slash++
|
||||
continue
|
||||
}
|
||||
|
||||
// skip any left padding whitespace
|
||||
if ws == -1 && (b[i] == '{' || b[i] == '[') {
|
||||
ws = i
|
||||
}
|
||||
|
||||
if state == expectObjClose || state == expectListClose {
|
||||
if b[i-1] != '\\' && b[i] == '"' {
|
||||
if b[i] == '"' && (slash%2 == 0) {
|
||||
instr = !instr
|
||||
}
|
||||
|
||||
if state == expectObjClose || state == expectListClose {
|
||||
if !instr {
|
||||
switch b[i] {
|
||||
case '{', '[':
|
||||
|
@ -59,7 +71,7 @@ func Replace(w *bytes.Buffer, b []byte, from, to []Field) error {
|
|||
state = expectKeyClose
|
||||
s = i
|
||||
|
||||
case state == expectKeyClose && (b[i-1] != '\\' && b[i] == '"'):
|
||||
case state == expectKeyClose && (b[i] == '"' && (slash%2 == 0)):
|
||||
state = expectColon
|
||||
if _, err := h.Write(b[(s + 1):i]); err != nil {
|
||||
return err
|
||||
|
@ -73,7 +85,7 @@ func Replace(w *bytes.Buffer, b []byte, from, to []Field) error {
|
|||
state = expectString
|
||||
s = i
|
||||
|
||||
case state == expectString && (b[i-1] != '\\' && b[i] == '"'):
|
||||
case state == expectString && (b[i] == '"' && (slash%2 == 0)):
|
||||
e = i
|
||||
|
||||
case state == expectValue && b[i] == '[':
|
||||
|
@ -167,6 +179,8 @@ func Replace(w *bytes.Buffer, b []byte, from, to []Field) error {
|
|||
e = 0
|
||||
d = 0
|
||||
}
|
||||
|
||||
slash = 0
|
||||
}
|
||||
|
||||
if ws == -1 || (ws == 0 && we == len(b)) {
|
||||
|
|
17
jsn/strip.go
17
jsn/strip.go
|
@ -12,12 +12,19 @@ func Strip(b []byte, path [][]byte) []byte {
|
|||
pm := false
|
||||
state := expectKey
|
||||
instr := false
|
||||
slash := 0
|
||||
|
||||
for i := 0; i < len(b); i++ {
|
||||
if state == expectObjClose || state == expectListClose {
|
||||
if b[i-1] != '\\' && b[i] == '"' {
|
||||
if instr && b[i] == '\\' {
|
||||
slash++
|
||||
continue
|
||||
}
|
||||
|
||||
if b[i] == '"' && (slash%2 == 0) {
|
||||
instr = !instr
|
||||
}
|
||||
|
||||
if state == expectObjClose || state == expectListClose {
|
||||
if !instr {
|
||||
switch b[i] {
|
||||
case '{', '[':
|
||||
|
@ -33,7 +40,7 @@ func Strip(b []byte, path [][]byte) []byte {
|
|||
state = expectKeyClose
|
||||
s = i
|
||||
|
||||
case state == expectKeyClose && (b[i-1] != '\\' && b[i] == '"'):
|
||||
case state == expectKeyClose && (b[i] == '"' && (slash%2 == 0)):
|
||||
state = expectColon
|
||||
if pi == len(path) {
|
||||
pi = 0
|
||||
|
@ -50,7 +57,7 @@ func Strip(b []byte, path [][]byte) []byte {
|
|||
state = expectString
|
||||
s = i
|
||||
|
||||
case state == expectString && (b[i-1] != '\\' && b[i] == '"'):
|
||||
case state == expectString && (b[i] == '"' && (slash%2 == 0)):
|
||||
e = i
|
||||
|
||||
case state == expectValue && b[i] == '[':
|
||||
|
@ -107,6 +114,8 @@ func Strip(b []byte, path [][]byte) []byte {
|
|||
state = expectKey
|
||||
e = 0
|
||||
}
|
||||
|
||||
slash = 0
|
||||
}
|
||||
|
||||
return ob
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"data": {
|
||||
"slug": "javapackage-mainimport-nethttp-strings-githubcomgi-2786",
|
||||
"published": true,
|
||||
"body": "# \n\n```java\npackage main\n\nimport (\n \"net/http\"\n \"strings\"\n\n \"github.com/gin-gonic/gin\"\n)\n\nfunc main() {\n r := gin.Default()\n r.LoadHTMLGlob(\"templates/*\")\n\n r.GET(\"/\", handleIndex)\n r.GET(\"/to/:name\", handleIndex)\n r.Run()\n}\n\n// Hello is page data for the template\ntype Hello struct {\n Name string\n}\n\nfunc handleIndex(c *gin.Context) {\n name := c.Param(\"name\")\n if name != \"\" {\n name = strings.TrimPrefix(c.Param(\"name\"), \"/\")\n }\n c.HTML(http.StatusOK, \"hellofly.tmpl\", gin.H{\"Name\": name})\n}\n```\n\n\\"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue