oj 3.7.12

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.
Files changed (156) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +96 -0
  4. data/ext/oj/buf.h +103 -0
  5. data/ext/oj/cache8.c +107 -0
  6. data/ext/oj/cache8.h +48 -0
  7. data/ext/oj/circarray.c +68 -0
  8. data/ext/oj/circarray.h +23 -0
  9. data/ext/oj/code.c +235 -0
  10. data/ext/oj/code.h +42 -0
  11. data/ext/oj/compat.c +299 -0
  12. data/ext/oj/custom.c +1188 -0
  13. data/ext/oj/dump.c +1232 -0
  14. data/ext/oj/dump.h +94 -0
  15. data/ext/oj/dump_compat.c +973 -0
  16. data/ext/oj/dump_leaf.c +252 -0
  17. data/ext/oj/dump_object.c +837 -0
  18. data/ext/oj/dump_strict.c +433 -0
  19. data/ext/oj/encode.h +45 -0
  20. data/ext/oj/err.c +57 -0
  21. data/ext/oj/err.h +70 -0
  22. data/ext/oj/extconf.rb +47 -0
  23. data/ext/oj/fast.c +1771 -0
  24. data/ext/oj/hash.c +163 -0
  25. data/ext/oj/hash.h +46 -0
  26. data/ext/oj/hash_test.c +512 -0
  27. data/ext/oj/mimic_json.c +873 -0
  28. data/ext/oj/object.c +771 -0
  29. data/ext/oj/odd.c +231 -0
  30. data/ext/oj/odd.h +44 -0
  31. data/ext/oj/oj.c +1694 -0
  32. data/ext/oj/oj.h +381 -0
  33. data/ext/oj/parse.c +1085 -0
  34. data/ext/oj/parse.h +111 -0
  35. data/ext/oj/rails.c +1485 -0
  36. data/ext/oj/rails.h +21 -0
  37. data/ext/oj/reader.c +231 -0
  38. data/ext/oj/reader.h +151 -0
  39. data/ext/oj/resolve.c +102 -0
  40. data/ext/oj/resolve.h +14 -0
  41. data/ext/oj/rxclass.c +147 -0
  42. data/ext/oj/rxclass.h +27 -0
  43. data/ext/oj/saj.c +714 -0
  44. data/ext/oj/scp.c +224 -0
  45. data/ext/oj/sparse.c +910 -0
  46. data/ext/oj/stream_writer.c +363 -0
  47. data/ext/oj/strict.c +212 -0
  48. data/ext/oj/string_writer.c +512 -0
  49. data/ext/oj/trace.c +79 -0
  50. data/ext/oj/trace.h +28 -0
  51. data/ext/oj/util.c +136 -0
  52. data/ext/oj/util.h +19 -0
  53. data/ext/oj/val_stack.c +118 -0
  54. data/ext/oj/val_stack.h +185 -0
  55. data/ext/oj/wab.c +631 -0
  56. data/lib/oj.rb +21 -0
  57. data/lib/oj/active_support_helper.rb +41 -0
  58. data/lib/oj/bag.rb +88 -0
  59. data/lib/oj/easy_hash.rb +52 -0
  60. data/lib/oj/error.rb +22 -0
  61. data/lib/oj/json.rb +176 -0
  62. data/lib/oj/mimic.rb +267 -0
  63. data/lib/oj/saj.rb +66 -0
  64. data/lib/oj/schandler.rb +142 -0
  65. data/lib/oj/state.rb +131 -0
  66. data/lib/oj/version.rb +5 -0
  67. data/pages/Advanced.md +22 -0
  68. data/pages/Compatibility.md +25 -0
  69. data/pages/Custom.md +23 -0
  70. data/pages/Encoding.md +65 -0
  71. data/pages/JsonGem.md +79 -0
  72. data/pages/Modes.md +154 -0
  73. data/pages/Options.md +266 -0
  74. data/pages/Rails.md +116 -0
  75. data/pages/Security.md +20 -0
  76. data/pages/WAB.md +13 -0
  77. data/test/_test_active.rb +76 -0
  78. data/test/_test_active_mimic.rb +96 -0
  79. data/test/_test_mimic_rails.rb +126 -0
  80. data/test/activerecord/result_test.rb +27 -0
  81. data/test/activesupport4/decoding_test.rb +108 -0
  82. data/test/activesupport4/encoding_test.rb +531 -0
  83. data/test/activesupport4/test_helper.rb +41 -0
  84. data/test/activesupport5/decoding_test.rb +125 -0
  85. data/test/activesupport5/encoding_test.rb +485 -0
  86. data/test/activesupport5/encoding_test_cases.rb +90 -0
  87. data/test/activesupport5/test_helper.rb +50 -0
  88. data/test/activesupport5/time_zone_test_helpers.rb +24 -0
  89. data/test/big.rb +15 -0
  90. data/test/files.rb +29 -0
  91. data/test/foo.rb +33 -0
  92. data/test/helper.rb +26 -0
  93. data/test/isolated/shared.rb +308 -0
  94. data/test/isolated/test_mimic_after.rb +13 -0
  95. data/test/isolated/test_mimic_alone.rb +12 -0
  96. data/test/isolated/test_mimic_as_json.rb +45 -0
  97. data/test/isolated/test_mimic_before.rb +13 -0
  98. data/test/isolated/test_mimic_define.rb +28 -0
  99. data/test/isolated/test_mimic_rails_after.rb +22 -0
  100. data/test/isolated/test_mimic_rails_before.rb +21 -0
  101. data/test/isolated/test_mimic_redefine.rb +15 -0
  102. data/test/json_gem/json_addition_test.rb +216 -0
  103. data/test/json_gem/json_common_interface_test.rb +148 -0
  104. data/test/json_gem/json_encoding_test.rb +107 -0
  105. data/test/json_gem/json_ext_parser_test.rb +20 -0
  106. data/test/json_gem/json_fixtures_test.rb +35 -0
  107. data/test/json_gem/json_generator_test.rb +383 -0
  108. data/test/json_gem/json_generic_object_test.rb +90 -0
  109. data/test/json_gem/json_parser_test.rb +470 -0
  110. data/test/json_gem/json_string_matching_test.rb +42 -0
  111. data/test/json_gem/test_helper.rb +18 -0
  112. data/test/mem.rb +35 -0
  113. data/test/perf.rb +107 -0
  114. data/test/perf_compat.rb +130 -0
  115. data/test/perf_fast.rb +164 -0
  116. data/test/perf_file.rb +64 -0
  117. data/test/perf_object.rb +138 -0
  118. data/test/perf_saj.rb +109 -0
  119. data/test/perf_scp.rb +151 -0
  120. data/test/perf_simple.rb +287 -0
  121. data/test/perf_strict.rb +145 -0
  122. data/test/perf_wab.rb +131 -0
  123. data/test/sample.rb +54 -0
  124. data/test/sample/change.rb +14 -0
  125. data/test/sample/dir.rb +19 -0
  126. data/test/sample/doc.rb +36 -0
  127. data/test/sample/file.rb +48 -0
  128. data/test/sample/group.rb +16 -0
  129. data/test/sample/hasprops.rb +16 -0
  130. data/test/sample/layer.rb +12 -0
  131. data/test/sample/line.rb +20 -0
  132. data/test/sample/oval.rb +10 -0
  133. data/test/sample/rect.rb +10 -0
  134. data/test/sample/shape.rb +35 -0
  135. data/test/sample/text.rb +20 -0
  136. data/test/sample_json.rb +37 -0
  137. data/test/test_compat.rb +509 -0
  138. data/test/test_custom.rb +406 -0
  139. data/test/test_debian.rb +53 -0
  140. data/test/test_fast.rb +470 -0
  141. data/test/test_file.rb +239 -0
  142. data/test/test_gc.rb +49 -0
  143. data/test/test_hash.rb +29 -0
  144. data/test/test_integer_range.rb +73 -0
  145. data/test/test_null.rb +376 -0
  146. data/test/test_object.rb +1018 -0
  147. data/test/test_saj.rb +186 -0
  148. data/test/test_scp.rb +433 -0
  149. data/test/test_strict.rb +410 -0
  150. data/test/test_various.rb +739 -0
  151. data/test/test_wab.rb +307 -0
  152. data/test/test_writer.rb +380 -0
  153. data/test/tests.rb +24 -0
  154. data/test/tests_mimic.rb +14 -0
  155. data/test/tests_mimic_addition.rb +7 -0
  156. metadata +359 -0
