@@ -12,41 +12,30 @@ import (
12
12
"unicode"
13
13
)
14
14
15
- // PathBuffer is a low-allocation helper for building a path string like
16
- // `foo.bar[2].baz`. It is not goroutine-safe, but the underlying buffer can
17
- // be re-used within the same goroutine or via a `sync.Pool`.
15
+ // PathBuffer builds up a path string from multiple parts.
18
16
type PathBuffer struct {
19
- buf []byte
20
- off int
17
+ parts [][]byte
21
18
}
22
19
23
20
func (b * PathBuffer ) Push (s string ) {
24
- if b .off > 0 && s [0 ] != '[' {
25
- b .buf = append (b .buf , '.' )
26
- b .off ++
21
+ if s [0 ] != '[' {
22
+ s = "." + s
27
23
}
28
- b .buf = append (b .buf , s ... )
29
- b .off += len (s )
24
+ b .parts = append (b .parts , []byte (s ))
30
25
}
31
26
32
27
func (b * PathBuffer ) Pop () {
33
- for b .off > 0 {
34
- b .off --
35
- if b .buf [b .off ] == '.' || b .buf [b .off ] == '[' {
36
- break
37
- }
38
- }
39
- b .buf = b .buf [:b .off ]
28
+ b .parts = b .parts [:len (b .parts )- 1 ]
40
29
}
41
30
42
31
func (b * PathBuffer ) Bytes () []byte {
43
- return b . buf [: b . off ]
32
+ return bytes . Join ( b . parts , [] byte {})
44
33
}
45
34
46
- // NewPathBuffer creates a new path buffer with the given underlying byte slice
47
- // and offset within that slice (for pre-loading with some path data) .
48
- func NewPathBuffer (buf []byte , offset int ) * PathBuffer {
49
- return & PathBuffer {buf : buf , off : offset }
35
+ // NewPathBuffer creates a new path buffer with the given underlying initial
36
+ // data loaded into it .
37
+ func NewPathBuffer (parts [][] byte ) * PathBuffer {
38
+ return & PathBuffer {parts : parts }
50
39
}
51
40
52
41
// validFirstRune returns true for runes that are valid
@@ -72,6 +61,8 @@ func identifier(s string) string {
72
61
return s
73
62
}
74
63
64
+ s = strings .ReplaceAll (s , `"` , `\"` )
65
+
75
66
return fmt .Sprintf (`["%s"]` , s )
76
67
}
77
68
0 commit comments