oj 3.16.6 → 3.17.3

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 (130) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +81 -0
  3. data/README.md +0 -16
  4. data/ext/oj/compat.c +3 -3
  5. data/ext/oj/custom.c +17 -11
  6. data/ext/oj/dump.c +592 -81
  7. data/ext/oj/dump.h +9 -2
  8. data/ext/oj/dump_compat.c +15 -9
  9. data/ext/oj/dump_leaf.c +1 -1
  10. data/ext/oj/dump_object.c +32 -17
  11. data/ext/oj/dump_strict.c +20 -14
  12. data/ext/oj/extconf.rb +10 -7
  13. data/ext/oj/fast.c +40 -23
  14. data/ext/oj/intern.c +1 -1
  15. data/ext/oj/mimic_json.c +11 -7
  16. data/ext/oj/object.c +8 -8
  17. data/ext/oj/oj.c +256 -10
  18. data/ext/oj/oj.h +55 -52
  19. data/ext/oj/parse.c +243 -46
  20. data/ext/oj/parser.c +113 -37
  21. data/ext/oj/parser.h +2 -0
  22. data/ext/oj/rails.c +41 -36
  23. data/ext/oj/rxclass.c +1 -1
  24. data/ext/oj/rxclass.h +1 -1
  25. data/ext/oj/safe.c +230 -0
  26. data/ext/oj/safe.h +79 -0
  27. data/ext/oj/saj.c +13 -8
  28. data/ext/oj/scp.c +3 -6
  29. data/ext/oj/simd.h +219 -0
  30. data/ext/oj/sparse.c +6 -3
  31. data/ext/oj/stream_writer.c +3 -13
  32. data/ext/oj/strict.c +2 -4
  33. data/ext/oj/string_writer.c +5 -7
  34. data/ext/oj/usual.c +20 -7
  35. data/ext/oj/wab.c +5 -4
  36. data/lib/oj/version.rb +1 -1
  37. data/pages/Encoding.md +1 -1
  38. metadata +22 -114
  39. data/test/_test_active.rb +0 -75
  40. data/test/_test_active_mimic.rb +0 -95
  41. data/test/_test_mimic_rails.rb +0 -123
  42. data/test/activerecord/result_test.rb +0 -31
  43. data/test/activesupport6/abstract_unit.rb +0 -44
  44. data/test/activesupport6/decoding_test.rb +0 -133
  45. data/test/activesupport6/encoding_test.rb +0 -542
  46. data/test/activesupport6/encoding_test_cases.rb +0 -98
  47. data/test/activesupport6/test_common.rb +0 -17
  48. data/test/activesupport6/test_helper.rb +0 -163
  49. data/test/activesupport6/time_zone_test_helpers.rb +0 -39
  50. data/test/activesupport7/abstract_unit.rb +0 -52
  51. data/test/activesupport7/decoding_test.rb +0 -125
  52. data/test/activesupport7/encoding_test.rb +0 -536
  53. data/test/activesupport7/encoding_test_cases.rb +0 -104
  54. data/test/activesupport7/time_zone_test_helpers.rb +0 -47
  55. data/test/files.rb +0 -29
  56. data/test/foo.rb +0 -26
  57. data/test/helper.rb +0 -39
  58. data/test/isolated/shared.rb +0 -309
  59. data/test/isolated/test_mimic_after.rb +0 -13
  60. data/test/isolated/test_mimic_alone.rb +0 -12
  61. data/test/isolated/test_mimic_as_json.rb +0 -45
  62. data/test/isolated/test_mimic_before.rb +0 -13
  63. data/test/isolated/test_mimic_define.rb +0 -28
  64. data/test/isolated/test_mimic_rails_after.rb +0 -22
  65. data/test/isolated/test_mimic_rails_before.rb +0 -21
  66. data/test/isolated/test_mimic_redefine.rb +0 -15
  67. data/test/json_gem/json_addition_test.rb +0 -216
  68. data/test/json_gem/json_common_interface_test.rb +0 -155
  69. data/test/json_gem/json_encoding_test.rb +0 -107
  70. data/test/json_gem/json_ext_parser_test.rb +0 -21
  71. data/test/json_gem/json_fixtures_test.rb +0 -36
  72. data/test/json_gem/json_generator_test.rb +0 -413
  73. data/test/json_gem/json_generic_object_test.rb +0 -90
  74. data/test/json_gem/json_parser_test.rb +0 -477
  75. data/test/json_gem/json_string_matching_test.rb +0 -42
  76. data/test/json_gem/test_helper.rb +0 -30
  77. data/test/mem.rb +0 -34
  78. data/test/perf.rb +0 -102
  79. data/test/perf_compat.rb +0 -128
  80. data/test/perf_dump.rb +0 -50
  81. data/test/perf_fast.rb +0 -162
  82. data/test/perf_file.rb +0 -62
  83. data/test/perf_object.rb +0 -134
  84. data/test/perf_once.rb +0 -59
  85. data/test/perf_parser.rb +0 -183
  86. data/test/perf_saj.rb +0 -101
  87. data/test/perf_scp.rb +0 -140
  88. data/test/perf_simple.rb +0 -289
  89. data/test/perf_strict.rb +0 -137
  90. data/test/perf_wab.rb +0 -129
  91. data/test/prec.rb +0 -23
  92. data/test/sample/change.rb +0 -13
  93. data/test/sample/dir.rb +0 -18
  94. data/test/sample/doc.rb +0 -35
  95. data/test/sample/file.rb +0 -47
  96. data/test/sample/group.rb +0 -15
  97. data/test/sample/hasprops.rb +0 -15
  98. data/test/sample/layer.rb +0 -11
  99. data/test/sample/line.rb +0 -20
  100. data/test/sample/oval.rb +0 -10
  101. data/test/sample/rect.rb +0 -9
  102. data/test/sample/shape.rb +0 -34
  103. data/test/sample/text.rb +0 -19
  104. data/test/sample.rb +0 -54
  105. data/test/sample_json.rb +0 -37
  106. data/test/test_compat.rb +0 -567
  107. data/test/test_custom.rb +0 -555
  108. data/test/test_debian.rb +0 -50
  109. data/test/test_fast.rb +0 -526
  110. data/test/test_file.rb +0 -250
  111. data/test/test_gc.rb +0 -60
  112. data/test/test_generate.rb +0 -21
  113. data/test/test_hash.rb +0 -39
  114. data/test/test_integer_range.rb +0 -72
  115. data/test/test_null.rb +0 -376
  116. data/test/test_object.rb +0 -1030
  117. data/test/test_parser.rb +0 -11
  118. data/test/test_parser_debug.rb +0 -27
  119. data/test/test_parser_saj.rb +0 -337
  120. data/test/test_parser_usual.rb +0 -251
  121. data/test/test_rails.rb +0 -35
  122. data/test/test_saj.rb +0 -188
  123. data/test/test_scp.rb +0 -431
  124. data/test/test_strict.rb +0 -441
  125. data/test/test_various.rb +0 -801
  126. data/test/test_wab.rb +0 -311
  127. data/test/test_writer.rb +0 -380
  128. data/test/tests.rb +0 -33
  129. data/test/tests_mimic.rb +0 -23
  130. data/test/tests_mimic_addition.rb +0 -16
