Skip to content

Commit 3e35a05

Browse files
committed
- add delete
1 parent bb14bb6 commit 3e35a05

File tree

3 files changed

+117
-29
lines changed

3 files changed

+117
-29
lines changed

bytes_unsafe.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,16 @@ import (
1616
//
1717
// TODO: Remove hack after Go 1.7 release
1818
//
19-
func equalStr(b *[]byte, s string) bool {
20-
return *(*string)(unsafe.Pointer(b)) == s
19+
func equalStr(b []byte, s string) bool {
20+
return *(*string)(unsafe.Pointer(&b)) == s
2121
}
2222

23-
func parseFloat(b *[]byte) (float64, error) {
24-
return strconv.ParseFloat(*(*string)(unsafe.Pointer(b)), 64)
23+
func parseFloat(b []byte) (float64, error) {
24+
return strconv.ParseFloat(*(*string)(unsafe.Pointer(&b)), 64)
2525
}
2626

2727
// A hack until issue golang/go#2632 is fixed.
2828
// See: https://github.com/golang/go/issues/2632
29-
func bytesToString(b *[]byte) string {
30-
return *(*string)(unsafe.Pointer(b))
29+
func bytesToString(b []byte) string {
30+
return *(*string)(unsafe.Pointer(&b))
3131
}

bytes_unsafe_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func bytesEqualStrUnsafeSlower(abytes *[]byte, bstr string) bool {
2727
}
2828

2929
func TestEqual(t *testing.T) {
30-
if !equalStr(&[]byte{}, "") {
30+
if !equalStr([]byte{}, "") {
3131
t.Errorf(`equalStr("", ""): expected true, obtained false`)
3232
return
3333
}
@@ -37,11 +37,11 @@ func TestEqual(t *testing.T) {
3737
s1, s2 := longstr[:i]+"1", longstr[:i]+"2"
3838
b1 := []byte(s1)
3939

40-
if !equalStr(&b1, s1) {
40+
if !equalStr(b1, s1) {
4141
t.Errorf(`equalStr("a"*%d + "1", "a"*%d + "1"): expected true, obtained false`, i, i)
4242
break
4343
}
44-
if equalStr(&b1, s2) {
44+
if equalStr(b1, s2) {
4545
t.Errorf(`equalStr("a"*%d + "1", "a"*%d + "2"): expected false, obtained true`, i, i)
4646
break
4747
}
@@ -50,7 +50,7 @@ func TestEqual(t *testing.T) {
5050

5151
func BenchmarkEqualStr(b *testing.B) {
5252
for i := 0; i < b.N; i++ {
53-
equalStr(&benchmarkBytes, benchmarkString)
53+
equalStr(benchmarkBytes, benchmarkString)
5454
}
5555
}
5656

parser.go

Lines changed: 107 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,28 @@ func tokenEnd(data []byte) int {
3636
return len(data)
3737
}
3838

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+
3961
// Find position of next character which is not whitespace
4062
func nextToken(data []byte) int {
4163
for i, c := range data {
@@ -173,7 +195,7 @@ func searchKeys(data []byte, keys ...string) int {
173195
keyUnesc = ku
174196
}
175197

176-
if equalStr(&keyUnesc, keys[level-1]) {
198+
if equalStr(keyUnesc, keys[level-1]) {
177199
keyLevel++
178200
// If we found all keys in path
179201
if keyLevel == lk {
@@ -200,14 +222,15 @@ func searchKeys(data []byte, keys ...string) int {
200222
var curIdx int
201223
var valueFound []byte
202224
var valueOffset int
225+
var curI = i
203226
ArrayEach(data[i:], func(value []byte, dataType ValueType, offset int, err error) {
204227
if curIdx == aIdx {
205228
valueFound = value
206229
valueOffset = offset
207-
if dataType == String {
230+
if dataType == String {
208231
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+
}
211234
}
212235
curIdx += 1
213236
})
@@ -314,13 +337,13 @@ func EachKey(data []byte, cb func(int, []byte, ValueType, error), paths ...[]str
314337

315338
if maxPath >= level {
316339
if level < 1 {
317-
cb(-1, []byte{}, Unknown, MalformedJsonError)
340+
cb(-1, nil, Unknown, MalformedJsonError)
318341
return -1
319342
}
320-
pathsBuf[level-1] = bytesToString(&keyUnesc)
321343

344+
pathsBuf[level-1] = bytesToString(keyUnesc)
322345
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]) {
324347
continue
325348
}
326349

@@ -338,9 +361,12 @@ func EachKey(data []byte, cb func(int, []byte, ValueType, error), paths ...[]str
338361
}
339362

340363
if pathsMatched == len(paths) {
341-
return i
364+
break
342365
}
343366
}
367+
if pathsMatched == len(paths) {
368+
return i
369+
}
344370
}
345371

346372
if match == -1 {
@@ -369,7 +395,7 @@ func EachKey(data []byte, cb func(int, []byte, ValueType, error), paths ...[]str
369395
var pIdxFlags int64
370396

371397
if level < 0 {
372-
cb(-1, []byte{}, Unknown, MalformedJsonError)
398+
cb(-1, nil, Unknown, MalformedJsonError)
373399
return -1
374400
}
375401

@@ -501,6 +527,68 @@ func createInsertComponent(keys []string, setValue []byte, comma, object bool) [
501527

502528
/*
503529
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+
504592
Set - Receives existing data structure, path to set, and data to set at that key.
505593
506594
Returns:
@@ -518,7 +606,7 @@ func Set(data []byte, setValue []byte, keys ...string) (value []byte, err error)
518606
if err != nil {
519607
if err != KeyPathNotFoundError {
520608
// problem parsing the data
521-
return []byte{}, err
609+
return nil, err
522610
}
523611
// full path doesnt exist
524612
// does any subpath exist?
@@ -553,10 +641,10 @@ func Set(data []byte, setValue []byte, keys ...string) (value []byte, err error)
553641
depthOffset := endOffset
554642
if depth != 0 {
555643
// 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:])] != '}' {
557645
depthOffset--
558646
startOffset = depthOffset
559-
// otherwise, over-write it with a new object
647+
// otherwise, over-write it with a new object
560648
} else {
561649
comma = false
562650
object = true
@@ -589,15 +677,15 @@ func getType(data []byte, offset int) ([]byte, ValueType, int, error) {
589677
if idx, _ := stringEnd(data[offset+1:]); idx != -1 {
590678
endOffset += idx + 1
591679
} else {
592-
return []byte{}, dataType, offset, MalformedStringError
680+
return nil, dataType, offset, MalformedStringError
593681
}
594682
} else if data[offset] == '[' { // if array value
595683
dataType = Array
596684
// break label, for stopping nested loops
597685
endOffset = blockEnd(data[offset:], '[', ']')
598686

599687
if endOffset == -1 {
600-
return []byte{}, dataType, offset, MalformedArrayError
688+
return nil, dataType, offset, MalformedArrayError
601689
}
602690

603691
endOffset += offset
@@ -607,7 +695,7 @@ func getType(data []byte, offset int) ([]byte, ValueType, int, error) {
607695
endOffset = blockEnd(data[offset:], '{', '}')
608696

609697
if endOffset == -1 {
610-
return []byte{}, dataType, offset, MalformedObjectError
698+
return nil, dataType, offset, MalformedObjectError
611699
}
612700

613701
endOffset += offset
@@ -665,14 +753,14 @@ func Get(data []byte, keys ...string) (value []byte, dataType ValueType, offset
665753
func internalGet(data []byte, keys ...string) (value []byte, dataType ValueType, offset, endOffset int, err error) {
666754
if len(keys) > 0 {
667755
if offset = searchKeys(data, keys...); offset == -1 {
668-
return []byte{}, NotExist, -1, -1, KeyPathNotFoundError
756+
return nil, NotExist, -1, -1, KeyPathNotFoundError
669757
}
670758
}
671759

672760
// Go to closest value
673761
nO := nextToken(data[offset:])
674762
if nO == -1 {
675-
return []byte{}, NotExist, offset, -1, MalformedJsonError
763+
return nil, NotExist, offset, -1, MalformedJsonError
676764
}
677765

678766
offset += nO
@@ -884,7 +972,7 @@ func GetUnsafeString(data []byte, keys ...string) (val string, err error) {
884972
return "", e
885973
}
886974

887-
return bytesToString(&v), nil
975+
return bytesToString(v), nil
888976
}
889977

890978
// 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) {
9821070

9831071
// ParseNumber parses a Number ValueType into a Go float64
9841072
func ParseFloat(b []byte) (float64, error) {
985-
if v, err := parseFloat(&b); err != nil {
1073+
if v, err := parseFloat(b); err != nil {
9861074
return 0, MalformedValueError
9871075
} else {
9881076
return v, nil

0 commit comments

Comments
 (0)