@@ -0,0 +1,512 @@
1
+ /* strwriter.c
2
+ * Copyright (c) 2012, 2017, Peter Ohler
3
+ * All rights reserved.
4
+ */
5
+
6
+ #include "dump.h"
7
+ #include "encode.h"
8
+
9
+ extern VALUE Oj;
10
+
11
+ static void
12
+ key_check(StrWriter sw, const char *key) {
13
+ DumpType type = sw->types[sw->depth];
14
+
15
+ if (0 == key && (ObjectNew == type || ObjectType == type)) {
16
+ rb_raise(rb_eStandardError, "Can not push onto an Object without a key.");
17
+ }
18
+ }
19
+
20
+ static void
21
+ push_type(StrWriter sw, DumpType type) {
22
+ if (sw->types_end <= sw->types + sw->depth + 1) {
23
+ size_t size = (sw->types_end - sw->types) * 2;
24
+
25
+ REALLOC_N(sw->types, char, size);
26
+ sw->types_end = sw->types + size;
27
+ }
28
+ sw->depth++;
29
+ sw->types[sw->depth] = type;
30
+ }
31
+
32
+ static void
33
+ maybe_comma(StrWriter sw) {
34
+ switch (sw->types[sw->depth]) {
35
+ case ObjectNew:
36
+ sw->types[sw->depth] = ObjectType;
37
+ break;
38
+ case ArrayNew:
39
+ sw->types[sw->depth] = ArrayType;
40
+ break;
41
+ case ObjectType:
42
+ case ArrayType:
43
+ // Always have a few characters available in the out.buf.
44
+ *sw->out.cur++ = ',';
45
+ break;
46
+ }
47
+ }
48
+
49
+ // Used by stream writer also.
50
+ void
51
+ oj_str_writer_init(StrWriter sw, int buf_size) {
52
+ sw->opts = oj_default_options;
53
+ sw->depth = 0;
54
+ sw->types = ALLOC_N(char, 256);
55
+ sw->types_end = sw->types + 256;
56
+ *sw->types = '\0';
57
+ sw->keyWritten = 0;
58
+
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;
67
+ sw->out.cur = sw->out.buf;
68
+ *sw->out.cur = '\0';
69
+ sw->out.circ_cache = NULL;
70
+ sw->out.circ_cnt = 0;
71
+ sw->out.hash_cnt = 0;
72
+ sw->out.opts = &sw->opts;
73
+ sw->out.indent = sw->opts.indent;
74
+ sw->out.depth = 0;
75
+ sw->out.argc = 0;
76
+ sw->out.argv = NULL;
77
+ sw->out.caller = 0;
78
+ sw->out.ropts = NULL;
79
+ sw->out.omit_nil = oj_default_options.dump_opts.omit_nil;
80
+ }
81
+
82
+ void
83
+ oj_str_writer_push_key(StrWriter sw, const char *key) {
84
+ DumpType type = sw->types[sw->depth];
85
+ long size;
86
+
87
+ if (sw->keyWritten) {
88
+ rb_raise(rb_eStandardError, "Can not push more than one key before pushing a non-key.");
89
+ }
90
+ if (ObjectNew != type && ObjectType != type) {
91
+ rb_raise(rb_eStandardError, "Can only push a key onto an Object.");
92
+ }
93
+ size = sw->depth * sw->out.indent + 3;
94
+ assure_size(&sw->out, size);
95
+ maybe_comma(sw);
96
+ if (0 < sw->depth) {
97
+ fill_indent(&sw->out, sw->depth);
98
+ }
99
+ oj_dump_cstr(key, strlen(key), 0, 0, &sw->out);
100
+ *sw->out.cur++ = ':';
101
+ sw->keyWritten = 1;
102
+ }
103
+
104
+ void
105
+ oj_str_writer_push_object(StrWriter sw, const char *key) {
106
+ if (sw->keyWritten) {
107
+ sw->keyWritten = 0;
108
+ assure_size(&sw->out, 1);
109
+ } else {
110
+ long size;
111
+
112
+ key_check(sw, key);
113
+ size = sw->depth * sw->out.indent + 3;
114
+ assure_size(&sw->out, size);
115
+ maybe_comma(sw);
116
+ if (0 < sw->depth) {
117
+ fill_indent(&sw->out, sw->depth);
118
+ }
119
+ if (0 != key) {
120
+ oj_dump_cstr(key, strlen(key), 0, 0, &sw->out);
121
+ *sw->out.cur++ = ':';
122
+ }
123
+ }
124
+ *sw->out.cur++ = '{';
125
+ push_type(sw, ObjectNew);
126
+ }
127
+
128
+ void
129
+ oj_str_writer_push_array(StrWriter sw, const char *key) {
130
+ if (sw->keyWritten) {
131
+ sw->keyWritten = 0;
132
+ assure_size(&sw->out, 1);
133
+ } else {
134
+ long size;
135
+
136
+ key_check(sw, key);
137
+ size = sw->depth * sw->out.indent + 3;
138
+ assure_size(&sw->out, size);
139
+ maybe_comma(sw);
140
+ if (0 < sw->depth) {
141
+ fill_indent(&sw->out, sw->depth);
142
+ }
143
+ if (0 != key) {
144
+ oj_dump_cstr(key, strlen(key), 0, 0, &sw->out);
145
+ *sw->out.cur++ = ':';
146
+ }
147
+ }
148
+ *sw->out.cur++ = '[';
149
+ push_type(sw, ArrayNew);
150
+ }
151
+
152
+ void
153
+ oj_str_writer_push_value(StrWriter sw, VALUE val, const char *key) {
154
+ Out out = &sw->out;
155
+
156
+ if (sw->keyWritten) {
157
+ sw->keyWritten = 0;
158
+ } else {
159
+ long size;
160
+
161
+ key_check(sw, key);
162
+ size = sw->depth * out->indent + 3;
163
+ assure_size(out, size);
164
+ maybe_comma(sw);
165
+ if (0 < sw->depth) {
166
+ fill_indent(&sw->out, sw->depth);
167
+ }
168
+ if (0 != key) {
169
+ oj_dump_cstr(key, strlen(key), 0, 0, out);
170
+ *out->cur++ = ':';
171
+ }
172
+ }
173
+ switch (out->opts->mode) {
174
+ case StrictMode: oj_dump_strict_val(val, sw->depth, out); break;
175
+ case NullMode: oj_dump_null_val(val, sw->depth, out); break;
176
+ case ObjectMode: oj_dump_obj_val(val, sw->depth, out); break;
177
+ case CompatMode: oj_dump_compat_val(val, sw->depth, out, Yes == out->opts->to_json); break;
178
+ case RailsMode: oj_dump_rails_val(val, sw->depth, out); break;
179
+ case CustomMode: oj_dump_custom_val(val, sw->depth, out, true); break;
180
+ default: oj_dump_custom_val(val, sw->depth, out, true); break;
181
+ }
182
+ }
183
+
184
+ void
185
+ oj_str_writer_push_json(StrWriter sw, const char *json, const char *key) {
186
+ if (sw->keyWritten) {
187
+ sw->keyWritten = 0;
188
+ } else {
189
+ long size;
190
+
191
+ key_check(sw, key);
192
+ size = sw->depth * sw->out.indent + 3;
193
+ assure_size(&sw->out, size);
194
+ maybe_comma(sw);
195
+ if (0 < sw->depth) {
196
+ fill_indent(&sw->out, sw->depth);
197
+ }
198
+ if (0 != key) {
199
+ oj_dump_cstr(key, strlen(key), 0, 0, &sw->out);
200
+ *sw->out.cur++ = ':';
201
+ }
202
+ }
203
+ oj_dump_raw(json, strlen(json), &sw->out);
204
+ }
205
+
206
+ void
207
+ oj_str_writer_pop(StrWriter sw) {
208
+ long size;
209
+ DumpType type = sw->types[sw->depth];
210
+
211
+ if (sw->keyWritten) {
212
+ sw->keyWritten = 0;
213
+ rb_raise(rb_eStandardError, "Can not pop after writing a key but no value.");
214
+ }
215
+ sw->depth--;
216
+ if (0 > sw->depth) {
217
+ rb_raise(rb_eStandardError, "Can not pop with no open array or object.");
218
+ }
219
+ size = sw->depth * sw->out.indent + 2;
220
+ assure_size(&sw->out, size);
221
+ fill_indent(&sw->out, sw->depth);
222
+ switch (type) {
223
+ case ObjectNew:
224
+ case ObjectType:
225
+ *sw->out.cur++ = '}';
226
+ break;
227
+ case ArrayNew:
228
+ case ArrayType:
229
+ *sw->out.cur++ = ']';
230
+ break;
231
+ }
232
+ if (0 == sw->depth && 0 <= sw->out.indent) {
233
+ *sw->out.cur++ = '\n';
234
+ }
235
+ }
236
+
237
+ void
238
+ oj_str_writer_pop_all(StrWriter sw) {
239
+ while (0 < sw->depth) {
240
+ oj_str_writer_pop(sw);
241
+ }
242
+ }
243
+
244
+ static void
245
+ str_writer_free(void *ptr) {
246
+ StrWriter sw;
247
+
248
+ if (0 == ptr) {
249
+ return;
250
+ }
251
+ sw = (StrWriter)ptr;
252
+ xfree(sw->out.buf);
253
+ xfree(sw->types);
254
+ xfree(ptr);
255
+ }
256
+
257
+ /* Document-method: new
258
+ * call-seq: new(io, options)
259
+ *
260
+ * Creates a new StringWriter. Options are supported according the the
261
+ * specified mode or the mode in the default options. Note that if mimic_JSON
262
+ * or Oj.optimize_rails has not been called then the behavior of the modes may
263
+ * not be the same as if they were.
264
+ *
265
+ * In addition to the regular dump options for the various modes a
266
+ * _:buffer_size_ option is available. It should be set to a positive
267
+ * integer. It is considered a hint of how large the initial internal buffer
268
+ * should be.
269
+ *
270
+ * - *io* [_IO_] stream to write to
271
+ * - *options* [_Hash_] formating options
272
+ */
273
+ static VALUE
274
+ str_writer_new(int argc, VALUE *argv, VALUE self) {
275
+ StrWriter sw = ALLOC(struct _strWriter);
276
+
277
+ oj_str_writer_init(sw, 0);
278
+ if (1 == argc) {
279
+ oj_parse_options(argv[0], &sw->opts);
280
+ }
281
+ sw->out.argc = argc - 1;
282
+ sw->out.argv = argv + 1;
283
+ sw->out.indent = sw->opts.indent;
284
+
285
+ return Data_Wrap_Struct(oj_string_writer_class, 0, str_writer_free, sw);
286
+ }
287
+
288
+ /* Document-method: push_key
289
+ * call-seq: push_key(key)
290
+ *
291
+ * Pushes a key onto the JSON document. The key will be used for the next push
292
+ * if currently in a JSON object and ignored otherwise. If a key is provided on
293
+ * the next push then that new key will be ignored.
294
+ * - *key* [_String_] the key pending for the next push
295
+ */
296
+ static VALUE
297
+ str_writer_push_key(VALUE self, VALUE key) {
298
+ StrWriter sw = (StrWriter)DATA_PTR(self);
299
+
300
+ rb_check_type(key, T_STRING);
301
+ oj_str_writer_push_key(sw, StringValuePtr(key));
302
+
303
+ return Qnil;
304
+ }
305
+
306
+ /* Document-method: push_object
307
+ * call-seq: push_object(key=nil)
308
+ *
309
+ * Pushes an object onto the JSON document. Future pushes will be to this object
310
+ * until a pop() is called.
311
+ * - *key* [_String_] the key if adding to an object in the JSON document
312
+ */
313
+ static VALUE
314
+ str_writer_push_object(int argc, VALUE *argv, VALUE self) {
315
+ StrWriter sw = (StrWriter)DATA_PTR(self);
316
+
317
+ switch (argc) {
318
+ case 0:
319
+ oj_str_writer_push_object(sw, 0);
320
+ break;
321
+ case 1:
322
+ if (Qnil == argv[0]) {
323
+ oj_str_writer_push_object(sw, 0);
324
+ } else {
325
+ rb_check_type(argv[0], T_STRING);
326
+ oj_str_writer_push_object(sw, StringValuePtr(argv[0]));
327
+ }
328
+ break;
329
+ default:
330
+ rb_raise(rb_eArgError, "Wrong number of argument to 'push_object'.");
331
+ break;
332
+ }
333
+ if (rb_block_given_p()) {
334
+ rb_yield(Qnil);
335
+ oj_str_writer_pop(sw);
336
+ }
337
+ return Qnil;
338
+ }
339
+
340
+ /* Document-method: push_array
341
+ * call-seq: push_array(key=nil)
342
+ *
343
+ * Pushes an array onto the JSON document. Future pushes will be to this object
344
+ * until a pop() is called.
345
+ * - *key* [_String_] the key if adding to an object in the JSON document
346
+ */
347
+ static VALUE
348
+ str_writer_push_array(int argc, VALUE *argv, VALUE self) {
349
+ StrWriter sw = (StrWriter)DATA_PTR(self);
350
+
351
+ switch (argc) {
352
+ case 0:
353
+ oj_str_writer_push_array(sw, 0);
354
+ break;
355
+ case 1:
356
+ if (Qnil == argv[0]) {
357
+ oj_str_writer_push_array(sw, 0);
358
+ } else {
359
+ rb_check_type(argv[0], T_STRING);
360
+ oj_str_writer_push_array(sw, StringValuePtr(argv[0]));
361
+ }
362
+ break;
363
+ default:
364
+ rb_raise(rb_eArgError, "Wrong number of argument to 'push_object'.");
365
+ break;
366
+ }
367
+ if (rb_block_given_p()) {
368
+ rb_yield(Qnil);
369
+ oj_str_writer_pop(sw);
370
+ }
371
+ return Qnil;
372
+ }
373
+
374
+ /* Document-method: push_value
375
+ * call-seq: push_value(value, key=nil)
376
+ *
377
+ * Pushes a value onto the JSON document.
378
+ * - *value* [_Object_] value to add to the JSON document
379
+ * - *key* [_String_] the key if adding to an object in the JSON document
380
+ */
381
+ static VALUE
382
+ str_writer_push_value(int argc, VALUE *argv, VALUE self) {
383
+ switch (argc) {
384
+ case 1:
385
+ oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, 0);
386
+ break;
387
+ case 2:
388
+ if (Qnil == argv[1]) {
389
+ oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, 0);
390
+ } else {
391
+ rb_check_type(argv[1], T_STRING);
392
+ oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, StringValuePtr(argv[1]));
393
+ }
394
+ break;
395
+ default:
396
+ rb_raise(rb_eArgError, "Wrong number of argument to 'push_value'.");
397
+ break;
398
+ }
399
+ return Qnil;
400
+ }
401
+
402
+ /* Document-method: push_json
403
+ * call-seq: push_json(value, key=nil)
404
+ *
405
+ * Pushes a string onto the JSON document. The String must be a valid JSON
406
+ * encoded string. No additional checking is done to verify the validity of the
407
+ * string.
408
+ * - *value* [_Object_] value to add to the JSON document
409
+ * - *key* [_String_] the key if adding to an object in the JSON document
410
+ */
411
+ static VALUE
412
+ str_writer_push_json(int argc, VALUE *argv, VALUE self) {
413
+ rb_check_type(argv[0], T_STRING);
414
+ switch (argc) {
415
+ case 1:
416
+ oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), 0);
417
+ break;
418
+ case 2:
419
+ if (Qnil == argv[1]) {
420
+ oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), 0);
421
+ } else {
422
+ rb_check_type(argv[1], T_STRING);
423
+ oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), StringValuePtr(argv[1]));
424
+ }
425
+ break;
426
+ default:
427
+ rb_raise(rb_eArgError, "Wrong number of argument to 'push_json'.");
428
+ break;
429
+ }
430
+ return Qnil;
431
+ }
432
+ /* Document-method: pop
433
+ * call-seq: pop()
434
+ *
435
+ * Pops up a level in the JSON document closing the array or object that is
436
+ * currently open.
437
+ */
438
+ static VALUE
439
+ str_writer_pop(VALUE self) {
440
+ oj_str_writer_pop((StrWriter)DATA_PTR(self));
441
+ return Qnil;
442
+ }
443
+
444
+ /* Document-method: pop_all
445
+ * call-seq: pop_all()
446
+ *
447
+ * Pops all level in the JSON document closing all the array or object that is
448
+ * currently open.
449
+ */
450
+ static VALUE
451
+ str_writer_pop_all(VALUE self) {
452
+ oj_str_writer_pop_all((StrWriter)DATA_PTR(self));
453
+
454
+ return Qnil;
455
+ }
456
+
457
+ /* Document-method: reset
458
+ * call-seq: reset()
459
+ *
460
+ * Reset the writer back to the empty state.
461
+ */
462
+ static VALUE
463
+ str_writer_reset(VALUE self) {
464
+ StrWriter sw = (StrWriter)DATA_PTR(self);
465
+
466
+ sw->depth = 0;
467
+ *sw->types = '\0';
468
+ sw->keyWritten = 0;
469
+ sw->out.cur = sw->out.buf;
470
+ *sw->out.cur = '\0';
471
+
472
+ return Qnil;
473
+ }
474
+
475
+ /* Document-method: to_s
476
+ * call-seq: to_s()
477
+ *
478
+ * Returns the JSON document string in what ever state the construction is at.
479
+ *
480
+ * *return* [_String_]
481
+ */
482
+ static VALUE
483
+ str_writer_to_s(VALUE self) {
484
+ StrWriter sw = (StrWriter)DATA_PTR(self);
485
+ VALUE rstr = rb_str_new(sw->out.buf, sw->out.cur - sw->out.buf);
486
+
487
+ return oj_encode(rstr);
488
+ }
489
+
490
+ /* Document-class: Oj::StringWriter
491
+ *
492
+ * Supports building a JSON document one element at a time. Build the document
493
+ * by pushing values into the document. Pushing an array or an object will
494
+ * create that element in the JSON document and subsequent pushes will add the
495
+ * elements to that array or object until a pop() is called. When complete
496
+ * calling to_s() will return the JSON document. Note tha calling to_s() before
497
+ * construction is complete will return the document in it's current state.
498
+ */
499
+ void
500
+ oj_string_writer_init() {
501
+ oj_string_writer_class = rb_define_class_under(Oj, "StringWriter", rb_cObject);
502
+ rb_define_module_function(oj_string_writer_class, "new", str_writer_new, -1);
503
+ rb_define_method(oj_string_writer_class, "push_key", str_writer_push_key, 1);
504
+ rb_define_method(oj_string_writer_class, "push_object", str_writer_push_object, -1);
505
+ rb_define_method(oj_string_writer_class, "push_array", str_writer_push_array, -1);
506
+ rb_define_method(oj_string_writer_class, "push_value", str_writer_push_value, -1);
507
+ rb_define_method(oj_string_writer_class, "push_json", str_writer_push_json, -1);
508
+ rb_define_method(oj_string_writer_class, "pop", str_writer_pop, 0);
509
+ rb_define_method(oj_string_writer_class, "pop_all", str_writer_pop_all, 0);
510
+ rb_define_method(oj_string_writer_class, "reset", str_writer_reset, 0);
511
+ rb_define_method(oj_string_writer_class, "to_s", str_writer_to_s, 0);
512
+ }