data/ext/oj/parser.c CHANGED
@@ -75,7 +75,7 @@ enum {
75
75
 
76
76
  /*
77
77
  0123456789abcdef0123456789abcdef */
78
- static const char value_map[257] = "\
78
+ static const char value_map[258] = "\
79
79
  X........ab..a..................\
80
80
  a.i..........f..ghhhhhhhhh......\
81
81
  ...........................k.m..\
@@ -85,7 +85,7 @@ a.i..........f..ghhhhhhhhh......\
85
85
  ................................\
86
86
  ................................v";
87
87
 
88
- static const char null_map[257] = "\
88
+ static const char null_map[258] = "\
89
89
  ................................\
90
90
  ............o...................\
91
91
  ................................\
@@ -95,7 +95,7 @@ static const char null_map[257] = "\
95
95
  ................................\
96
96
  ................................N";
97
97
 
98
- static const char true_map[257] = "\
98
+ static const char true_map[258] = "\
99
99
  ................................\
100
100
  ............o...................\
101
101
  ................................\
@@ -105,7 +105,7 @@ static const char true_map[257] = "\
105
105
  ................................\
106
106
  ................................T";
107
107
 
108
- static const char false_map[257] = "\
108
+ static const char false_map[258] = "\
109
109
  ................................\
110
110
  ............o...................\
111
111
  ................................\
@@ -115,7 +115,7 @@ static const char false_map[257] = "\
115
115
  ................................\
116
116
  ................................F";
117
117
 
118
- static const char comma_map[257] = "\
118
+ static const char comma_map[258] = "\
119
119
  .........ab..a..................\
120
120
  a.i..........f..ghhhhhhhhh......\
121
121
  ...........................k....\
@@ -125,7 +125,7 @@ a.i..........f..ghhhhhhhhh......\
125
125
  ................................\
126
126
  ................................,";
127
127
 
128
- static const char after_map[257] = "\
128
+ static const char after_map[258] = "\
129
129
  X........ab..a..................\
130
130
  a...........o...................\
131
131
  .............................m..\
@@ -135,7 +135,7 @@ a...........o...................\
135
135
  ................................\
136
136
  ................................a";
137
137
 
138
- static const char key1_map[257] = "\
138
+ static const char key1_map[258] = "\
139
139
  .........ab..a..................\
140
140
  a.p.............................\
141
141
  ................................\
@@ -145,7 +145,7 @@ a.p.............................\
145
145
  ................................\
146
146
  ................................K";
147
147
 
148
- static const char key_map[257] = "\
148
+ static const char key_map[258] = "\
149
149
  .........ab..a..................\
150
150
  a.p.............................\
151
151
  ................................\
@@ -155,7 +155,7 @@ a.p.............................\
155
155
  ................................\
156
156
  ................................k";
157
157
 
158
- static const char colon_map[257] = "\
158
+ static const char colon_map[258] = "\
159
159
  .........ab..a..................\
160
160
  a.........................q.....\
161
161
  ................................\
@@ -165,7 +165,7 @@ a.........................q.....\
165
165
  ................................\
166
166
  ................................:";
167
167
 
168
- static const char neg_map[257] = "\
168
+ static const char neg_map[258] = "\
169
169
  ................................\
170
170
  ................O---------......\
171
171
  ................................\
@@ -175,7 +175,7 @@ static const char neg_map[257] = "\
175
175
  ................................\
176
176
  ................................-";
177
177
 
178
- static const char zero_map[257] = "\
178
+ static const char zero_map[258] = "\
179
179
  .........rs..r..................\
180
180
  r...........u.t.................\
181
181
  .............................H..\
@@ -185,7 +185,7 @@ r...........u.t.................\
185
185
  ................................\
186
186
  ................................0";
187
187
 
188
- static const char digit_map[257] = "\
188
+ static const char digit_map[258] = "\
189
189
  .........rs..r..................\
190
190
  r...........u.t.NNNNNNNNNN......\
191
191
  .....w.......................H..\
@@ -195,7 +195,7 @@ r...........u.t.NNNNNNNNNN......\
195
195
  ................................\
196
196
  ................................d";
197
197
 
198
- static const char dot_map[257] = "\
198
+ static const char dot_map[258] = "\
199
199
  ................................\
200
200
  ................vvvvvvvvvv......\
201
201
  ................................\
@@ -205,7 +205,7 @@ static const char dot_map[257] = "\
205
205
  ................................\
206
206
  .................................";
207
207
 
208
- static const char frac_map[257] = "\
208
+ static const char frac_map[258] = "\
209
209
  .........rs..r..................\
210
210
  r...........u...vvvvvvvvvv......\
211
211
  .....w.......................H..\
@@ -215,7 +215,7 @@ r...........u...vvvvvvvvvv......\
215
215
  ................................\
216
216
  ................................f";
217
217
 
218
- static const char exp_sign_map[257] = "\
218
+ static const char exp_sign_map[258] = "\
219
219
  ................................\
220
220
  ...........x.x..yyyyyyyyyy......\
221
221
  ................................\
@@ -225,7 +225,7 @@ static const char exp_sign_map[257] = "\
225
225
  ................................\
226
226
  ................................x";
227
227
 
228
- static const char exp_zero_map[257] = "\
228
+ static const char exp_zero_map[258] = "\
229
229
  ................................\
230
230
  ................yyyyyyyyyy......\
231
231
  ................................\
@@ -235,7 +235,7 @@ static const char exp_zero_map[257] = "\
235
235
  ................................\
236
236
  ................................z";
237
237
 
238
- static const char exp_map[257] = "\
238
+ static const char exp_map[258] = "\
239
239
  .........rs..r..................\
240
240
  r...........u...yyyyyyyyyy......\
241
241
  .............................H..\
@@ -245,7 +245,7 @@ r...........u...yyyyyyyyyy......\
245
245
  ................................\
246
246
  ................................X";
247
247
 
248
- static const char big_digit_map[257] = "\
248
+ static const char big_digit_map[258] = "\
249
249
  .........rs..r..................\
250
250
  r...........u.D.CCCCCCCCCC......\
251
251
  .....J.......................H..\
@@ -255,7 +255,7 @@ r...........u.D.CCCCCCCCCC......\
255
255
  ................................\
256
256
  ................................D";
257
257
 
258
- static const char big_dot_map[257] = "\
258
+ static const char big_dot_map[258] = "\
259
259
  ................................\
260
260
  ................IIIIIIIIII......\
261
261
  ................................\
@@ -265,7 +265,7 @@ static const char big_dot_map[257] = "\
265
265
  ................................\
266
266
  ................................o";
267
267
 
268
- static const char big_frac_map[257] = "\
268
+ static const char big_frac_map[258] = "\
269
269
  .........rs..r..................\
270
270
  r...........u...IIIIIIIIII......\
271
271
  .....J.......................H..\
@@ -275,7 +275,7 @@ r...........u...IIIIIIIIII......\
275
275
  ................................\
276
276
  ................................g";
277
277
 
278
- static const char big_exp_sign_map[257] = "\
278
+ static const char big_exp_sign_map[258] = "\
279
279
  ................................\
280
280
  ...........K.K..LLLLLLLLLL......\
281
281
  ................................\
@@ -285,7 +285,7 @@ static const char big_exp_sign_map[257] = "\
285
285
  ................................\
286
286
  ................................B";
287
287
 
288
- static const char big_exp_zero_map[257] = "\
288
+ static const char big_exp_zero_map[258] = "\
289
289
  ................................\
290
290
  ................LLLLLLLLLL......\
291
291
  ................................\
@@ -295,7 +295,7 @@ static const char big_exp_zero_map[257] = "\
295
295
  ................................\
296
296
  ................................Z";
297
297
 
298
- static const char big_exp_map[257] = "\
298
+ static const char big_exp_map[258] = "\
299
299
  .........rs..r..................\
300
300
  r...........u...LLLLLLLLLL......\
301
301
  .............................H..\
@@ -305,7 +305,7 @@ r...........u...LLLLLLLLLL......\
305
305
  ................................\
306
306
  ................................Y";
307
307
 
308
- static const char string_map[257] = "\
308
+ static const char string_map[258] = "\
309
309
  ................................\
310
310
  RRzRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
311
311
  RRRRRRRRRRRRRRRRRRRRRRRRRRRRARRR\
@@ -315,7 +315,7 @@ RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
315
315
  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\
316
316
  PPPPPPPPPPPPPPPPQQQQQQQQ........s";
317
317
 
318
- static const char esc_map[257] = "\
318
+ static const char esc_map[258] = "\
319
319
  ................................\
320
320
  ..B............B................\
321
321
  ............................B...\
@@ -325,7 +325,7 @@ static const char esc_map[257] = "\
325
325
  ................................\
326
326
  ................................~";
327
327
 
328
- static const char esc_byte_map[257] = "\
328
+ static const char esc_byte_map[258] = "\
329
329
  ................................\
330
330
  ..\"............/................\
331
331
  ............................\\...\
@@ -335,7 +335,7 @@ static const char esc_byte_map[257] = "\
335
335
  ................................\
336
336
  ................................b";
337
337
 
338
- static const char u_map[257] = "\
338
+ static const char u_map[258] = "\
339
339
  ................................\
340
340
  ................EEEEEEEEEE......\
341
341
  .EEEEEE.........................\
@@ -345,7 +345,7 @@ static const char u_map[257] = "\
345
345
  ................................\
346
346
  ................................u";
347
347
 
348
- static const char utf_map[257] = "\
348
+ static const char utf_map[258] = "\
349
349
  ................................\
350
350
  ................................\
351
351
  ................................\
@@ -355,7 +355,7 @@ SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS\
355
355
  ................................\
356
356
  ................................8";
357
357
 
358
- static const char space_map[257] = "\
358
+ static const char space_map[258] = "\
359
359
  .........ab..a..................\
360
360
  a...............................\
361
361
  ................................\
@@ -365,7 +365,7 @@ a...............................\
365
365
  ................................\
366
366
  ................................S";
367
367
 
368
- static const char trail_map[257] = "\
368
+ static const char trail_map[258] = "\
369
369
  .........ab..a..................\
370
370
  a...............................\
371
371
  ................................\
@@ -375,7 +375,7 @@ a...............................\
375
375
  ................................\
376
376
  ................................R";
377
377
 
378
- static const byte hex_map[256] = "\
378
+ static const byte hex_map[257] = "\
379
379
  ................................\
380
380
  ................\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09......\
381
381
  .\x0a\x0b\x0c\x0d\x0e\x0f.........................\
@@ -594,7 +594,7 @@ static void big_change(ojParser p) {
594
594
  }
595
595
  }
