@@ -36,6 +36,28 @@ func tokenEnd(data []byte) int {
36
36
return len (data )
37
37
}
38
38
39
+ func findLastTokenEnd (data []byte , token byte ) int {
40
+ for i := len (data ) - 1 ; i >= 0 ; i -- {
41
+ switch data [i ] {
42
+ case token :
43
+ return i
44
+ }
45
+ }
46
+
47
+ return 0
48
+ }
49
+
50
+ func lastTokenEnd (data []byte ) int {
51
+ for i := len (data ) - 1 ; i >= 0 ; i -- {
52
+ switch data [i ] {
53
+ case ' ' , '\n' , '\r' , '\t' , ',' , '}' , ']' :
54
+ return i
55
+ }
56
+ }
57
+
58
+ return 0
59
+ }
60
+
39
61
// Find position of next character which is not whitespace
40
62
func nextToken (data []byte ) int {
41
63
for i , c := range data {
@@ -173,7 +195,7 @@ func searchKeys(data []byte, keys ...string) int {
173
195
keyUnesc = ku
174
196
}
175
197
176
- if equalStr (& keyUnesc , keys [level - 1 ]) {
198
+ if equalStr (keyUnesc , keys [level - 1 ]) {
177
199
keyLevel ++
178
200
// If we found all keys in path
179
201
if keyLevel == lk {
@@ -200,14 +222,15 @@ func searchKeys(data []byte, keys ...string) int {
200
222
var curIdx int
201
223
var valueFound []byte
202
224
var valueOffset int
225
+ var curI = i
203
226
ArrayEach (data [i :], func (value []byte , dataType ValueType , offset int , err error ) {
204
227
if curIdx == aIdx {
205
228
valueFound = value
206
229
valueOffset = offset
207
- if dataType == String {
230
+ if dataType == String {
208
231
valueOffset = valueOffset - 2
209
- valueFound = data [i + valueOffset : i + valueOffset + len (value ) + 2 ]
210
- }
232
+ valueFound = data [curI + valueOffset : curI + valueOffset + len (value )+ 2 ]
233
+ }
211
234
}
212
235
curIdx += 1
213
236
})
@@ -314,13 +337,13 @@ func EachKey(data []byte, cb func(int, []byte, ValueType, error), paths ...[]str
314
337
315
338
if maxPath >= level {
316
339
if level < 1 {
317
- cb (- 1 , [] byte {} , Unknown , MalformedJsonError )
340
+ cb (- 1 , nil , Unknown , MalformedJsonError )
318
341
return - 1
319
342
}
320
- pathsBuf [level - 1 ] = bytesToString (& keyUnesc )
321
343
344
+ pathsBuf [level - 1 ] = bytesToString (keyUnesc )
322
345
for pi , p := range paths {
323
- if len (p ) != level || pathFlags & bitwiseFlags [pi + 1 ] != 0 || ! equalStr (& keyUnesc , p [level - 1 ]) || ! sameTree (p , pathsBuf [:level ]) {
346
+ if len (p ) != level || pathFlags & bitwiseFlags [pi + 1 ] != 0 || ! equalStr (keyUnesc , p [level - 1 ]) || ! sameTree (p , pathsBuf [:level ]) {
324
347
continue
325
348
}
326
349
@@ -338,9 +361,12 @@ func EachKey(data []byte, cb func(int, []byte, ValueType, error), paths ...[]str
338
361
}
339
362
340
363
if pathsMatched == len (paths ) {
341
- return i
364
+ break
342
365
}
343
366
}
367
+ if pathsMatched == len (paths ) {
368
+ return i
369
+ }
344
370
}
345
371
346
372
if match == - 1 {
@@ -369,7 +395,7 @@ func EachKey(data []byte, cb func(int, []byte, ValueType, error), paths ...[]str
369
395
var pIdxFlags int64
370
396
371
397
if level < 0 {
372
- cb (- 1 , [] byte {} , Unknown , MalformedJsonError )
398
+ cb (- 1 , nil , Unknown , MalformedJsonError )
373
399
return - 1
374
400
}
375
401
@@ -501,6 +527,68 @@ func createInsertComponent(keys []string, setValue []byte, comma, object bool) [
501
527
502
528
/*
503
529
530
+ Del - Receives existing data structure, path to delete.
531
+
532
+ Returns:
533
+ `data` - return modified data
534
+
535
+ */
536
+ func Del (data []byte , keys ... string ) []byte {
537
+ lk := len (keys )
538
+ if lk == 0 {
539
+ return data [:0 ]
540
+ }
541
+
542
+ array := false
543
+ if len (keys [lk - 1 ]) > 0 && string (keys [lk - 1 ][0 ]) == "[" {
544
+ array = true
545
+ }
546
+
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 ++
568
+ }
569
+ endOffset = endOffset + lastTokEnd
570
+ } else {
571
+ tokEnd := tokenEnd (data [endOffset :])
572
+ tokStart := findLastTokenEnd (data [:startOffset ], "," [0 ])
573
+
574
+ if data [endOffset + tokEnd ] == "," [0 ] {
575
+ endOffset += tokEnd + 1
576
+ } else if data [endOffset + tokEnd ] == "]" [0 ] && data [tokStart ] == "," [0 ] {
577
+ startOffset = tokStart
578
+ }
579
+ }
580
+
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
584
+ }
585
+ data = data [:len (data )- endOffset + startOffset ]
586
+ }
587
+ return data
588
+ }
589
+
590
+ /*
591
+
504
592
Set - Receives existing data structure, path to set, and data to set at that key.
505
593
506
594
Returns:
@@ -518,7 +606,7 @@ func Set(data []byte, setValue []byte, keys ...string) (value []byte, err error)
518
606
if err != nil {
519
607
if err != KeyPathNotFoundError {
520
608
// problem parsing the data
521
- return [] byte {} , err
609
+ return nil , err
522
610
}
523
611
// full path doesnt exist
524
612
// does any subpath exist?
@@ -553,10 +641,10 @@ func Set(data []byte, setValue []byte, keys ...string) (value []byte, err error)
553
641
depthOffset := endOffset
554
642
if depth != 0 {
555
643
// if subpath is a non-empty object, add to it
556
- if data [startOffset ] == '{' && data [startOffset + 1 + nextToken (data [startOffset + 1 :])]!= '}' {
644
+ if data [startOffset ] == '{' && data [startOffset + 1 + nextToken (data [startOffset + 1 :])] != '}' {
557
645
depthOffset --
558
646
startOffset = depthOffset
559
- // otherwise, over-write it with a new object
647
+ // otherwise, over-write it with a new object
560
648
} else {
561
649
comma = false
562
650
object = true
@@ -589,15 +677,15 @@ func getType(data []byte, offset int) ([]byte, ValueType, int, error) {
589
677
if idx , _ := stringEnd (data [offset + 1 :]); idx != - 1 {
590
678
endOffset += idx + 1
591
679
} else {
592
- return [] byte {} , dataType , offset , MalformedStringError
680
+ return nil , dataType , offset , MalformedStringError
593
681
}
594
682
} else if data [offset ] == '[' { // if array value
595
683
dataType = Array
596
684
// break label, for stopping nested loops
597
685
endOffset = blockEnd (data [offset :], '[' , ']' )
598
686
599
687
if endOffset == - 1 {
600
- return [] byte {} , dataType , offset , MalformedArrayError
688
+ return nil , dataType , offset , MalformedArrayError
601
689
}
602
690
603
691
endOffset += offset
@@ -607,7 +695,7 @@ func getType(data []byte, offset int) ([]byte, ValueType, int, error) {
607
695
endOffset = blockEnd (data [offset :], '{' , '}' )
608
696
609
697
if endOffset == - 1 {
610
- return [] byte {} , dataType , offset , MalformedObjectError
698
+ return nil , dataType , offset , MalformedObjectError
611
699
}
612
700
613
701
endOffset += offset
@@ -665,14 +753,14 @@ func Get(data []byte, keys ...string) (value []byte, dataType ValueType, offset
665
753
func internalGet (data []byte , keys ... string ) (value []byte , dataType ValueType , offset , endOffset int , err error ) {
666
754
if len (keys ) > 0 {
667
755
if offset = searchKeys (data , keys ... ); offset == - 1 {
668
- return [] byte {} , NotExist , - 1 , - 1 , KeyPathNotFoundError
756
+ return nil , NotExist , - 1 , - 1 , KeyPathNotFoundError
669
757
}
670
758
}
671
759
672
760
// Go to closest value
673
761
nO := nextToken (data [offset :])
674
762
if nO == - 1 {
675
- return [] byte {} , NotExist , offset , - 1 , MalformedJsonError
763
+ return nil , NotExist , offset , - 1 , MalformedJsonError
676
764
}
677
765
678
766
offset += nO
@@ -884,7 +972,7 @@ func GetUnsafeString(data []byte, keys ...string) (val string, err error) {
884
972
return "" , e
885
973
}
886
974
887
- return bytesToString (& v ), nil
975
+ return bytesToString (v ), nil
888
976
}
889
977
890
978
// GetString returns the value retrieved by `Get`, cast to a string if possible, trying to properly handle escape and utf8 symbols
@@ -982,7 +1070,7 @@ func ParseString(b []byte) (string, error) {
982
1070
983
1071
// ParseNumber parses a Number ValueType into a Go float64
984
1072
func ParseFloat (b []byte ) (float64 , error ) {
985
- if v , err := parseFloat (& b ); err != nil {
1073
+ if v , err := parseFloat (b ); err != nil {
986
1074
return 0 , MalformedValueError
987
1075
} else {
988
1076
return v , nil
0 commit comments