@@ -36,21 +36,75 @@ func tokenEnd(data []byte) int {
36
36
return len (data )
37
37
}
38
38
39
- func findLastTokenEnd (data []byte , token byte ) int {
39
+ func findTokenStart (data []byte , token byte ) int {
40
40
for i := len (data ) - 1 ; i >= 0 ; i -- {
41
41
switch data [i ] {
42
42
case token :
43
43
return i
44
+ case '[' , '{' :
45
+ return 0
44
46
}
45
47
}
46
48
47
49
return 0
48
50
}
49
51
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 {
51
105
for i := len (data ) - 1 ; i >= 0 ; i -- {
52
106
switch data [i ] {
53
- case ' ' , ' \n' , '\r' , '\t' , ',' , '} ' , '] ' :
107
+ case '\n' , '\r' , '\t' , ',' , '{ ' , '[ ' :
54
108
return i
55
109
}
56
110
}
@@ -195,7 +249,7 @@ func searchKeys(data []byte, keys ...string) int {
195
249
keyUnesc = ku
196
250
}
197
251
198
- if equalStr (keyUnesc , keys [level - 1 ]) {
252
+ if equalStr (& keyUnesc , keys [level - 1 ]) {
199
253
keyLevel ++
200
254
// If we found all keys in path
201
255
if keyLevel == lk {
@@ -341,9 +395,9 @@ func EachKey(data []byte, cb func(int, []byte, ValueType, error), paths ...[]str
341
395
return - 1
342
396
}
343
397
344
- pathsBuf [level - 1 ] = bytesToString (keyUnesc )
398
+ pathsBuf [level - 1 ] = bytesToString (& keyUnesc )
345
399
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 ]) {
347
401
continue
348
402
}
349
403
@@ -544,46 +598,52 @@ func Del(data []byte, keys ...string) []byte {
544
598
array = true
545
599
}
546
600
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
568
610
}
569
- endOffset = endOffset + lastTokEnd
570
- } else {
571
- tokEnd := tokenEnd (data [endOffset :])
572
- tokStart := findLastTokenEnd (data [:startOffset ], "," [0 ])
611
+ }
573
612
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
579
628
}
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 ])
580
638
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
584
643
}
585
- data = data [:len (data )- endOffset + startOffset ]
586
644
}
645
+
646
+ data = append (data [:keyOffset ], data [endOffset :]... )
587
647
return data
588
648
}
589
649
@@ -972,7 +1032,7 @@ func GetUnsafeString(data []byte, keys ...string) (val string, err error) {
972
1032
return "" , e
973
1033
}
974
1034
975
- return bytesToString (v ), nil
1035
+ return bytesToString (& v ), nil
976
1036
}
977
1037
978
1038
// 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) {
1070
1130
1071
1131
// ParseNumber parses a Number ValueType into a Go float64
1072
1132
func ParseFloat (b []byte ) (float64 , error ) {
1073
- if v , err := parseFloat (b ); err != nil {
1133
+ if v , err := parseFloat (& b ); err != nil {
1074
1134
return 0 , MalformedValueError
1075
1135
} else {
1076
1136
return v , nil
0 commit comments