596
596
 
597
- static void parse(ojParser p, const byte *json) {
597
+ static void parse(ojParser p, const byte *json, bool more) {
598
598
  const byte *start;
599
599
  const byte *b = json;
600
600
  int i;
@@ -635,6 +635,9 @@ static void parse(ojParser p, const byte *json) {
635
635
  if ('"' == *b) {
636
636
  p->map = colon_map;
637
637
  break;
638
+ } else if ('\0' == *b && !more) {
639
+ parse_error(p, "quoted string not terminated");
640
+ break;
638
641
  }
639
642
  b--;
640
643
  p->map = string_map;
@@ -659,6 +662,9 @@ static void parse(ojParser p, const byte *json) {
659
662
  p->funcs[p->stack[p->depth]].add_str(p);
660
663
  p->map = (0 == p->depth) ? value_map : after_map;
661
664
  break;
665
+ } else if ('\0' == *b && !more) {
666
+ parse_error(p, "quoted string not terminated");
667
+ break;
662
668
  }
663
669
  b--;
664
670
  p->map = string_map;
@@ -668,6 +674,10 @@ static void parse(ojParser p, const byte *json) {
668
674
  p->cur = b - json;
669
675
  p->funcs[p->stack[p->depth]].open_object(p);
670
676
  p->depth++;
677
+ if ((int)sizeof(p->stack) <= p->depth) {
678
+ parse_error(p, "too deeply nested");
679
+ break;
680
+ }
671
681
  p->stack[p->depth] = OBJECT_FUN;
672
682
  p->map = key1_map;
673
683
  break;
@@ -690,6 +700,10 @@ static void parse(ojParser p, const byte *json) {
690
700
  p->cur = b - json;
691
701
  p->funcs[p->stack[p->depth]].open_array(p);
692
702
  p->depth++;
703
+ if ((int)sizeof(p->stack) <= p->depth) {
704
+ parse_error(p, "too deeply nested");
705
+ break;
706
+ }
693
707
  p->stack[p->depth] = ARRAY_FUN;
694
708
  p->map = value_map;
695
709
  break;
@@ -1161,7 +1175,7 @@ static void parser_mark(void *ptr) {
1161
1175
  }
1162
1176
  }
1163
1177
 
1164
- static const rb_data_type_t oj_parser_type = {
1178
+ const rb_data_type_t oj_parser_type = {
1165
1179
  "Oj/parser",
1166
1180
  {
1167
1181
  parser_mark,
@@ -1176,6 +1190,8 @@ extern void oj_set_parser_validator(ojParser p);
1176
1190
  extern void oj_set_parser_saj(ojParser p);
1177
1191
  extern void oj_set_parser_usual(ojParser p);
1178
1192
  extern void oj_set_parser_debug(ojParser p);
1193
+ extern void oj_set_parser_safe(ojParser p, VALUE options);
1194
+ extern void oj_safe_init(VALUE parser_class);
1179
1195
 
1180
1196
  static int opt_cb(VALUE rkey, VALUE value, VALUE ptr) {
1181
1197
  ojParser p = (ojParser)ptr;
@@ -1354,6 +1370,34 @@ static VALUE parser_missing(int argc, VALUE *argv, VALUE self) {
1354
1370
  return p->option(p, key, rv);
1355
1371
  }
1356
1372
 
1373
+ static void validate_primitives_are_complete(ojParser p) {
1374
+ if (0 >= p->ri) {
1375
+ return;
1376
+ }
1377
+
1378
+ switch (p->map[256]) {
1379
+ case 'N': parse_error(p, "expected null"); break;
1380
+ case 'F': parse_error(p, "expected false"); break;
1381
+ case 'T': parse_error(p, "expected true"); break;
1382
+ }
1383
+ }
1384
+
1385
+ static void validate_non_primitives_are_complete(ojParser p) {
1386
+ if (0 >= p->depth) {
1387
+ return;
1388
+ }
1389
+ if (OBJECT_FUN == p->stack[p->depth]) {
1390
+ parse_error(p, "Object is not closed");
1391
+ } else {
1392
+ parse_error(p, "Array is not closed");
1393
+ }
1394
+ }
1395
+
1396
+ static void validate_document_end(ojParser p) {
1397
+ validate_primitives_are_complete(p);
1398
+ validate_non_primitives_are_complete(p);
1399
+ }
1400
+
1357
1401
  /* Document-method: parse(json)
1358
1402
  * call-seq: parse(json)
1359
1403
  *
@@ -1363,13 +1407,20 @@ static VALUE parser_missing(int argc, VALUE *argv, VALUE self) {
1363
1407
  */
1364
1408
  static VALUE parser_parse(VALUE self, VALUE json) {
1365
1409
  ojParser p;
1366
- const byte *ptr = (const byte *)StringValuePtr(json);
1410
+ int frozen = OBJ_FROZEN(json);
1411
+ const byte *ptr;
1412
+
1413
+ if (!frozen) {
1414
+ rb_str_freeze(json);
1415
+ }
1416
+ ptr = (const byte *)StringValuePtr(json);
1367
1417
 
1368
1418
  TypedData_Get_Struct(self, struct _ojParser, &oj_parser_type, p);
1369
1419
 
1370
1420
  parser_reset(p);
1371
1421
  p->start(p);
1372
- parse(p, ptr);
1422
+ parse(p, ptr, false);
1423
+ validate_document_end(p);
1373
1424
 
1374
1425
  return p->result(p);
1375
1426
  }
@@ -1389,7 +1440,7 @@ static VALUE load(VALUE self) {
1389
1440
  while (true) {
1390
1441
  rb_funcall(p->reader, oj_readpartial_id, 2, INT2NUM(16385), rbuf);
1391
1442
  if (0 < RSTRING_LEN(rbuf)) {
1392
- parse(p, (byte *)StringValuePtr(rbuf));
1443
+ parse(p, (byte *)StringValuePtr(rbuf), true);
1393
1444
  }
1394
1445
  if (Qtrue == rb_funcall(p->reader, oj_eofq_id, 0)) {
1395
1446
  if (0 < p->depth) {
@@ -1459,7 +1510,7 @@ static VALUE parser_file(VALUE self, VALUE filename) {
1459
1510
  while (true) {
1460
1511
  if (0 < (rsize = read(fd, buf, size))) {
1461
1512
  buf[rsize] = '\0';
1462
- parse(p, buf);
1513
+ parse(p, buf, true);
1463
1514
  }
1464
1515
  if (rsize <= 0) {
1465
1516
  if (0 != rsize) {
@@ -1570,6 +1621,28 @@ static VALUE parser_validate(VALUE self) {
1570
1621
  return validate_parser;
1571
1622
  }
1572
1623
 
1624
+ static VALUE parser_safe(int argc, VALUE *argv, VALUE self) {
1625
+ VALUE options;
1626
+
1627
+ if (1 == argc) {
1628
+ options = argv[0];
1629
+
1630
+ Check_Type(options, T_HASH);
1631
+ } else {
1632
+ options = rb_hash_new();
1633
+ }
1634
+
1635
+ ojParser p = OJ_R_ALLOC(struct _ojParser);
1636
+
1637
+ memset(p, 0, sizeof(struct _ojParser));
1638
+ buf_init(&p->key);
1639
+ buf_init(&p->buf);
1640
+ p->map = value_map;
1641
+ oj_set_parser_safe(p, options);
1642
+
1643
+ return TypedData_Wrap_Struct(parser_class, &oj_parser_type, p);
1644
+ }
1645
+
1573
1646
  /* Document-class: Oj::Parser
1574
1647
  *
1575
1648
  * A reusable parser that makes use of named delegates to determine the
@@ -1597,4 +1670,7 @@ void oj_parser_init(void) {
1597
1670
  rb_define_module_function(parser_class, "usual", parser_usual, 0);
1598
1671
  rb_define_module_function(parser_class, "saj", parser_saj, 0);
1599
1672
  rb_define_module_function(parser_class, "validate", parser_validate, 0);
1673
+ rb_define_module_function(parser_class, "safe", parser_safe, -1);
1674
+
1675
+ oj_safe_init(parser_class);
1600
1676
  }
data/ext/oj/parser.h CHANGED
@@ -42,6 +42,8 @@ typedef struct _num {
42
42
 
43
43
  struct _ojParser;
44
44
 
45
+ extern const rb_data_type_t oj_parser_type;
46
+
45
47
  typedef struct _funcs {
46
48
  void (*add_null)(struct _ojParser *p);
47
49
  void (*add_true)(struct _ojParser *p);
data/ext/oj/rails.c CHANGED
@@ -140,7 +140,7 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
140
140
  volatile VALUE v;
141
141
  int cnt;
142
142
  int i;
143
- int len;
143
+ size_t len;
144
144
  const char *name;
145
145
 
146
146
  #ifdef RSTRUCT_LEN
@@ -161,7 +161,7 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
161
161
  volatile VALUE s = rb_sym2str(RARRAY_AREF(ma, i));
162
162
 
163
163
  name = RSTRING_PTR(s);
164
- len = (int)RSTRING_LEN(s);
164
+ len = RSTRING_LEN(s);
165
165
  assure_size(out, size + sep_len + 6);
166
166
  if (0 < i) {
167
167
  *out->cur++ = ',';
@@ -205,11 +205,11 @@ static void dump_bigdecimal(VALUE obj, int depth, Out out, bool as_ok) {
205
205
  if ('I' == *str || 'N' == *str || ('-' == *str && 'I' == str[1])) {
206
206
  oj_dump_nil(Qnil, depth, out, false);
207
207
  } else if (out->opts->int_range_max != 0 || out->opts->int_range_min != 0) {
208
- oj_dump_cstr(str, (int)RSTRING_LEN(rstr), 0, 0, out);
208
+ oj_dump_cstr(str, RSTRING_LEN(rstr), 0, 0, out);
209
209
  } else if (Yes == out->opts->bigdec_as_num) {
210
- oj_dump_raw(str, (int)RSTRING_LEN(rstr), out);
210
+ oj_dump_raw(str, RSTRING_LEN(rstr), out);
211
211
  } else {
212
- oj_dump_cstr(str, (int)RSTRING_LEN(rstr), 0, 0, out);
212
+ oj_dump_cstr(str, RSTRING_LEN(rstr), 0, 0, out);
213
213
  }
214
214
  }
215
215
 
@@ -330,14 +330,14 @@ static void dump_timewithzone(VALUE obj, int depth, Out out, bool as_ok) {
330
330
  static void dump_to_s(VALUE obj, int depth, Out out, bool as_ok) {
331
331
  volatile VALUE rstr = oj_safe_string_convert(obj);
332
332
 
333
- oj_dump_cstr(RSTRING_PTR(rstr), (int)RSTRING_LEN(rstr), 0, 0, out);
333
+ oj_dump_cstr(RSTRING_PTR(rstr), RSTRING_LEN(rstr), 0, 0, out);
334
334
  }
335
335
 
336
336
  static ID parameters_id = 0;
337
337
 
338
338
  typedef struct _strLen {
339
339
  const char *str;
340
- int len;
340
+ size_t len;
341
341
  } *StrLen;
342
342
 
343
343
  static void dump_actioncontroller_parameters(VALUE obj, int depth, Out out, bool as_ok) {
@@ -352,10 +352,10 @@ static StrLen columns_array(VALUE rcols, int *ccnt) {
352
352
  volatile VALUE v;
353
353
  StrLen cp;
354
354
  StrLen cols;
355
- int i;
356
- int cnt = (int)RARRAY_LEN(rcols);
355
+ size_t i;
356
+ size_t cnt = RARRAY_LEN(rcols);
357
357
 
358
- *ccnt = cnt;
358
+ *ccnt = (int)cnt;
359
359
  cols = OJ_R_ALLOC_N(struct _strLen, cnt);
360
360
  for (i = 0, cp = cols; i < cnt; i++, cp++) {
361
361
  v = RARRAY_AREF(rcols, i);
@@ -363,7 +363,7 @@ static StrLen columns_array(VALUE rcols, int *ccnt) {
363
363
  v = oj_safe_string_convert(v);
364
364
  }
365
365
  cp->str = StringValuePtr(v);
366
- cp->len = (int)RSTRING_LEN(v);
366
+ cp->len = RSTRING_LEN(v);
367
367
  }
368
368
  return cols;
369
369
  }
@@ -424,7 +424,8 @@ static void dump_activerecord_result(VALUE obj, int depth, Out out, bool as_ok)
424
424
  volatile VALUE rows;
425
425
  StrLen cols;
426
426
  int ccnt = 0;
427
- int i, rcnt;
427
+ size_t i;
428
+ size_t rcnt;
428
429
  size_t size;
429
430
  int d2 = depth + 1;
430
431
 
@@ -435,7 +436,7 @@ static void dump_activerecord_result(VALUE obj, int depth, Out out, bool as_ok)
435
436
  out->argc = 0;
436
437
  cols = columns_array(rb_ivar_get(obj, columns_id), &ccnt);
437
438
  rows = rb_ivar_get(obj, rows_id);
438
- rcnt = (int)RARRAY_LEN(rows);
439
+ rcnt = RARRAY_LEN(rows);
439
440
  assure_size(out, 2);
440
441
  *out->cur++ = '[';
441
442
  if (out->opts->dump_opts.use) {
@@ -660,13 +661,15 @@ static VALUE encoder_new(int argc, VALUE *argv, VALUE self) {
660
661
  Encoder e = OJ_R_ALLOC(struct _encoder);
661
662
 
662
663
  e->opts = oj_default_options;
663
- e->arg = Qnil;
664
664
  copy_opts(&ropts, &e->ropts);
665
665
 
666
666
  if (1 <= argc && Qnil != *argv) {
667
- oj_parse_options(*argv, &e->opts);
668
667
  e->arg = *argv;
668
+ } else {
669
+ e->arg = rb_hash_new();
669
670
  }
671
+ oj_parse_options(e->arg, &e->opts);
672
+
670
673
  return TypedData_Wrap_Struct(encoder_class, &oj_encoder_type, e);
671
674
  }
672
675
 
@@ -917,7 +920,7 @@ static VALUE encode(VALUE obj, ROptTable ropts, Options opts, int argc, VALUE *a
917
920
  if (Yes == copts.circular) {
918
921
  oj_cache8_new(&out.circ_cache);
919
922
  }
920
- // dump_rails_val(*argv, 0, &out, true);
923
+
921
924
  rb_protect(protect_dump, (VALUE)&oo, &line);
922
925
 
923
926
  if (0 == line) {
@@ -933,8 +936,7 @@ static VALUE encode(VALUE obj, ROptTable ropts, Options opts, int argc, VALUE *a
933
936
  if (0 == out.buf) {
934
937
  rb_raise(rb_eNoMemError, "Not enough memory.");
935
938
  }
936
- rstr = rb_str_new2(out.buf);
937
- rstr = oj_encode(rstr);
939
+ rstr = rb_utf8_str_new_cstr(out.buf);
938
940
  }
939
941
  if (Yes == copts.circular) {
940
942
  oj_cache8_delete(out.circ_cache);
@@ -1101,6 +1103,8 @@ static VALUE rails_set_decoder(VALUE self) {
1101
1103
  } else {
1102
1104
  json_error = rb_define_class_under(json, "JSONError", rb_eStandardError);
1103
1105
  }
1106
+
1107
+ rb_global_variable(&oj_json_parser_error_class);
1104
1108
  if (rb_const_defined_at(json, rb_intern("ParserError"))) {
1105
1109
  oj_json_parser_error_class = rb_const_get(json, rb_intern("ParserError"));
1106
1110
  } else {
@@ -1172,7 +1176,7 @@ static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
1172
1176
  char buf[64];
1173
1177
  char *b;
1174
1178
  double d = rb_num2dbl(obj);
1175
- int cnt = 0;
1179
+ size_t cnt = 0;
1176
1180
 
1177
1181
  if (0.0 == d) {
1178
1182
  b = buf;
@@ -1193,7 +1197,7 @@ static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
1193
1197
  volatile VALUE rstr = oj_safe_string_convert(obj);
1194
1198
 
1195
1199
  strcpy(buf, RSTRING_PTR(rstr));
1196
- cnt = (int)RSTRING_LEN(rstr);
1200
+ cnt = RSTRING_LEN(rstr);
1197
1201
  }
1198
1202
  }
1199
1203
  assure_size(out, cnt);
@@ -1205,7 +1209,8 @@ static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
1205
1209
 
1206
1210
  static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
1207
1211
  size_t size;
1208
- int i, cnt;
1212
+ size_t i;
1213
+ size_t cnt;
1209
1214
  int d2 = depth + 1;
1210
1215
 
1211
1216
  if (Yes == out->opts->circular) {
@@ -1214,12 +1219,11 @@ static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
1214
1219
  return;
1215
1220
  }
1216
1221
  }
1217
- // if (!oj_rails_array_opt && as_ok && 0 < out->argc && rb_respond_to(a, oj_as_json_id)) {
1218
- if (as_ok && 0 < out->argc && rb_respond_to(a, oj_as_json_id)) {
1222
+ if (!oj_rails_array_opt && as_ok && rb_respond_to(a, oj_as_json_id)) {
1219
1223
  dump_as_json(a, depth, out, false);
1220
1224
  return;
1221
1225
  }
1222
- cnt = (int)RARRAY_LEN(a);
1226
+ cnt = RARRAY_LEN(a);
1223
1227
  *out->cur++ = '[';
1224
1228
  size = 2;
1225
1229
  assure_size(out, size);
@@ -1282,18 +1286,19 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
1282
1286
  if (out->omit_nil && Qnil == value) {
1283
1287
  return ST_CONTINUE;
1284
1288
  }
1285
- if (rtype != T_STRING && rtype != T_SYMBOL) {
1286
- key = oj_safe_string_convert(key);
1287
- rtype = rb_type(key);
1289
+ if (NULL != out->opts->dump_opts.only || NULL != out->opts->dump_opts.except) {
1290
+ if (oj_key_skip(key, out->opts->dump_opts.only, out->opts->dump_opts.except)) {
1291
+ return ST_CONTINUE;
1292
+ }
1288
1293
  }
1289
1294
  if (!out->opts->dump_opts.use) {
1290
1295
  size = depth * out->indent + 1;
1291
1296
  assure_size(out, size);
1292
1297
  fill_indent(out, depth);
1293
- if (rtype == T_STRING) {
1294
- oj_dump_str(key, 0, out, false);
1295
- } else {
1296
- oj_dump_sym(key, 0, out, false);
1298
+ switch (rtype) {
1299
+ case T_STRING: oj_dump_str(key, 0, out, false); break;
1300
+ case T_SYMBOL: oj_dump_sym(key, 0, out, false); break;
1301
+ default: oj_dump_str(oj_safe_string_convert(key), 0, out, false); break;
1297
1302
  }
1298
1303
  *out->cur++ = ':';
1299
1304
  } else {
@@ -1308,10 +1313,10 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
1308
1313
  APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
1309
1314
  }
1310
1315
  }
1311
- if (rtype == T_STRING) {
1312
- oj_dump_str(key, 0, out, false);
1313
- } else {
1314
- oj_dump_sym(key, 0, out, false);
1316
+ switch (rtype) {
1317
+ case T_STRING: oj_dump_str(key, 0, out, false); break;
1318
+ case T_SYMBOL: oj_dump_sym(key, 0, out, false); break;
1319
+ default: oj_dump_str(oj_safe_string_convert(key), 0, out, false); break;
1315
1320
  }
1316
1321
  size = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
1317
1322
  assure_size(out, size);
@@ -1340,7 +1345,7 @@ static void dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
1340
1345
  return;
1341
1346
  }
1342
1347
  }
1343
- if ((!oj_rails_hash_opt || 0 < out->argc) && as_ok && rb_respond_to(obj, oj_as_json_id)) {
1348
+ if (!oj_rails_hash_opt && as_ok && rb_respond_to(obj, oj_as_json_id)) {
1344
1349
  dump_as_json(obj, depth, out, false);
1345
1350
  return;
1346
1351
  }
data/ext/oj/rxclass.c CHANGED
@@ -96,7 +96,7 @@ int oj_rxclass_append(RxClass rc, const char *expr, VALUE clas) {
96
96
  }
97
97
 
98
98
  VALUE
99
- oj_rxclass_match(RxClass rc, const char *str, int len) {
99
+ oj_rxclass_match(RxClass rc, const char *str, size_t len) {
100
100
  RxC rxc;
101
101
  char buf[4096];
102
102