@@ -19,22 +19,58 @@ package fieldpath
19
19
import (
20
20
"bytes"
21
21
"io"
22
+ "strings"
23
+ "unsafe"
22
24
23
25
jsoniter "github.com/json-iterator/go"
24
26
)
25
27
26
28
func (s * Set ) ToJSON () ([]byte , error ) {
27
29
buf := bytes.Buffer {}
28
- stream := jsoniter .NewStream (jsoniter .ConfigCompatibleWithStandardLibrary , & buf , 4096 )
30
+ err := s .ToJSONStream (& buf )
31
+ if err != nil {
32
+ return nil , err
33
+ }
34
+ return buf .Bytes (), nil
35
+ }
36
+
37
+ func (s * Set ) ToJSONStream (w io.Writer ) error {
38
+ stream := writePool .BorrowStream (w )
39
+ defer writePool .ReturnStream (stream )
40
+
41
+ var r reusableBuilder
29
42
30
43
stream .WriteObjectStart ()
31
- s .emitContents_v1 (false , stream )
44
+ err := s .emitContents_v1 (false , stream , & r )
45
+ if err != nil {
46
+ return err
47
+ }
32
48
stream .WriteObjectEnd ()
33
- err := stream .Flush ()
34
- return buf .Bytes (), err
49
+ return stream .Flush ()
50
+ }
51
+
52
+ func manageMemory (stream * jsoniter.Stream ) error {
53
+ b := stream .Buffer ()
54
+ if len (b ) > 4096 || cap (b )- len (b ) < 2048 {
55
+ if err := stream .Flush (); err != nil {
56
+ return err
57
+ }
58
+ stream .SetBuffer (b [:0 ])
59
+ }
60
+ return nil
61
+ }
62
+
63
+ type reusableBuilder struct {
64
+ addr * strings.Builder // of receiver, to detect copies by value
65
+ buf []byte
66
+ }
67
+
68
+ func (r * reusableBuilder ) reset () * strings.Builder {
69
+ r .buf = r .buf [:0 ]
70
+ return (* strings .Builder )(unsafe .Pointer (r ))
35
71
}
36
72
37
- func (s * Set ) emitContents_v1 (includeSelf bool , stream * jsoniter.Stream ) {
73
+ func (s * Set ) emitContents_v1 (includeSelf bool , stream * jsoniter.Stream , r * reusableBuilder ) error {
38
74
mi , ci := 0 , 0
39
75
first := true
40
76
preWrite := func () {
@@ -51,24 +87,28 @@ func (s *Set) emitContents_v1(includeSelf bool, stream *jsoniter.Stream) {
51
87
52
88
if mpe .Less (cpe ) {
53
89
preWrite ()
54
- str , _ := SerializePathElement ( mpe )
90
+ str , _ := serializePathElementUsingSB ( r . reset (), mpe )
55
91
stream .WriteObjectField (str )
56
92
stream .WriteEmptyObject ()
57
93
mi ++
58
94
} else if cpe .Less (mpe ) {
59
95
preWrite ()
60
- str , _ := SerializePathElement ( cpe )
96
+ str , _ := serializePathElementUsingSB ( r . reset (), cpe )
61
97
stream .WriteObjectField (str )
62
98
stream .WriteObjectStart ()
63
- s .Children .members [ci ].set .emitContents_v1 (false , stream )
99
+ if err := s .Children .members [ci ].set .emitContents_v1 (false , stream , r ); err != nil {
100
+ return err
101
+ }
64
102
stream .WriteObjectEnd ()
65
103
ci ++
66
104
} else {
67
105
preWrite ()
68
- str , _ := SerializePathElement ( cpe )
106
+ str , _ := serializePathElementUsingSB ( r . reset (), cpe )
69
107
stream .WriteObjectField (str )
70
108
stream .WriteObjectStart ()
71
- s .Children .members [ci ].set .emitContents_v1 (true , stream )
109
+ if err := s .Children .members [ci ].set .emitContents_v1 (true , stream , r ); err != nil {
110
+ return err
111
+ }
72
112
stream .WriteObjectEnd ()
73
113
mi ++
74
114
ci ++
@@ -79,7 +119,7 @@ func (s *Set) emitContents_v1(includeSelf bool, stream *jsoniter.Stream) {
79
119
mpe := s .Members .members [mi ]
80
120
81
121
preWrite ()
82
- str , _ := SerializePathElement ( mpe )
122
+ str , _ := serializePathElementUsingSB ( r . reset (), mpe )
83
123
stream .WriteObjectField (str )
84
124
stream .WriteEmptyObject ()
85
125
mi ++
@@ -89,10 +129,12 @@ func (s *Set) emitContents_v1(includeSelf bool, stream *jsoniter.Stream) {
89
129
cpe := s .Children .members [ci ].pathElement
90
130
91
131
preWrite ()
92
- str , _ := SerializePathElement ( cpe )
132
+ str , _ := serializePathElementUsingSB ( r . reset (), cpe )
93
133
stream .WriteObjectField (str )
94
134
stream .WriteObjectStart ()
95
- s .Children .members [ci ].set .emitContents_v1 (false , stream )
135
+ if err := s .Children .members [ci ].set .emitContents_v1 (false , stream , r ); err != nil {
136
+ return err
137
+ }
96
138
stream .WriteObjectEnd ()
97
139
ci ++
98
140
}
@@ -102,10 +144,12 @@ func (s *Set) emitContents_v1(includeSelf bool, stream *jsoniter.Stream) {
102
144
stream .WriteObjectField ("." )
103
145
stream .WriteEmptyObject ()
104
146
}
147
+ return manageMemory (stream )
105
148
}
106
149
107
150
// FromJSON clears s and reads a JSON formatted set structure.
108
151
func (s * Set ) FromJSON (r io.Reader ) error {
152
+ // The iterator pool is completely useless for memory management, grrr.
109
153
iter := jsoniter .Parse (jsoniter .ConfigCompatibleWithStandardLibrary , r , 4096 )
110
154
111
155
found , _ := readIter_v1 (iter )
0 commit comments