@@ -36,21 +36,75 @@ func tokenEnd(data []byte) int {
3636 return len (data )
3737}
3838
39- func findLastTokenEnd (data []byte , token byte ) int {
39+ func findTokenStart (data []byte , token byte ) int {
4040 for i := len (data ) - 1 ; i >= 0 ; i -- {
4141 switch data [i ] {
4242 case token :
4343 return i
44+ case '[' , '{' :
45+ return 0
4446 }
4547 }
4648
4749 return 0
4850}
4951
50- func lastTokenEnd (data []byte ) int {
52+ func findKeyStart (data []byte , key string ) (int , error ) {
53+ i := 0
54+ ln := len (data )
55+ var stackbuf [unescapeStackBufSize ]byte // stack-allocated array for allocation-free unescaping of small strings
56+
57+ if ku , err := Unescape (StringToBytes (key ), stackbuf [:]); err == nil {
58+ key = bytesToString (& ku )
59+ }
60+
61+ for i < ln {
62+ switch data [i ] {
63+ case '"' :
64+ i ++
65+ keyBegin := i
66+
67+ strEnd , keyEscaped := stringEnd (data [i :])
68+ if strEnd == - 1 {
69+ break
70+ }
71+ i += strEnd
72+ keyEnd := i - 1
73+
74+ valueOffset := nextToken (data [i :])
75+ if valueOffset == - 1 {
76+ break
77+ }
78+
79+ i += valueOffset
80+
81+ // if string is a key, and key level match
82+ k := data [keyBegin :keyEnd ]
83+ // for unescape: if there are no escape sequences, this is cheap; if there are, it is a
84+ // bit more expensive, but causes no allocations unless len(key) > unescapeStackBufSize
85+ if keyEscaped {
86+ if ku , err := Unescape (k , stackbuf [:]); err != nil {
87+ break
88+ } else {
89+ k = ku
90+ }
91+ }
92+
93+ if data [i ] == ':' && len (key ) == len (k ) && bytesToString (& k ) == key {
94+ return keyBegin - 1 , nil
95+ }
96+
97+ }
98+ i ++
99+ }
100+
101+ return - 1 , KeyPathNotFoundError
102+ }
103+
104+ func tokenStart (data []byte ) int {
51105 for i := len (data ) - 1 ; i >= 0 ; i -- {
52106 switch data [i ] {
53- case ' ' , ' \n' , '\r' , '\t' , ',' , '} ' , '] ' :
107+ case '\n' , '\r' , '\t' , ',' , '{ ' , '[ ' :
54108 return i
55109 }
56110 }
@@ -195,7 +249,7 @@ func searchKeys(data []byte, keys ...string) int {
195249 keyUnesc = ku
196250 }
197251
198- if equalStr (keyUnesc , keys [level - 1 ]) {
252+ if equalStr (& keyUnesc , keys [level - 1 ]) {
199253 keyLevel ++
200254 // If we found all keys in path
201255 if keyLevel == lk {
@@ -341,9 +395,9 @@ func EachKey(data []byte, cb func(int, []byte, ValueType, error), paths ...[]str
341395 return - 1
342396 }
343397
344- pathsBuf [level - 1 ] = bytesToString (keyUnesc )
398+ pathsBuf [level - 1 ] = bytesToString (& keyUnesc )
345399 for pi , p := range paths {
346- if len (p ) != level || pathFlags & bitwiseFlags [pi + 1 ] != 0 || ! equalStr (keyUnesc , p [level - 1 ]) || ! sameTree (p , pathsBuf [:level ]) {
400+ if len (p ) != level || pathFlags & bitwiseFlags [pi + 1 ] != 0 || ! equalStr (& keyUnesc , p [level - 1 ]) || ! sameTree (p , pathsBuf [:level ]) {
347401 continue
348402 }
349403
@@ -544,46 +598,52 @@ func Del(data []byte, keys ...string) []byte {
544598 array = true
545599 }
546600
547- _ , _ , startOffset , endOffset , err := internalGet (data , keys ... )
548- if err == nil {
549- if ! array {
550- lastTok := lastTokenEnd (data [:startOffset ])
551- keyOffset , _ := stringEnd (data [:lastTok ])
552- lastTokEnd := tokenEnd (data [endOffset :])
553-
554- if keyOffset == - 1 {
555- keyOffset = 0
556- } else {
557- keyOffset --
558- }
559- if lastTok != 0 {
560- startOffset = lastTok + keyOffset
561- }
562-
563- if lastTokEnd >= len (data [endOffset :])- 1 {
564- lastTokEnd = 0
565- startOffset = lastTok
566- } else {
567- lastTokEnd ++
601+ var startOffset , keyOffset int
602+ endOffset := len (data )
603+ var err error
604+ if ! array {
605+ if len (keys ) > 1 {
606+ _ , _ , startOffset , endOffset , err = internalGet (data , keys [:lk - 1 ]... )
607+ if err == KeyPathNotFoundError {
608+ // problem parsing the data
609+ return data
568610 }
569- endOffset = endOffset + lastTokEnd
570- } else {
571- tokEnd := tokenEnd (data [endOffset :])
572- tokStart := findLastTokenEnd (data [:startOffset ], "," [0 ])
611+ }
573612
574- if data [endOffset + tokEnd ] == "," [0 ] {
575- endOffset += tokEnd + 1
576- } else if data [endOffset + tokEnd ] == "]" [0 ] && data [tokStart ] == "," [0 ] {
577- startOffset = tokStart
578- }
613+ keyOffset , err = findKeyStart (data [startOffset :endOffset ], keys [lk - 1 ])
614+ if err == KeyPathNotFoundError {
615+ // problem parsing the data
616+ return data
617+ }
618+ keyOffset += startOffset
619+ _ , _ , _ , subEndOffset , _ := internalGet (data [startOffset :endOffset ], keys [lk - 1 ])
620+ endOffset = startOffset + subEndOffset
621+ tokEnd := tokenEnd (data [endOffset :])
622+ tokStart := findTokenStart (data [:keyOffset ], "," [0 ])
623+
624+ if data [endOffset + tokEnd ] == "," [0 ] {
625+ endOffset += tokEnd + 1
626+ } else if data [endOffset + tokEnd ] == "}" [0 ] && data [tokStart ] == "," [0 ] {
627+ keyOffset = tokStart
579628 }
629+ } else {
630+ _ , _ , keyOffset , endOffset , err = internalGet (data , keys ... )
631+ if err == KeyPathNotFoundError {
632+ // problem parsing the data
633+ return data
634+ }
635+
636+ tokEnd := tokenEnd (data [endOffset :])
637+ tokStart := findTokenStart (data [:keyOffset ], "," [0 ])
580638
581- copy (data [startOffset :], data [endOffset :])
582- for k , n := len (data )- endOffset + startOffset , len (data ); k < n ; k ++ {
583- data [k ] = 0 // or the zero value of T
639+ if data [endOffset + tokEnd ] == "," [0 ] {
640+ endOffset += tokEnd + 1
641+ } else if data [endOffset + tokEnd ] == "]" [0 ] && data [tokStart ] == "," [0 ] {
642+ keyOffset = tokStart
584643 }
585- data = data [:len (data )- endOffset + startOffset ]
586644 }
645+
646+ data = append (data [:keyOffset ], data [endOffset :]... )
587647 return data
588648}
589649
@@ -972,7 +1032,7 @@ func GetUnsafeString(data []byte, keys ...string) (val string, err error) {
9721032 return "" , e
9731033 }
9741034
975- return bytesToString (v ), nil
1035+ return bytesToString (& v ), nil
9761036}
9771037
9781038// GetString returns the value retrieved by `Get`, cast to a string if possible, trying to properly handle escape and utf8 symbols
@@ -1070,7 +1130,7 @@ func ParseString(b []byte) (string, error) {
10701130
10711131// ParseNumber parses a Number ValueType into a Go float64
10721132func ParseFloat (b []byte ) (float64 , error ) {
1073- if v , err := parseFloat (b ); err != nil {
1133+ if v , err := parseFloat (& b ); err != nil {
10741134 return 0 , MalformedValueError
10751135 } else {
10761136 return v , nil
0 commit comments