oj 2.0.0 → 3.0.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.
Files changed (133) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +17 -23
  3. data/README.md +74 -425
  4. data/ext/oj/buf.h +103 -0
  5. data/ext/oj/cache8.c +4 -0
  6. data/ext/oj/circarray.c +68 -0
  7. data/ext/oj/circarray.h +23 -0
  8. data/ext/oj/code.c +227 -0
  9. data/ext/oj/code.h +40 -0
  10. data/ext/oj/compat.c +243 -0
  11. data/ext/oj/custom.c +1097 -0
  12. data/ext/oj/dump.c +766 -1534
  13. data/ext/oj/dump.h +92 -0
  14. data/ext/oj/dump_compat.c +937 -0
  15. data/ext/oj/dump_leaf.c +254 -0
  16. data/ext/oj/dump_object.c +810 -0
  17. data/ext/oj/dump_rails.c +329 -0
  18. data/ext/oj/dump_strict.c +416 -0
  19. data/ext/oj/encode.h +51 -0
  20. data/ext/oj/err.c +57 -0
  21. data/ext/oj/err.h +70 -0
  22. data/ext/oj/extconf.rb +17 -7
  23. data/ext/oj/fast.c +213 -180
  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 +817 -0
  28. data/ext/oj/mimic_rails.c +806 -0
  29. data/ext/oj/mimic_rails.h +17 -0
  30. data/ext/oj/object.c +752 -0
  31. data/ext/oj/odd.c +230 -0
  32. data/ext/oj/odd.h +44 -0
  33. data/ext/oj/oj.c +1288 -929
  34. data/ext/oj/oj.h +240 -69
  35. data/ext/oj/parse.c +1014 -0
  36. data/ext/oj/parse.h +92 -0
  37. data/ext/oj/reader.c +223 -0
  38. data/ext/oj/reader.h +151 -0
  39. data/ext/oj/resolve.c +127 -0
  40. data/ext/oj/{cache.h → resolve.h} +6 -13
  41. data/ext/oj/rxclass.c +133 -0
  42. data/ext/oj/rxclass.h +27 -0
  43. data/ext/oj/saj.c +77 -175
  44. data/ext/oj/scp.c +224 -0
  45. data/ext/oj/sparse.c +911 -0
  46. data/ext/oj/stream_writer.c +301 -0
  47. data/ext/oj/strict.c +162 -0
  48. data/ext/oj/string_writer.c +480 -0
  49. data/ext/oj/val_stack.c +98 -0
  50. data/ext/oj/val_stack.h +188 -0
  51. data/lib/oj/active_support_helper.rb +41 -0
  52. data/lib/oj/bag.rb +6 -10
  53. data/lib/oj/easy_hash.rb +52 -0
  54. data/lib/oj/json.rb +172 -0
  55. data/lib/oj/mimic.rb +260 -5
  56. data/lib/oj/saj.rb +13 -10
  57. data/lib/oj/schandler.rb +142 -0
  58. data/lib/oj/state.rb +131 -0
  59. data/lib/oj/version.rb +1 -1
  60. data/lib/oj.rb +11 -23
  61. data/pages/Advanced.md +22 -0
  62. data/pages/Compatibility.md +25 -0
  63. data/pages/Custom.md +23 -0
  64. data/pages/Encoding.md +65 -0
  65. data/pages/JsonGem.md +79 -0
  66. data/pages/Modes.md +140 -0
  67. data/pages/Options.md +250 -0
  68. data/pages/Rails.md +60 -0
  69. data/pages/Security.md +20 -0
  70. data/test/_test_active.rb +76 -0
  71. data/test/_test_active_mimic.rb +96 -0
  72. data/test/_test_mimic_rails.rb +126 -0
  73. data/test/activesupport4/decoding_test.rb +105 -0
  74. data/test/activesupport4/encoding_test.rb +531 -0
  75. data/test/activesupport4/test_helper.rb +41 -0
  76. data/test/activesupport5/decoding_test.rb +125 -0
  77. data/test/activesupport5/encoding_test.rb +483 -0
  78. data/test/activesupport5/encoding_test_cases.rb +90 -0
  79. data/test/activesupport5/test_helper.rb +50 -0
  80. data/test/activesupport5/time_zone_test_helpers.rb +24 -0
  81. data/test/helper.rb +27 -0
  82. data/test/isolated/shared.rb +310 -0
  83. data/test/isolated/test_mimic_after.rb +13 -0
  84. data/test/isolated/test_mimic_alone.rb +12 -0
  85. data/test/isolated/test_mimic_as_json.rb +45 -0
  86. data/test/isolated/test_mimic_before.rb +13 -0
  87. data/test/isolated/test_mimic_define.rb +28 -0
  88. data/test/isolated/test_mimic_rails_after.rb +22 -0
  89. data/test/isolated/test_mimic_rails_before.rb +21 -0
  90. data/test/isolated/test_mimic_redefine.rb +15 -0
  91. data/test/json_gem/json_addition_test.rb +216 -0
  92. data/test/json_gem/json_common_interface_test.rb +143 -0
  93. data/test/json_gem/json_encoding_test.rb +109 -0
  94. data/test/json_gem/json_ext_parser_test.rb +20 -0
  95. data/test/json_gem/json_fixtures_test.rb +35 -0
  96. data/test/json_gem/json_generator_test.rb +383 -0
  97. data/test/json_gem/json_generic_object_test.rb +90 -0
  98. data/test/json_gem/json_parser_test.rb +470 -0
  99. data/test/json_gem/json_string_matching_test.rb +42 -0
  100. data/test/json_gem/test_helper.rb +18 -0
  101. data/test/perf_compat.rb +130 -0
  102. data/test/perf_fast.rb +9 -9
  103. data/test/perf_file.rb +64 -0
  104. data/test/{perf_obj.rb → perf_object.rb} +24 -10
  105. data/test/perf_scp.rb +151 -0
  106. data/test/perf_strict.rb +32 -113
  107. data/test/sample.rb +2 -3
  108. data/test/test_compat.rb +474 -0
  109. data/test/test_custom.rb +355 -0
  110. data/test/test_debian.rb +53 -0
  111. data/test/test_fast.rb +66 -16
  112. data/test/test_file.rb +237 -0
  113. data/test/test_gc.rb +49 -0
  114. data/test/test_hash.rb +29 -0
  115. data/test/test_null.rb +376 -0
  116. data/test/test_object.rb +1010 -0
  117. data/test/test_saj.rb +16 -16
  118. data/test/test_scp.rb +417 -0
  119. data/test/test_strict.rb +410 -0
  120. data/test/test_various.rb +815 -0
  121. data/test/test_writer.rb +308 -0
  122. data/test/tests.rb +9 -902
  123. data/test/tests_mimic.rb +14 -0
  124. data/test/tests_mimic_addition.rb +7 -0
  125. metadata +253 -38
  126. data/ext/oj/cache.c +0 -148
  127. data/ext/oj/foo.rb +0 -6
  128. data/ext/oj/load.c +0 -1049
  129. data/test/a.rb +0 -38
  130. data/test/perf1.rb +0 -64
  131. data/test/perf2.rb +0 -76
  132. data/test/perf_obj_old.rb +0 -213
  133. data/test/test_mimic.rb +0 -208
