oj 3.1.4 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/oj/dump.c +4 -4
- data/ext/oj/dump_leaf.c +3 -3
- data/ext/oj/fast.c +3 -3
- data/ext/oj/mimic_json.c +3 -3
- data/ext/oj/oj.c +2 -2
- data/ext/oj/oj.h +4 -2
- data/ext/oj/rails.c +1 -1
- data/ext/oj/stream_writer.c +77 -21
- data/ext/oj/string_writer.c +15 -5
- data/lib/oj/version.rb +1 -1
- data/test/test_writer.rb +55 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: af2435c13d3e1e32934f3743b0de0333093ec0bd
|
4
|
+
data.tar.gz: 05013dc900f2839c67a5d8aea480845686ac2bf9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 49af58a9f5747e506f972ca8a6a85d9463ae915194f230f2b64edb74f627c5d20f50ba38b9a07c5a9e56f774c3c5c1a58e45ec979151a35ac72e96cb0a77d2d6
|
7
|
+
data.tar.gz: 6c0fb738c3dd93610034550cb2ef123c75e5bb9cc2cf27f5effd7f97197f5747eac7dcce7542a5d1b0c9e6b7de8b25b9a6b914e77d710ebaf6514e98d3bb7a11
|
data/ext/oj/dump.c
CHANGED
@@ -552,7 +552,7 @@ oj_dump_obj_to_json_using_params(VALUE obj, Options copts, Out out, int argc, VA
|
|
552
552
|
if (0 == out->buf) {
|
553
553
|
out->buf = ALLOC_N(char, 4096);
|
554
554
|
out->end = out->buf + 4095 - BUFFER_EXTRA; // 1 less than end plus extra for possible errors
|
555
|
-
out->allocated =
|
555
|
+
out->allocated = true;
|
556
556
|
}
|
557
557
|
out->cur = out->buf;
|
558
558
|
out->circ_cnt = 0;
|
@@ -600,7 +600,7 @@ oj_write_obj_to_file(VALUE obj, const char *path, Options copts) {
|
|
600
600
|
|
601
601
|
out.buf = buf;
|
602
602
|
out.end = buf + sizeof(buf) - BUFFER_EXTRA;
|
603
|
-
out.allocated =
|
603
|
+
out.allocated = false;
|
604
604
|
out.omit_nil = copts->dump_opts.omit_nil;
|
605
605
|
oj_dump_obj_to_json(obj, copts, &out);
|
606
606
|
size = out.cur - out.buf;
|
@@ -635,7 +635,7 @@ oj_write_obj_to_stream(VALUE obj, VALUE stream, Options copts) {
|
|
635
635
|
|
636
636
|
out.buf = buf;
|
637
637
|
out.end = buf + sizeof(buf) - BUFFER_EXTRA;
|
638
|
-
out.allocated =
|
638
|
+
out.allocated = false;
|
639
639
|
out.omit_nil = copts->dump_opts.omit_nil;
|
640
640
|
oj_dump_obj_to_json(obj, copts, &out);
|
641
641
|
size = out.cur - out.buf;
|
@@ -873,7 +873,7 @@ oj_grow_out(Out out, size_t len) {
|
|
873
873
|
buf = REALLOC_N(out->buf, char, (size + BUFFER_EXTRA));
|
874
874
|
} else {
|
875
875
|
buf = ALLOC_N(char, (size + BUFFER_EXTRA));
|
876
|
-
out->allocated =
|
876
|
+
out->allocated = true;
|
877
877
|
memcpy(buf, out->buf, out->end - out->buf + BUFFER_EXTRA);
|
878
878
|
}
|
879
879
|
if (0 == buf) {
|
data/ext/oj/dump_leaf.c
CHANGED
@@ -24,7 +24,7 @@ grow(Out out, size_t len) {
|
|
24
24
|
buf = REALLOC_N(out->buf, char, (size + BUFFER_EXTRA));
|
25
25
|
} else {
|
26
26
|
buf = ALLOC_N(char, (size + BUFFER_EXTRA));
|
27
|
-
out->allocated =
|
27
|
+
out->allocated = true;
|
28
28
|
memcpy(buf, out->buf, out->end - out->buf + BUFFER_EXTRA);
|
29
29
|
}
|
30
30
|
if (0 == buf) {
|
@@ -214,7 +214,7 @@ oj_dump_leaf_to_json(Leaf leaf, Options copts, Out out) {
|
|
214
214
|
if (0 == out->buf) {
|
215
215
|
out->buf = ALLOC_N(char, 4096);
|
216
216
|
out->end = out->buf + 4095 - BUFFER_EXTRA; // 1 less than end plus extra for possible errors
|
217
|
-
out->allocated =
|
217
|
+
out->allocated = true;
|
218
218
|
}
|
219
219
|
out->cur = out->buf;
|
220
220
|
out->circ_cnt = 0;
|
@@ -233,7 +233,7 @@ oj_write_leaf_to_file(Leaf leaf, const char *path, Options copts) {
|
|
233
233
|
|
234
234
|
out.buf = buf;
|
235
235
|
out.end = buf + sizeof(buf) - BUFFER_EXTRA;
|
236
|
-
out.allocated =
|
236
|
+
out.allocated = false;
|
237
237
|
out.omit_nil = copts->dump_opts.omit_nil;
|
238
238
|
oj_dump_leaf_to_json(leaf, copts, &out);
|
239
239
|
size = out.cur - out.buf;
|
data/ext/oj/fast.c
CHANGED
@@ -92,7 +92,7 @@ static char* read_quoted_value(ParseInfo pi);
|
|
92
92
|
static void skip_comment(ParseInfo pi);
|
93
93
|
|
94
94
|
static VALUE protect_open_proc(VALUE x);
|
95
|
-
static VALUE parse_json(VALUE clas, char *json,
|
95
|
+
static VALUE parse_json(VALUE clas, char *json, bool given, bool allocated);
|
96
96
|
static void each_leaf(Doc doc, VALUE self);
|
97
97
|
static int move_step(Doc doc, const char *path, int loc);
|
98
98
|
static Leaf get_doc_leaf(Doc doc, const char *path);
|
@@ -779,7 +779,7 @@ free_doc_cb(void *x) {
|
|
779
779
|
}
|
780
780
|
|
781
781
|
static VALUE
|
782
|
-
parse_json(VALUE clas, char *json,
|
782
|
+
parse_json(VALUE clas, char *json, bool given, bool allocated) {
|
783
783
|
struct _ParseInfo pi;
|
784
784
|
VALUE result = Qnil;
|
785
785
|
Doc doc;
|
@@ -1594,7 +1594,7 @@ doc_dump(int argc, VALUE *argv, VALUE self) {
|
|
1594
1594
|
|
1595
1595
|
out.buf = buf;
|
1596
1596
|
out.end = buf + sizeof(buf) - 10;
|
1597
|
-
out.allocated =
|
1597
|
+
out.allocated = false;
|
1598
1598
|
out.omit_nil = oj_default_options.dump_opts.omit_nil;
|
1599
1599
|
oj_dump_leaf_to_json(leaf, &oj_default_options, &out);
|
1600
1600
|
rjson = rb_str_new2(out.buf);
|
data/ext/oj/mimic_json.c
CHANGED
@@ -198,7 +198,7 @@ mimic_dump(int argc, VALUE *argv, VALUE self) {
|
|
198
198
|
copts.str_rx.tail = NULL;
|
199
199
|
out.buf = buf;
|
200
200
|
out.end = buf + sizeof(buf) - 10;
|
201
|
-
out.allocated =
|
201
|
+
out.allocated = false;
|
202
202
|
out.caller = CALLER_DUMP;
|
203
203
|
copts.escape_mode = JXEsc;
|
204
204
|
copts.mode = CompatMode;
|
@@ -357,7 +357,7 @@ mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
|
357
357
|
|
358
358
|
out.buf = buf;
|
359
359
|
out.end = buf + sizeof(buf) - 10;
|
360
|
-
out.allocated =
|
360
|
+
out.allocated = false;
|
361
361
|
out.omit_nil = copts->dump_opts.omit_nil;
|
362
362
|
out.caller = CALLER_GENERATE;
|
363
363
|
// For obj.to_json or generate nan is not allowed but if called from dump
|
@@ -720,7 +720,7 @@ mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
|
|
720
720
|
copts.str_rx.tail = NULL;
|
721
721
|
out.buf = buf;
|
722
722
|
out.end = buf + sizeof(buf) - 10;
|
723
|
-
out.allocated =
|
723
|
+
out.allocated = false;
|
724
724
|
out.omit_nil = copts.dump_opts.omit_nil;
|
725
725
|
copts.mode = CompatMode;
|
726
726
|
copts.to_json = No;
|
data/ext/oj/oj.c
CHANGED
@@ -957,7 +957,7 @@ dump(int argc, VALUE *argv, VALUE self) {
|
|
957
957
|
}
|
958
958
|
out.buf = buf;
|
959
959
|
out.end = buf + sizeof(buf) - 10;
|
960
|
-
out.allocated =
|
960
|
+
out.allocated = false;
|
961
961
|
out.omit_nil = copts.dump_opts.omit_nil;
|
962
962
|
out.caller = CALLER_DUMP;
|
963
963
|
oj_dump_obj_to_json_using_params(*argv, &copts, &out, argc - 1,argv + 1);
|
@@ -1009,7 +1009,7 @@ to_json(int argc, VALUE *argv, VALUE self) {
|
|
1009
1009
|
copts.to_json = Yes;
|
1010
1010
|
out.buf = buf;
|
1011
1011
|
out.end = buf + sizeof(buf) - 10;
|
1012
|
-
out.allocated =
|
1012
|
+
out.allocated = false;
|
1013
1013
|
out.omit_nil = copts.dump_opts.omit_nil;
|
1014
1014
|
// For obj.to_json or generate nan is not allowed but if called from dump
|
1015
1015
|
// it is.
|
data/ext/oj/oj.h
CHANGED
@@ -188,7 +188,7 @@ typedef struct _Out {
|
|
188
188
|
int depth; // used by dump_hash
|
189
189
|
Options opts;
|
190
190
|
uint32_t hash_cnt;
|
191
|
-
|
191
|
+
bool allocated;
|
192
192
|
bool omit_nil;
|
193
193
|
int argc;
|
194
194
|
VALUE *argv;
|
@@ -203,6 +203,7 @@ typedef struct _StrWriter {
|
|
203
203
|
char *types; // DumpType
|
204
204
|
char *types_end;
|
205
205
|
int keyWritten;
|
206
|
+
|
206
207
|
} *StrWriter;
|
207
208
|
|
208
209
|
typedef struct _StreamWriter {
|
@@ -210,6 +211,7 @@ typedef struct _StreamWriter {
|
|
210
211
|
StreamWriterType type;
|
211
212
|
VALUE stream;
|
212
213
|
int fd;
|
214
|
+
int flush_limit; // indicator of when to flush
|
213
215
|
} *StreamWriter;
|
214
216
|
|
215
217
|
enum {
|
@@ -269,7 +271,7 @@ extern void oj_str_writer_pop_all(StrWriter sw);
|
|
269
271
|
extern void oj_init_doc(void);
|
270
272
|
extern void oj_string_writer_init();
|
271
273
|
extern void oj_stream_writer_init();
|
272
|
-
extern void oj_str_writer_init(StrWriter sw);
|
274
|
+
extern void oj_str_writer_init(StrWriter sw, int buf_size);
|
273
275
|
extern VALUE oj_define_mimic_json(int argc, VALUE *argv, VALUE self);
|
274
276
|
extern VALUE oj_mimic_generate(int argc, VALUE *argv, VALUE self);
|
275
277
|
extern VALUE oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self);
|
data/ext/oj/rails.c
CHANGED
@@ -658,7 +658,7 @@ encode(VALUE obj, ROptTable ropts, Options opts, int argc, VALUE *argv) {
|
|
658
658
|
}
|
659
659
|
out.buf = buf;
|
660
660
|
out.end = buf + sizeof(buf) - 10;
|
661
|
-
out.allocated =
|
661
|
+
out.allocated = false;
|
662
662
|
out.omit_nil = copts.dump_opts.omit_nil;
|
663
663
|
out.caller = 0;
|
664
664
|
out.cur = out.buf;
|
data/ext/oj/stream_writer.c
CHANGED
@@ -24,6 +24,12 @@ stream_writer_free(void *ptr) {
|
|
24
24
|
xfree(ptr);
|
25
25
|
}
|
26
26
|
|
27
|
+
static void
|
28
|
+
stream_writer_reset_buf(StreamWriter sw) {
|
29
|
+
sw->sw.out.cur = sw->sw.out.buf;
|
30
|
+
*sw->sw.out.cur = '\0';
|
31
|
+
}
|
32
|
+
|
27
33
|
static void
|
28
34
|
stream_writer_write(StreamWriter sw) {
|
29
35
|
ssize_t size = sw->sw.out.cur - sw->sw.out.buf;
|
@@ -43,18 +49,24 @@ stream_writer_write(StreamWriter sw) {
|
|
43
49
|
default:
|
44
50
|
rb_raise(rb_eArgError, "expected an IO Object.");
|
45
51
|
}
|
52
|
+
stream_writer_reset_buf(sw);
|
46
53
|
}
|
47
54
|
|
48
|
-
static
|
49
|
-
stream_writer_reset_buf(StreamWriter sw) {
|
50
|
-
sw->sw.out.cur = sw->sw.out.buf;
|
51
|
-
*sw->sw.out.cur = '\0';
|
52
|
-
}
|
55
|
+
static VALUE buffer_size_sym = Qundef;
|
53
56
|
|
54
57
|
/* Document-method: new
|
55
58
|
* call-seq: new(io, options)
|
56
59
|
*
|
57
|
-
* Creates a new StreamWriter.
|
60
|
+
* Creates a new StreamWriter. Options are supported according the the
|
61
|
+
* specified mode or the mode in the default options. Note that if mimic_JSON
|
62
|
+
* or Oj.optimize_rails has not been called then the behavior of the modes may
|
63
|
+
* not be the same as if they were.
|
64
|
+
*
|
65
|
+
* In addition to the regular dump options for the various modes a
|
66
|
+
* _:buffer_size_ option is available. It should be set to a positive
|
67
|
+
* integer. It is considered a hint of how large the initial internal buffer
|
68
|
+
* should be and also a hint on when to flush.
|
69
|
+
*
|
58
70
|
* - *io* [_IO_] stream to write to
|
59
71
|
* - *options* [_Hash_] formating options
|
60
72
|
*/
|
@@ -83,9 +95,32 @@ stream_writer_new(int argc, VALUE *argv, VALUE self) {
|
|
83
95
|
rb_raise(rb_eArgError, "expected an IO Object.");
|
84
96
|
}
|
85
97
|
sw = ALLOC(struct _StreamWriter);
|
86
|
-
|
87
|
-
|
98
|
+
if (2 == argc && T_HASH == rb_type(argv[1])) {
|
99
|
+
volatile VALUE v;
|
100
|
+
int buf_size = 0;
|
101
|
+
|
102
|
+
if (Qundef == buffer_size_sym) {
|
103
|
+
buffer_size_sym = ID2SYM(rb_intern("buffer_size")); rb_gc_register_address(&buffer_size_sym);
|
104
|
+
|
105
|
+
}
|
106
|
+
if (Qnil != (v = rb_hash_lookup(argv[1], buffer_size_sym))) {
|
107
|
+
#ifdef RUBY_INTEGER_UNIFICATION
|
108
|
+
if (rb_cInteger != rb_obj_class(v)) {
|
109
|
+
rb_raise(rb_eArgError, ":buffer size must be a Integer.");
|
110
|
+
}
|
111
|
+
#else
|
112
|
+
if (T_FIXNUM != rb_type(v)) {
|
113
|
+
rb_raise(rb_eArgError, ":buffer size must be a Integer.");
|
114
|
+
}
|
115
|
+
#endif
|
116
|
+
buf_size = FIX2INT(v);
|
117
|
+
}
|
118
|
+
oj_str_writer_init(&sw->sw, buf_size);
|
88
119
|
oj_parse_options(argv[1], &sw->sw.opts);
|
120
|
+
sw->flush_limit = buf_size;
|
121
|
+
} else {
|
122
|
+
oj_str_writer_init(&sw->sw, 4096);
|
123
|
+
sw->flush_limit = 0;
|
89
124
|
}
|
90
125
|
sw->sw.out.indent = sw->sw.opts.indent;
|
91
126
|
sw->stream = stream;
|
@@ -101,6 +136,7 @@ stream_writer_new(int argc, VALUE *argv, VALUE self) {
|
|
101
136
|
* Pushes a key onto the JSON document. The key will be used for the next push
|
102
137
|
* if currently in a JSON object and ignored otherwise. If a key is provided on
|
103
138
|
* the next push then that new key will be ignored.
|
139
|
+
*
|
104
140
|
* - *key* [_String_] the key pending for the next push
|
105
141
|
*/
|
106
142
|
static VALUE
|
@@ -108,9 +144,10 @@ stream_writer_push_key(VALUE self, VALUE key) {
|
|
108
144
|
StreamWriter sw = (StreamWriter)DATA_PTR(self);
|
109
145
|
|
110
146
|
rb_check_type(key, T_STRING);
|
111
|
-
stream_writer_reset_buf(sw);
|
112
147
|
oj_str_writer_push_key(&sw->sw, StringValuePtr(key));
|
113
|
-
|
148
|
+
if (sw->flush_limit < sw->sw.out.cur - sw->sw.out.buf) {
|
149
|
+
stream_writer_write(sw);
|
150
|
+
}
|
114
151
|
return Qnil;
|
115
152
|
}
|
116
153
|
|
@@ -119,13 +156,13 @@ stream_writer_push_key(VALUE self, VALUE key) {
|
|
119
156
|
*
|
120
157
|
* Pushes an object onto the JSON document. Future pushes will be to this object
|
121
158
|
* until a pop() is called.
|
159
|
+
*
|
122
160
|
* - *key* [_String_] the key if adding to an object in the JSON document
|
123
161
|
*/
|
124
162
|
static VALUE
|
125
163
|
stream_writer_push_object(int argc, VALUE *argv, VALUE self) {
|
126
164
|
StreamWriter sw = (StreamWriter)DATA_PTR(self);
|
127
165
|
|
128
|
-
stream_writer_reset_buf(sw);
|
129
166
|
switch (argc) {
|
130
167
|
case 0:
|
131
168
|
oj_str_writer_push_object(&sw->sw, 0);
|
@@ -142,7 +179,9 @@ stream_writer_push_object(int argc, VALUE *argv, VALUE self) {
|
|
142
179
|
rb_raise(rb_eArgError, "Wrong number of argument to 'push_object'.");
|
143
180
|
break;
|
144
181
|
}
|
145
|
-
|
182
|
+
if (sw->flush_limit < sw->sw.out.cur - sw->sw.out.buf) {
|
183
|
+
stream_writer_write(sw);
|
184
|
+
}
|
146
185
|
return Qnil;
|
147
186
|
}
|
148
187
|
|
@@ -151,13 +190,13 @@ stream_writer_push_object(int argc, VALUE *argv, VALUE self) {
|
|
151
190
|
*
|
152
191
|
* Pushes an array onto the JSON document. Future pushes will be to this object
|
153
192
|
* until a pop() is called.
|
193
|
+
*
|
154
194
|
* - *key* [_String_] the key if adding to an object in the JSON document
|
155
195
|
*/
|
156
196
|
static VALUE
|
157
197
|
stream_writer_push_array(int argc, VALUE *argv, VALUE self) {
|
158
198
|
StreamWriter sw = (StreamWriter)DATA_PTR(self);
|
159
199
|
|
160
|
-
stream_writer_reset_buf(sw);
|
161
200
|
switch (argc) {
|
162
201
|
case 0:
|
163
202
|
oj_str_writer_push_array(&sw->sw, 0);
|
@@ -174,7 +213,9 @@ stream_writer_push_array(int argc, VALUE *argv, VALUE self) {
|
|
174
213
|
rb_raise(rb_eArgError, "Wrong number of argument to 'push_object'.");
|
175
214
|
break;
|
176
215
|
}
|
177
|
-
|
216
|
+
if (sw->flush_limit < sw->sw.out.cur - sw->sw.out.buf) {
|
217
|
+
stream_writer_write(sw);
|
218
|
+
}
|
178
219
|
return Qnil;
|
179
220
|
}
|
180
221
|
|
@@ -189,7 +230,6 @@ static VALUE
|
|
189
230
|
stream_writer_push_value(int argc, VALUE *argv, VALUE self) {
|
190
231
|
StreamWriter sw = (StreamWriter)DATA_PTR(self);
|
191
232
|
|
192
|
-
stream_writer_reset_buf(sw);
|
193
233
|
switch (argc) {
|
194
234
|
case 1:
|
195
235
|
oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, 0);
|
@@ -206,7 +246,9 @@ stream_writer_push_value(int argc, VALUE *argv, VALUE self) {
|
|
206
246
|
rb_raise(rb_eArgError, "Wrong number of argument to 'push_value'.");
|
207
247
|
break;
|
208
248
|
}
|
209
|
-
|
249
|
+
if (sw->flush_limit < sw->sw.out.cur - sw->sw.out.buf) {
|
250
|
+
stream_writer_write(sw);
|
251
|
+
}
|
210
252
|
return Qnil;
|
211
253
|
}
|
212
254
|
|
@@ -224,7 +266,6 @@ stream_writer_push_json(int argc, VALUE *argv, VALUE self) {
|
|
224
266
|
StreamWriter sw = (StreamWriter)DATA_PTR(self);
|
225
267
|
|
226
268
|
rb_check_type(argv[0], T_STRING);
|
227
|
-
stream_writer_reset_buf(sw);
|
228
269
|
switch (argc) {
|
229
270
|
case 1:
|
230
271
|
oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), 0);
|
@@ -241,7 +282,9 @@ stream_writer_push_json(int argc, VALUE *argv, VALUE self) {
|
|
241
282
|
rb_raise(rb_eArgError, "Wrong number of argument to 'push_json'.");
|
242
283
|
break;
|
243
284
|
}
|
244
|
-
|
285
|
+
if (sw->flush_limit < sw->sw.out.cur - sw->sw.out.buf) {
|
286
|
+
stream_writer_write(sw);
|
287
|
+
}
|
245
288
|
return Qnil;
|
246
289
|
}
|
247
290
|
|
@@ -255,9 +298,10 @@ static VALUE
|
|
255
298
|
stream_writer_pop(VALUE self) {
|
256
299
|
StreamWriter sw = (StreamWriter)DATA_PTR(self);
|
257
300
|
|
258
|
-
stream_writer_reset_buf(sw);
|
259
301
|
oj_str_writer_pop(&sw->sw);
|
260
|
-
|
302
|
+
if (sw->flush_limit < sw->sw.out.cur - sw->sw.out.buf) {
|
303
|
+
stream_writer_write(sw);
|
304
|
+
}
|
261
305
|
return Qnil;
|
262
306
|
}
|
263
307
|
|
@@ -271,13 +315,24 @@ static VALUE
|
|
271
315
|
stream_writer_pop_all(VALUE self) {
|
272
316
|
StreamWriter sw = (StreamWriter)DATA_PTR(self);
|
273
317
|
|
274
|
-
stream_writer_reset_buf(sw);
|
275
318
|
oj_str_writer_pop_all(&sw->sw);
|
276
319
|
stream_writer_write(sw);
|
277
320
|
|
278
321
|
return Qnil;
|
279
322
|
}
|
280
323
|
|
324
|
+
/* Document-method: flush
|
325
|
+
* call-seq: flush()
|
326
|
+
*
|
327
|
+
* Flush any remaining characters in the buffer.
|
328
|
+
*/
|
329
|
+
static VALUE
|
330
|
+
stream_writer_flush(VALUE self) {
|
331
|
+
stream_writer_write((StreamWriter)DATA_PTR(self));
|
332
|
+
|
333
|
+
return Qnil;
|
334
|
+
}
|
335
|
+
|
281
336
|
/* Document-class: Oj::StreamWriter
|
282
337
|
*
|
283
338
|
* Supports building a JSON document one element at a time. Build the IO stream
|
@@ -296,6 +351,7 @@ oj_stream_writer_init() {
|
|
296
351
|
rb_define_method(oj_stream_writer_class, "push_json", stream_writer_push_json, -1);
|
297
352
|
rb_define_method(oj_stream_writer_class, "pop", stream_writer_pop, 0);
|
298
353
|
rb_define_method(oj_stream_writer_class, "pop_all", stream_writer_pop_all, 0);
|
354
|
+
rb_define_method(oj_stream_writer_class, "flush", stream_writer_flush, 0);
|
299
355
|
}
|
300
356
|
|
301
357
|
|
data/ext/oj/string_writer.c
CHANGED
@@ -48,7 +48,7 @@ maybe_comma(StrWriter sw) {
|
|
48
48
|
|
49
49
|
// Used by stream writer also.
|
50
50
|
void
|
51
|
-
oj_str_writer_init(StrWriter sw) {
|
51
|
+
oj_str_writer_init(StrWriter sw, int buf_size) {
|
52
52
|
sw->opts = oj_default_options;
|
53
53
|
sw->depth = 0;
|
54
54
|
sw->types = ALLOC_N(char, 256);
|
@@ -56,9 +56,14 @@ oj_str_writer_init(StrWriter sw) {
|
|
56
56
|
*sw->types = '\0';
|
57
57
|
sw->keyWritten = 0;
|
58
58
|
|
59
|
-
|
60
|
-
|
61
|
-
|
59
|
+
if (0 == buf_size) {
|
60
|
+
buf_size = 4096;
|
61
|
+
} else if (buf_size < 1024) {
|
62
|
+
buf_size = 1024;
|
63
|
+
}
|
64
|
+
sw->out.buf = ALLOC_N(char, buf_size);
|
65
|
+
sw->out.end = sw->out.buf + buf_size - 10;
|
66
|
+
sw->out.allocated = true;
|
62
67
|
sw->out.cur = sw->out.buf;
|
63
68
|
*sw->out.cur = '\0';
|
64
69
|
sw->out.circ_cnt = 0;
|
@@ -255,6 +260,11 @@ str_writer_free(void *ptr) {
|
|
255
260
|
* or Oj.optimize_rails has not been called then the behavior of the modes may
|
256
261
|
* not be the same as if they were.
|
257
262
|
*
|
263
|
+
* In addition to the regular dump options for the various modes a
|
264
|
+
* _:buffer_size_ option is available. It should be set to a positive
|
265
|
+
* integer. It is considered a hint of how large the initial internal buffer
|
266
|
+
* should be.
|
267
|
+
*
|
258
268
|
* - *io* [_IO_] stream to write to
|
259
269
|
* - *options* [_Hash_] formating options
|
260
270
|
*/
|
@@ -262,7 +272,7 @@ static VALUE
|
|
262
272
|
str_writer_new(int argc, VALUE *argv, VALUE self) {
|
263
273
|
StrWriter sw = ALLOC(struct _StrWriter);
|
264
274
|
|
265
|
-
oj_str_writer_init(sw);
|
275
|
+
oj_str_writer_init(sw, 0);
|
266
276
|
if (1 == argc) {
|
267
277
|
oj_parse_options(argv[0], &sw->opts);
|
268
278
|
}
|
data/lib/oj/version.rb
CHANGED
data/test/test_writer.rb
CHANGED
@@ -297,6 +297,61 @@ class OjWriter < Minitest::Test
|
|
297
297
|
assert_equal(%|{"a1":{},"a2":{"b":{}},"a3":{"a4":37}}\n|, output.string())
|
298
298
|
end
|
299
299
|
|
300
|
+
def push_stuff(w, pop_all=true)
|
301
|
+
w.push_object()
|
302
|
+
w.push_object("a1")
|
303
|
+
w.pop()
|
304
|
+
w.push_object("a2")
|
305
|
+
w.push_array("b")
|
306
|
+
w.push_value(7)
|
307
|
+
w.push_value(true)
|
308
|
+
w.push_value("string")
|
309
|
+
w.pop()
|
310
|
+
w.pop()
|
311
|
+
w.push_object("a3")
|
312
|
+
if pop_all
|
313
|
+
w.pop_all()
|
314
|
+
else
|
315
|
+
w.pop()
|
316
|
+
w.pop()
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
def test_stream_writer_buf_small
|
321
|
+
output = StringIO.open("", "w+")
|
322
|
+
w = Oj::StreamWriter.new(output, :indent => 0, :buffer_size => 20)
|
323
|
+
push_stuff(w)
|
324
|
+
assert_equal(%|{"a1":{},"a2":{"b":[7,true,"string"]},"a3":{}}\n|, output.string())
|
325
|
+
end
|
326
|
+
|
327
|
+
def test_stream_writer_buf_large
|
328
|
+
output = StringIO.open("", "w+")
|
329
|
+
w = Oj::StreamWriter.new(output, :indent => 0, :buffer_size => 16000)
|
330
|
+
push_stuff(w)
|
331
|
+
assert_equal(%|{"a1":{},"a2":{"b":[7,true,"string"]},"a3":{}}\n|, output.string())
|
332
|
+
end
|
333
|
+
|
334
|
+
def test_stream_writer_buf_flush
|
335
|
+
output = StringIO.open("", "w+")
|
336
|
+
w = Oj::StreamWriter.new(output, :indent => 0, :buffer_size => 4096)
|
337
|
+
push_stuff(w, false)
|
338
|
+
# no flush so nothing should be in the output yet
|
339
|
+
assert_equal("", output.string())
|
340
|
+
w.flush()
|
341
|
+
assert_equal(%|{"a1":{},"a2":{"b":[7,true,"string"]},"a3":{}}\n|, output.string())
|
342
|
+
end
|
343
|
+
|
344
|
+
def test_stream_writer_buf_flush_small
|
345
|
+
output = StringIO.open("", "w+")
|
346
|
+
w = Oj::StreamWriter.new(output, :indent => 0, :buffer_size => 30)
|
347
|
+
push_stuff(w, false)
|
348
|
+
# flush should be called at 30 bytes but since the writes are chunky flush
|
349
|
+
# is called after adding "string".
|
350
|
+
assert_equal(%|{"a1":{},"a2":{"b":[7,true,"string"|, output.string())
|
351
|
+
w.flush()
|
352
|
+
assert_equal(%|{"a1":{},"a2":{"b":[7,true,"string"]},"a3":{}}\n|, output.string())
|
353
|
+
end
|
354
|
+
|
300
355
|
def test_stream_writer_push_null_value_with_key
|
301
356
|
output = StringIO.open("", "w+")
|
302
357
|
w = Oj::StreamWriter.new(output, :indent => 0)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oj
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Ohler
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-06-
|
11
|
+
date: 2017-06-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|