oj 3.1.4 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|