@@ -0,0 +1,301 @@
1
+ /* stream_writer.c
2
+ * Copyright (c) 2012, 2017, Peter Ohler
3
+ * All rights reserved.
4
+ */
5
+
6
+ #include <errno.h>
7
+
8
+ #include <ruby.h>
9
+
10
+ #include "oj.h"
11
+
12
+ extern VALUE Oj;
13
+
14
+ static void
15
+ stream_writer_free(void *ptr) {
16
+ StreamWriter sw;
17
+
18
+ if (0 == ptr) {
19
+ return;
20
+ }
21
+ sw = (StreamWriter)ptr;
22
+ xfree(sw->sw.out.buf);
23
+ xfree(sw->sw.types);
24
+ xfree(ptr);
25
+ }
26
+
27
+ static void
28
+ stream_writer_write(StreamWriter sw) {
29
+ ssize_t size = sw->sw.out.cur - sw->sw.out.buf;
30
+
31
+ switch (sw->type) {
32
+ case STRING_IO:
33
+ rb_funcall(sw->stream, oj_write_id, 1, rb_str_new(sw->sw.out.buf, size));
34
+ break;
35
+ case STREAM_IO:
36
+ rb_funcall(sw->stream, oj_write_id, 1, rb_str_new(sw->sw.out.buf, size));
37
+ break;
38
+ case FILE_IO:
39
+ if (size != write(sw->fd, sw->sw.out.buf, size)) {
40
+ rb_raise(rb_eIOError, "Write failed. [_%d_:%s]\n", errno, strerror(errno));
41
+ }
42
+ break;
43
+ default:
44
+ rb_raise(rb_eArgError, "expected an IO Object.");
45
+ }
46
+ }
47
+
48
+ static void
49
+ stream_writer_reset_buf(StreamWriter sw) {
50
+ sw->sw.out.cur = sw->sw.out.buf;
51
+ *sw->sw.out.cur = '\0';
52
+ }
53
+
54
+ /* Document-method: new
55
+ * call-seq: new(io, options)
56
+ *
57
+ * Creates a new StreamWriter.
58
+ * - *io* [_IO_] stream to write to
59
+ * - *options* [_Hash_] formating options
60
+ */
61
+ static VALUE
62
+ stream_writer_new(int argc, VALUE *argv, VALUE self) {
63
+ StreamWriterType type = STREAM_IO;
64
+ int fd = 0;
65
+ VALUE stream = argv[0];
66
+ VALUE clas = rb_obj_class(stream);
67
+ StreamWriter sw;
68
+ #if !IS_WINDOWS
69
+ VALUE s;
70
+ #endif
71
+
72
+ if (oj_stringio_class == clas) {
73
+ type = STRING_IO;
74
+ #if !IS_WINDOWS
75
+ } else if (rb_respond_to(stream, oj_fileno_id) &&
76
+ Qnil != (s = rb_funcall(stream, oj_fileno_id, 0)) &&
77
+ 0 != (fd = FIX2INT(s))) {
78
+ type = FILE_IO;
79
+ #endif
80
+ } else if (rb_respond_to(stream, oj_write_id)) {
81
+ type = STREAM_IO;
82
+ } else {
83
+ rb_raise(rb_eArgError, "expected an IO Object.");
84
+ }
85
+ sw = ALLOC(struct _StreamWriter);
86
+ oj_str_writer_init(&sw->sw);
87
+ if (2 == argc) {
88
+ oj_parse_options(argv[1], &sw->sw.opts);
89
+ }
90
+ sw->sw.out.indent = sw->sw.opts.indent;
91
+ sw->stream = stream;
92
+ sw->type = type;
93
+ sw->fd = fd;
94
+
95
+ return Data_Wrap_Struct(oj_stream_writer_class, 0, stream_writer_free, sw);
96
+ }
97
+
98
+ /* Document-method: push_key
99
+ * call-seq: push_key(key)
100
+ *
101
+ * Pushes a key onto the JSON document. The key will be used for the next push
102
+ * if currently in a JSON object and ignored otherwise. If a key is provided on
103
+ * the next push then that new key will be ignored.
104
+ * - *key* [_String_] the key pending for the next push
105
+ */
106
+ static VALUE
107
+ stream_writer_push_key(VALUE self, VALUE key) {
108
+ StreamWriter sw = (StreamWriter)DATA_PTR(self);
109
+
110
+ rb_check_type(key, T_STRING);
111
+ stream_writer_reset_buf(sw);
112
+ oj_str_writer_push_key(&sw->sw, StringValuePtr(key));
113
+ stream_writer_write(sw);
114
+ return Qnil;
115
+ }
116
+
117
+ /* Document-method: push_object
118
+ * call-seq: push_object(key=nil)
119
+ *
120
+ * Pushes an object onto the JSON document. Future pushes will be to this object
121
+ * until a pop() is called.
122
+ * - *key* [_String_] the key if adding to an object in the JSON document
123
+ */
124
+ static VALUE
125
+ stream_writer_push_object(int argc, VALUE *argv, VALUE self) {
126
+ StreamWriter sw = (StreamWriter)DATA_PTR(self);
127
+
128
+ stream_writer_reset_buf(sw);
129
+ switch (argc) {
130
+ case 0:
131
+ oj_str_writer_push_object(&sw->sw, 0);
132
+ break;
133
+ case 1:
134
+ if (Qnil == argv[0]) {
135
+ oj_str_writer_push_object(&sw->sw, 0);
136
+ } else {
137
+ rb_check_type(argv[0], T_STRING);
138
+ oj_str_writer_push_object(&sw->sw, StringValuePtr(argv[0]));
139
+ }
140
+ break;
141
+ default:
142
+ rb_raise(rb_eArgError, "Wrong number of argument to 'push_object'.");
143
+ break;
144
+ }
145
+ stream_writer_write(sw);
146
+ return Qnil;
147
+ }
148
+
149
+ /* Document-method: push_array
150
+ * call-seq: push_array(key=nil)
151
+ *
152
+ * Pushes an array onto the JSON document. Future pushes will be to this object
153
+ * until a pop() is called.
154
+ * - *key* [_String_] the key if adding to an object in the JSON document
155
+ */
156
+ static VALUE
157
+ stream_writer_push_array(int argc, VALUE *argv, VALUE self) {
158
+ StreamWriter sw = (StreamWriter)DATA_PTR(self);
159
+
160
+ stream_writer_reset_buf(sw);
161
+ switch (argc) {
162
+ case 0:
163
+ oj_str_writer_push_array(&sw->sw, 0);
164
+ break;
165
+ case 1:
166
+ if (Qnil == argv[0]) {
167
+ oj_str_writer_push_array(&sw->sw, 0);
168
+ } else {
169
+ rb_check_type(argv[0], T_STRING);
170
+ oj_str_writer_push_array(&sw->sw, StringValuePtr(argv[0]));
171
+ }
172
+ break;
173
+ default:
174
+ rb_raise(rb_eArgError, "Wrong number of argument to 'push_object'.");
175
+ break;
176
+ }
177
+ stream_writer_write(sw);
178
+ return Qnil;
179
+ }
180
+
181
+ /* Document-method: push_value
182
+ * call-seq: push_value(value, key=nil)
183
+ *
184
+ * Pushes a value onto the JSON document.
185
+ * - *value* [_Object_] value to add to the JSON document
186
+ * - *key* [_String_] the key if adding to an object in the JSON document
187
+ */
188
+ static VALUE
189
+ stream_writer_push_value(int argc, VALUE *argv, VALUE self) {
190
+ StreamWriter sw = (StreamWriter)DATA_PTR(self);
191
+
192
+ stream_writer_reset_buf(sw);
193
+ switch (argc) {
194
+ case 1:
195
+ oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, 0);
196
+ break;
197
+ case 2:
198
+ if (Qnil == argv[1]) {
199
+ oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, 0);
200
+ } else {
201
+ rb_check_type(argv[1], T_STRING);
202
+ oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, StringValuePtr(argv[1]));
203
+ }
204
+ break;
205
+ default:
206
+ rb_raise(rb_eArgError, "Wrong number of argument to 'push_value'.");
207
+ break;
208
+ }
209
+ stream_writer_write(sw);
210
+ return Qnil;
211
+ }
212
+
213
+ /* Document-method: push_json
214
+ * call-seq: push_json(value, key=nil)
215
+ *
216
+ * Pushes a string onto the JSON document. The String must be a valid JSON
217
+ * encoded string. No additional checking is done to verify the validity of the
218
+ * string.
219
+ * - *value* [_Object_] value to add to the JSON document
220
+ * - *key* [_String_] the key if adding to an object in the JSON document
221
+ */
222
+ static VALUE
223
+ stream_writer_push_json(int argc, VALUE *argv, VALUE self) {
224
+ StreamWriter sw = (StreamWriter)DATA_PTR(self);
225
+
226
+ rb_check_type(argv[0], T_STRING);
227
+ stream_writer_reset_buf(sw);
228
+ switch (argc) {
229
+ case 1:
230
+ oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), 0);
231
+ break;
232
+ case 2:
233
+ if (Qnil == argv[0]) {
234
+ oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), 0);
235
+ } else {
236
+ rb_check_type(argv[1], T_STRING);
237
+ oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), StringValuePtr(argv[1]));
238
+ }
239
+ break;
240
+ default:
241
+ rb_raise(rb_eArgError, "Wrong number of argument to 'push_json'.");
242
+ break;
243
+ }
244
+ stream_writer_write(sw);
245
+ return Qnil;
246
+ }
247
+
248
+ /* Document-method: pop
249
+ * call-seq: pop()
250
+ *
251
+ * Pops up a level in the JSON document closing the array or object that is
252
+ * currently open.
253
+ */
254
+ static VALUE
255
+ stream_writer_pop(VALUE self) {
256
+ StreamWriter sw = (StreamWriter)DATA_PTR(self);
257
+
258
+ stream_writer_reset_buf(sw);
259
+ oj_str_writer_pop(&sw->sw);
260
+ stream_writer_write(sw);
261
+ return Qnil;
262
+ }
263
+
264
+ /* Document-method: pop_all
265
+ * call-seq: pop_all()
266
+ *
267
+ * Pops all level in the JSON document closing all the array or object that is
268
+ * currently open.
269
+ */
270
+ static VALUE
271
+ stream_writer_pop_all(VALUE self) {
272
+ StreamWriter sw = (StreamWriter)DATA_PTR(self);
273
+
274
+ stream_writer_reset_buf(sw);
275
+ oj_str_writer_pop_all(&sw->sw);
276
+ stream_writer_write(sw);
277
+
278
+ return Qnil;
279
+ }
280
+
281
+ /* Document-class: Oj::StreamWriter
282
+ *
283
+ * Supports building a JSON document one element at a time. Build the IO stream
284
+ * document by pushing values into the document. Pushing an array or an object
285
+ * will create that element in the JSON document and subsequent pushes will add
286
+ * the elements to that array or object until a pop() is called.
287
+ */
288
+ void
289
+ oj_stream_writer_init() {
290
+ oj_stream_writer_class = rb_define_class_under(Oj, "StreamWriter", rb_cObject);
291
+ rb_define_module_function(oj_stream_writer_class, "new", stream_writer_new, -1);
292
+ rb_define_method(oj_stream_writer_class, "push_key", stream_writer_push_key, 1);
293
+ rb_define_method(oj_stream_writer_class, "push_object", stream_writer_push_object, -1);
294
+ rb_define_method(oj_stream_writer_class, "push_array", stream_writer_push_array, -1);
295
+ rb_define_method(oj_stream_writer_class, "push_value", stream_writer_push_value, -1);
296
+ rb_define_method(oj_stream_writer_class, "push_json", stream_writer_push_json, -1);
297
+ rb_define_method(oj_stream_writer_class, "pop", stream_writer_pop, 0);
298
+ rb_define_method(oj_stream_writer_class, "pop_all", stream_writer_pop_all, 0);
299
+ }
300
+
301
+
data/ext/oj/strict.c ADDED
@@ -0,0 +1,162 @@
1
+ /* strict.c
2
+ * Copyright (c) 2012, Peter Ohler
3
+ * All rights reserved.
4
+ */
5
+
6
+ #include <stdlib.h>
7
+ #include <stdio.h>
8
+ #include <string.h>
9
+ #include <unistd.h>
10
+
11
+ #include "oj.h"
12
+ #include "err.h"
13
+ #include "parse.h"
14
+ #include "encode.h"
15
+
16
+ static void
17
+ noop_end(struct _ParseInfo *pi) {
18
+ }
19
+
20
+ static VALUE
21
+ noop_hash_key(struct _ParseInfo *pi, const char *key, size_t klen) {
22
+ return Qundef;
23
+ }
24
+
25
+ static void
26
+ add_value(ParseInfo pi, VALUE val) {
27
+ pi->stack.head->val = val;
28
+ }
29
+
30
+ static void
31
+ add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
32
+ volatile VALUE rstr = rb_str_new(str, len);
33
+
34
+ rstr = oj_encode(rstr);
35
+ pi->stack.head->val = rstr;
36
+ }
37
+
38
+ static void
39
+ add_num(ParseInfo pi, NumInfo ni) {
40
+ if (ni->infinity || ni->nan) {
41
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
42
+ }
43
+ pi->stack.head->val = oj_num_as_value(ni);
44
+ }
45
+
46
+ static VALUE
47
+ start_hash(ParseInfo pi) {
48
+ if (Qnil != pi->options.hash_class) {
49
+ return rb_class_new_instance(0, NULL, pi->options.hash_class);
50
+ }
51
+ return rb_hash_new();
52
+ }
53
+
54
+ static VALUE
55
+ calc_hash_key(ParseInfo pi, Val parent) {
56
+ volatile VALUE rkey = parent->key_val;
57
+
58
+ if (Qundef == rkey) {
59
+ rkey = rb_str_new(parent->key, parent->klen);
60
+ }
61
+ rkey = oj_encode(rkey);
62
+ if (Yes == pi->options.sym_key) {
63
+ rkey = rb_str_intern(rkey);
64
+ }
65
+ return rkey;
66
+ }
67
+
68
+ static void
69
+ hash_set_cstr(ParseInfo pi, Val parent, const char *str, size_t len, const char *orig) {
70
+ volatile VALUE rstr = rb_str_new(str, len);
71
+
72
+ rstr = oj_encode(rstr);
73
+ rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), rstr);
74
+ }
75
+
76
+ static void
77
+ hash_set_num(struct _ParseInfo *pi, Val parent, NumInfo ni) {
78
+ if (ni->infinity || ni->nan) {
79
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
80
+ }
81
+ rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), oj_num_as_value(ni));
82
+ }
83
+
84
+ static void
85
+ hash_set_value(ParseInfo pi, Val parent, VALUE value) {
86
+ rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), value);
87
+ }
88
+
89
+ static VALUE
90
+ start_array(ParseInfo pi) {
91
+ return rb_ary_new();
92
+ }
93
+
94
+ static void
95
+ array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
96
+ volatile VALUE rstr = rb_str_new(str, len);
97
+
98
+ rstr = oj_encode(rstr);
99
+ rb_ary_push(stack_peek(&pi->stack)->val, rstr);
100
+ }
101
+
102
+ static void
103
+ array_append_num(ParseInfo pi, NumInfo ni) {
104
+ if (ni->infinity || ni->nan) {
105
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
106
+ }
107
+ rb_ary_push(stack_peek(&pi->stack)->val, oj_num_as_value(ni));
108
+ }
109
+
110
+ static void
111
+ array_append_value(ParseInfo pi, VALUE value) {
112
+ rb_ary_push(stack_peek(&pi->stack)->val, value);
113
+ }
114
+
115
+ void
116
+ oj_set_strict_callbacks(ParseInfo pi) {
117
+ pi->start_hash = start_hash;
118
+ pi->end_hash = noop_end;
119
+ pi->hash_key = noop_hash_key;
120
+ pi->hash_set_cstr = hash_set_cstr;
121
+ pi->hash_set_num = hash_set_num;
122
+ pi->hash_set_value = hash_set_value;
123
+ pi->start_array = start_array;
124
+ pi->end_array = noop_end;
125
+ pi->array_append_cstr = array_append_cstr;
126
+ pi->array_append_num = array_append_num;
127
+ pi->array_append_value = array_append_value;
128
+ pi->add_cstr = add_cstr;
129
+ pi->add_num = add_num;
130
+ pi->add_value = add_value;
131
+ pi->expect_value = 1;
132
+ }
133
+
134
+ VALUE
135
+ oj_strict_parse(int argc, VALUE *argv, VALUE self) {
136
+ struct _ParseInfo pi;
137
+
138
+ parse_info_init(&pi);
139
+ pi.options = oj_default_options;
140
+ pi.handler = Qnil;
141
+ pi.err_class = Qnil;
142
+ oj_set_strict_callbacks(&pi);
143
+
144
+ if (T_STRING == rb_type(*argv)) {
145
+ return oj_pi_parse(argc, argv, &pi, 0, 0, true);
146
+ } else {
147
+ return oj_pi_sparse(argc, argv, &pi, 0);
148
+ }
149
+ }
150
+
151
+ VALUE
152
+ oj_strict_parse_cstr(int argc, VALUE *argv, char *json, size_t len) {
153
+ struct _ParseInfo pi;
154
+
155
+ parse_info_init(&pi);
156
+ pi.options = oj_default_options;
157
+ pi.handler = Qnil;
158
+ pi.err_class = Qnil;
159
+ oj_set_strict_callbacks(&pi);
160
+
161
+ return oj_pi_parse(argc, argv, &pi, json, len, true);
162
+ }