oj 3.16.0 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +107 -0
- data/README.md +0 -16
- data/ext/oj/cache.c +4 -2
- data/ext/oj/cache.h +3 -2
- data/ext/oj/compat.c +3 -3
- data/ext/oj/custom.c +17 -11
- data/ext/oj/dump.c +624 -90
- data/ext/oj/dump.h +9 -2
- data/ext/oj/dump_compat.c +15 -9
- data/ext/oj/dump_leaf.c +1 -1
- data/ext/oj/dump_object.c +32 -17
- data/ext/oj/dump_strict.c +20 -14
- data/ext/oj/extconf.rb +11 -9
- data/ext/oj/fast.c +50 -32
- data/ext/oj/intern.c +24 -7
- data/ext/oj/mimic_json.c +17 -11
- data/ext/oj/object.c +21 -13
- data/ext/oj/oj.c +387 -140
- data/ext/oj/oj.h +59 -55
- data/ext/oj/parse.c +248 -47
- data/ext/oj/parser.c +179 -89
- data/ext/oj/parser.h +4 -2
- data/ext/oj/rails.c +64 -42
- data/ext/oj/reader.c +1 -1
- data/ext/oj/rxclass.c +1 -1
- data/ext/oj/rxclass.h +1 -1
- data/ext/oj/safe.c +230 -0
- data/ext/oj/safe.h +79 -0
- data/ext/oj/saj.c +15 -10
- data/ext/oj/scp.c +3 -6
- data/ext/oj/simd.h +219 -0
- data/ext/oj/sparse.c +6 -3
- data/ext/oj/stream_writer.c +38 -28
- data/ext/oj/strict.c +2 -4
- data/ext/oj/string_writer.c +54 -22
- data/ext/oj/usual.c +57 -35
- data/ext/oj/usual.h +1 -0
- data/ext/oj/val_stack.c +13 -2
- data/ext/oj/wab.c +5 -4
- data/lib/oj/mimic.rb +1 -5
- data/lib/oj/schandler.rb +5 -4
- data/lib/oj/version.rb +1 -1
- data/pages/Encoding.md +1 -1
- metadata +36 -100
- data/test/_test_active.rb +0 -75
- data/test/_test_active_mimic.rb +0 -95
- data/test/_test_mimic_rails.rb +0 -123
- data/test/activerecord/result_test.rb +0 -31
- data/test/activesupport6/abstract_unit.rb +0 -44
- data/test/activesupport6/decoding_test.rb +0 -133
- data/test/activesupport6/encoding_test.rb +0 -507
- data/test/activesupport6/encoding_test_cases.rb +0 -98
- data/test/activesupport6/test_common.rb +0 -17
- data/test/activesupport6/test_helper.rb +0 -163
- data/test/activesupport6/time_zone_test_helpers.rb +0 -39
- data/test/activesupport7/abstract_unit.rb +0 -49
- data/test/activesupport7/decoding_test.rb +0 -125
- data/test/activesupport7/encoding_test.rb +0 -486
- data/test/activesupport7/encoding_test_cases.rb +0 -104
- data/test/activesupport7/time_zone_test_helpers.rb +0 -47
- data/test/files.rb +0 -29
- data/test/foo.rb +0 -14
- data/test/helper.rb +0 -39
- data/test/isolated/shared.rb +0 -309
- data/test/isolated/test_mimic_after.rb +0 -13
- data/test/isolated/test_mimic_alone.rb +0 -12
- data/test/isolated/test_mimic_as_json.rb +0 -45
- data/test/isolated/test_mimic_before.rb +0 -13
- data/test/isolated/test_mimic_define.rb +0 -28
- data/test/isolated/test_mimic_rails_after.rb +0 -22
- data/test/isolated/test_mimic_rails_before.rb +0 -21
- data/test/isolated/test_mimic_redefine.rb +0 -15
- data/test/json_gem/json_addition_test.rb +0 -216
- data/test/json_gem/json_common_interface_test.rb +0 -155
- data/test/json_gem/json_encoding_test.rb +0 -107
- data/test/json_gem/json_ext_parser_test.rb +0 -21
- data/test/json_gem/json_fixtures_test.rb +0 -36
- data/test/json_gem/json_generator_test.rb +0 -407
- data/test/json_gem/json_generic_object_test.rb +0 -90
- data/test/json_gem/json_parser_test.rb +0 -477
- data/test/json_gem/json_string_matching_test.rb +0 -42
- data/test/json_gem/test_helper.rb +0 -30
- data/test/mem.rb +0 -34
- data/test/perf.rb +0 -102
- data/test/perf_compat.rb +0 -128
- data/test/perf_dump.rb +0 -50
- data/test/perf_fast.rb +0 -162
- data/test/perf_file.rb +0 -62
- data/test/perf_object.rb +0 -134
- data/test/perf_once.rb +0 -59
- data/test/perf_parser.rb +0 -183
- data/test/perf_saj.rb +0 -101
- data/test/perf_scp.rb +0 -140
- data/test/perf_simple.rb +0 -289
- data/test/perf_strict.rb +0 -137
- data/test/perf_wab.rb +0 -129
- data/test/prec.rb +0 -23
- data/test/sample/change.rb +0 -13
- data/test/sample/dir.rb +0 -18
- data/test/sample/doc.rb +0 -35
- data/test/sample/file.rb +0 -47
- data/test/sample/group.rb +0 -15
- data/test/sample/hasprops.rb +0 -15
- data/test/sample/layer.rb +0 -11
- data/test/sample/line.rb +0 -20
- data/test/sample/oval.rb +0 -10
- data/test/sample/rect.rb +0 -9
- data/test/sample/shape.rb +0 -34
- data/test/sample/text.rb +0 -19
- data/test/sample.rb +0 -54
- data/test/sample_json.rb +0 -37
- data/test/test_compat.rb +0 -567
- data/test/test_custom.rb +0 -554
- data/test/test_debian.rb +0 -50
- data/test/test_fast.rb +0 -526
- data/test/test_file.rb +0 -250
- data/test/test_gc.rb +0 -60
- data/test/test_generate.rb +0 -21
- data/test/test_hash.rb +0 -39
- data/test/test_integer_range.rb +0 -72
- data/test/test_null.rb +0 -376
- data/test/test_object.rb +0 -1016
- data/test/test_parser.rb +0 -11
- data/test/test_parser_debug.rb +0 -27
- data/test/test_parser_saj.rb +0 -337
- data/test/test_parser_usual.rb +0 -217
- data/test/test_rails.rb +0 -35
- data/test/test_saj.rb +0 -188
- data/test/test_scp.rb +0 -431
- data/test/test_strict.rb +0 -431
- data/test/test_various.rb +0 -801
- data/test/test_wab.rb +0 -311
- data/test/test_writer.rb +0 -380
- data/test/tests.rb +0 -33
- data/test/tests_mimic.rb +0 -23
- data/test/tests_mimic_addition.rb +0 -16
data/ext/oj/string_writer.c
CHANGED
|
@@ -225,7 +225,7 @@ void oj_str_writer_pop_all(StrWriter sw) {
|
|
|
225
225
|
}
|
|
226
226
|
}
|
|
227
227
|
|
|
228
|
-
static void
|
|
228
|
+
static void string_writer_free(void *ptr) {
|
|
229
229
|
StrWriter sw;
|
|
230
230
|
|
|
231
231
|
if (0 == ptr) {
|
|
@@ -239,6 +239,23 @@ static void str_writer_free(void *ptr) {
|
|
|
239
239
|
OJ_R_FREE(ptr);
|
|
240
240
|
}
|
|
241
241
|
|
|
242
|
+
static const rb_data_type_t oj_string_writer_type = {
|
|
243
|
+
"Oj/string_writer",
|
|
244
|
+
{
|
|
245
|
+
NULL,
|
|
246
|
+
string_writer_free,
|
|
247
|
+
NULL,
|
|
248
|
+
},
|
|
249
|
+
0,
|
|
250
|
+
0,
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
StrWriter oj_str_writer_unwrap(VALUE writer) {
|
|
254
|
+
StrWriter sw;
|
|
255
|
+
TypedData_Get_Struct(writer, struct _strWriter, &oj_string_writer_type, sw);
|
|
256
|
+
return sw;
|
|
257
|
+
}
|
|
258
|
+
|
|
242
259
|
/* Document-method: new
|
|
243
260
|
* call-seq: new(io, options)
|
|
244
261
|
*
|
|
@@ -266,7 +283,7 @@ static VALUE str_writer_new(int argc, VALUE *argv, VALUE self) {
|
|
|
266
283
|
sw->out.argv = argv + 1;
|
|
267
284
|
sw->out.indent = sw->opts.indent;
|
|
268
285
|
|
|
269
|
-
return
|
|
286
|
+
return TypedData_Wrap_Struct(oj_string_writer_class, &oj_string_writer_type, sw);
|
|
270
287
|
}
|
|
271
288
|
|
|
272
289
|
/* Document-method: push_key
|
|
@@ -278,7 +295,8 @@ static VALUE str_writer_new(int argc, VALUE *argv, VALUE self) {
|
|
|
278
295
|
* - *key* [_String_] the key pending for the next push
|
|
279
296
|
*/
|
|
280
297
|
static VALUE str_writer_push_key(VALUE self, VALUE key) {
|
|
281
|
-
StrWriter sw
|
|
298
|
+
StrWriter sw;
|
|
299
|
+
TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
|
|
282
300
|
|
|
283
301
|
oj_str_writer_push_key(sw, StringValuePtr(key));
|
|
284
302
|
|
|
@@ -293,7 +311,8 @@ static VALUE str_writer_push_key(VALUE self, VALUE key) {
|
|
|
293
311
|
* - *key* [_String_] the key if adding to an object in the JSON document
|
|
294
312
|
*/
|
|
295
313
|
static VALUE str_writer_push_object(int argc, VALUE *argv, VALUE self) {
|
|
296
|
-
StrWriter sw
|
|
314
|
+
StrWriter sw;
|
|
315
|
+
TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
|
|
297
316
|
|
|
298
317
|
switch (argc) {
|
|
299
318
|
case 0: oj_str_writer_push_object(sw, 0); break;
|
|
@@ -321,7 +340,8 @@ static VALUE str_writer_push_object(int argc, VALUE *argv, VALUE self) {
|
|
|
321
340
|
* - *key* [_String_] the key if adding to an object in the JSON document
|
|
322
341
|
*/
|
|
323
342
|
static VALUE str_writer_push_array(int argc, VALUE *argv, VALUE self) {
|
|
324
|
-
StrWriter sw
|
|
343
|
+
StrWriter sw;
|
|
344
|
+
TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
|
|
325
345
|
|
|
326
346
|
switch (argc) {
|
|
327
347
|
case 0: oj_str_writer_push_array(sw, 0); break;
|
|
@@ -349,13 +369,16 @@ static VALUE str_writer_push_array(int argc, VALUE *argv, VALUE self) {
|
|
|
349
369
|
* - *key* [_String_] the key if adding to an object in the JSON document
|
|
350
370
|
*/
|
|
351
371
|
static VALUE str_writer_push_value(int argc, VALUE *argv, VALUE self) {
|
|
372
|
+
StrWriter sw;
|
|
373
|
+
TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
|
|
374
|
+
|
|
352
375
|
switch (argc) {
|
|
353
|
-
case 1: oj_str_writer_push_value(
|
|
376
|
+
case 1: oj_str_writer_push_value(sw, *argv, 0); break;
|
|
354
377
|
case 2:
|
|
355
378
|
if (Qnil == argv[1]) {
|
|
356
|
-
oj_str_writer_push_value(
|
|
379
|
+
oj_str_writer_push_value(sw, *argv, 0);
|
|
357
380
|
} else {
|
|
358
|
-
oj_str_writer_push_value(
|
|
381
|
+
oj_str_writer_push_value(sw, *argv, StringValuePtr(argv[1]));
|
|
359
382
|
}
|
|
360
383
|
break;
|
|
361
384
|
default: rb_raise(rb_eArgError, "Wrong number of argument to 'push_value'."); break;
|
|
@@ -373,13 +396,16 @@ static VALUE str_writer_push_value(int argc, VALUE *argv, VALUE self) {
|
|
|
373
396
|
* - *key* [_String_] the key if adding to an object in the JSON document
|
|
374
397
|
*/
|
|
375
398
|
static VALUE str_writer_push_json(int argc, VALUE *argv, VALUE self) {
|
|
399
|
+
StrWriter sw;
|
|
400
|
+
TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
|
|
401
|
+
|
|
376
402
|
switch (argc) {
|
|
377
|
-
case 1: oj_str_writer_push_json(
|
|
403
|
+
case 1: oj_str_writer_push_json(sw, StringValuePtr(*argv), 0); break;
|
|
378
404
|
case 2:
|
|
379
405
|
if (Qnil == argv[1]) {
|
|
380
|
-
oj_str_writer_push_json(
|
|
406
|
+
oj_str_writer_push_json(sw, StringValuePtr(*argv), 0);
|
|
381
407
|
} else {
|
|
382
|
-
oj_str_writer_push_json(
|
|
408
|
+
oj_str_writer_push_json(sw, StringValuePtr(*argv), StringValuePtr(argv[1]));
|
|
383
409
|
}
|
|
384
410
|
break;
|
|
385
411
|
default: rb_raise(rb_eArgError, "Wrong number of argument to 'push_json'."); break;
|
|
@@ -393,7 +419,10 @@ static VALUE str_writer_push_json(int argc, VALUE *argv, VALUE self) {
|
|
|
393
419
|
* currently open.
|
|
394
420
|
*/
|
|
395
421
|
static VALUE str_writer_pop(VALUE self) {
|
|
396
|
-
|
|
422
|
+
StrWriter sw;
|
|
423
|
+
TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
|
|
424
|
+
|
|
425
|
+
oj_str_writer_pop(sw);
|
|
397
426
|
return Qnil;
|
|
398
427
|
}
|
|
399
428
|
|
|
@@ -404,7 +433,10 @@ static VALUE str_writer_pop(VALUE self) {
|
|
|
404
433
|
* currently open.
|
|
405
434
|
*/
|
|
406
435
|
static VALUE str_writer_pop_all(VALUE self) {
|
|
407
|
-
|
|
436
|
+
StrWriter sw;
|
|
437
|
+
TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
|
|
438
|
+
|
|
439
|
+
oj_str_writer_pop_all(sw);
|
|
408
440
|
|
|
409
441
|
return Qnil;
|
|
410
442
|
}
|
|
@@ -415,7 +447,8 @@ static VALUE str_writer_pop_all(VALUE self) {
|
|
|
415
447
|
* Reset the writer back to the empty state.
|
|
416
448
|
*/
|
|
417
449
|
static VALUE str_writer_reset(VALUE self) {
|
|
418
|
-
StrWriter sw
|
|
450
|
+
StrWriter sw;
|
|
451
|
+
TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
|
|
419
452
|
|
|
420
453
|
sw->depth = 0;
|
|
421
454
|
*sw->types = '\0';
|
|
@@ -434,23 +467,22 @@ static VALUE str_writer_reset(VALUE self) {
|
|
|
434
467
|
* *return* [_String_]
|
|
435
468
|
*/
|
|
436
469
|
static VALUE str_writer_to_s(VALUE self) {
|
|
437
|
-
StrWriter sw
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
return oj_encode(rstr);
|
|
470
|
+
StrWriter sw;
|
|
471
|
+
TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
|
|
472
|
+
return rb_utf8_str_new(sw->out.buf, sw->out.cur - sw->out.buf);
|
|
441
473
|
}
|
|
442
474
|
|
|
443
475
|
/* Document-method: as_json
|
|
444
|
-
* call-seq: as_json()
|
|
476
|
+
* call-seq: as_json(*)
|
|
445
477
|
*
|
|
446
478
|
* Returns the contents of the writer as a JSON element. If called from inside
|
|
447
479
|
* an array or hash by Oj the raw buffer will be used othersize a more
|
|
448
480
|
* inefficient parse of the contents and a return of the result is
|
|
449
|
-
* completed. The parse uses the strict mode.
|
|
481
|
+
* completed. The parse uses the strict mode. Optional arguments are ignored.
|
|
450
482
|
*
|
|
451
483
|
* *return* [_Hash_|_Array_|_String_|_Integer_|_Float_|_True_|_False_|_nil|)
|
|
452
484
|
*/
|
|
453
|
-
static VALUE str_writer_as_json(VALUE self) {
|
|
485
|
+
static VALUE str_writer_as_json(int argc, VALUE *argv, VALUE self) {
|
|
454
486
|
if (string_writer_optimized) {
|
|
455
487
|
return self;
|
|
456
488
|
}
|
|
@@ -481,5 +513,5 @@ void oj_string_writer_init(void) {
|
|
|
481
513
|
rb_define_method(oj_string_writer_class, "reset", str_writer_reset, 0);
|
|
482
514
|
rb_define_method(oj_string_writer_class, "to_s", str_writer_to_s, 0);
|
|
483
515
|
rb_define_method(oj_string_writer_class, "raw_json", str_writer_to_s, 0);
|
|
484
|
-
rb_define_method(oj_string_writer_class, "as_json", str_writer_as_json,
|
|
516
|
+
rb_define_method(oj_string_writer_class, "as_json", str_writer_as_json, -1);
|
|
485
517
|
}
|
data/ext/oj/usual.c
CHANGED
|
@@ -63,7 +63,7 @@ static VALUE form_attr(const char *str, size_t len) {
|
|
|
63
63
|
memcpy(b + 1, str, len);
|
|
64
64
|
b[len + 1] = '\0';
|
|
65
65
|
|
|
66
|
-
id = rb_intern3(
|
|
66
|
+
id = rb_intern3(b, len + 1, oj_utf8_encoding);
|
|
67
67
|
OJ_R_FREE(b);
|
|
68
68
|
return id;
|
|
69
69
|
}
|
|
@@ -200,7 +200,10 @@ static void push_key(ojParser p) {
|
|
|
200
200
|
d->ktail = d->khead + pos;
|
|
201
201
|
d->kend = d->khead + cap;
|
|
202
202
|
}
|
|
203
|
-
|
|
203
|
+
if (32000 < klen) {
|
|
204
|
+
rb_raise(oj_json_parser_error_class, "Key too long. Keys are limited to 32,000 bytes.");
|
|
205
|
+
}
|
|
206
|
+
d->ktail->len = (int16_t)klen;
|
|
204
207
|
if (klen < sizeof(d->ktail->buf)) {
|
|
205
208
|
memcpy(d->ktail->buf, key, klen);
|
|
206
209
|
d->ktail->buf[klen] = '\0';
|
|
@@ -281,7 +284,6 @@ static void close_object(ojParser p) {
|
|
|
281
284
|
VALUE *head = d->vhead + c->vi + 1;
|
|
282
285
|
volatile VALUE obj = rb_hash_new();
|
|
283
286
|
|
|
284
|
-
#if HAVE_RB_HASH_BULK_INSERT
|
|
285
287
|
for (vp = head; kp < d->ktail; kp++, vp += 2) {
|
|
286
288
|
*vp = d->get_key(p, kp);
|
|
287
289
|
if (sizeof(kp->buf) <= (size_t)kp->len) {
|
|
@@ -289,18 +291,15 @@ static void close_object(ojParser p) {
|
|
|
289
291
|
}
|
|
290
292
|
}
|
|
291
293
|
rb_hash_bulk_insert(d->vtail - head, head, obj);
|
|
292
|
-
#else
|
|
293
|
-
for (vp = head; kp < d->ktail; kp++, vp += 2) {
|
|
294
|
-
rb_hash_aset(obj, d->get_key(p, kp), *(vp + 1));
|
|
295
|
-
if (sizeof(kp->buf) <= (size_t)kp->len) {
|
|
296
|
-
OJ_R_FREE(kp->key);
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
#endif
|
|
300
294
|
d->ktail = d->khead + c->ki;
|
|
295
|
+
|
|
301
296
|
d->vtail = head;
|
|
302
297
|
head--;
|
|
303
298
|
*head = obj;
|
|
299
|
+
if (1 == d->vtail - d->vhead && rb_block_given_p()) {
|
|
300
|
+
d->vtail = d->vhead;
|
|
301
|
+
rb_yield(obj);
|
|
302
|
+
}
|
|
304
303
|
}
|
|
305
304
|
|
|
306
305
|
static void close_object_class(ojParser p) {
|
|
@@ -341,7 +340,6 @@ static void close_object_create(ojParser p) {
|
|
|
341
340
|
head++;
|
|
342
341
|
if (Qnil == d->hash_class) {
|
|
343
342
|
obj = rb_hash_new();
|
|
344
|
-
#if HAVE_RB_HASH_BULK_INSERT
|
|
345
343
|
for (vp = head; kp < d->ktail; kp++, vp += 2) {
|
|
346
344
|
*vp = d->get_key(p, kp);
|
|
347
345
|
if (sizeof(kp->buf) <= (size_t)kp->len) {
|
|
@@ -349,14 +347,6 @@ static void close_object_create(ojParser p) {
|
|
|
349
347
|
}
|
|
350
348
|
}
|
|
351
349
|
rb_hash_bulk_insert(d->vtail - head, head, obj);
|
|
352
|
-
#else
|
|
353
|
-
for (vp = head; kp < d->ktail; kp++, vp += 2) {
|
|
354
|
-
rb_hash_aset(obj, d->get_key(p, kp), *(vp + 1));
|
|
355
|
-
if (sizeof(kp->buf) <= (size_t)kp->len) {
|
|
356
|
-
OJ_R_FREE(kp->key);
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
#endif
|
|
360
350
|
} else {
|
|
361
351
|
obj = rb_class_new_instance(0, NULL, d->hash_class);
|
|
362
352
|
for (vp = head; kp < d->ktail; kp++, vp += 2) {
|
|
@@ -373,7 +363,6 @@ static void close_object_create(ojParser p) {
|
|
|
373
363
|
if (!d->ignore_json_create && rb_respond_to(clas, oj_json_create_id)) {
|
|
374
364
|
volatile VALUE arg = rb_hash_new();
|
|
375
365
|
|
|
376
|
-
#if HAVE_RB_HASH_BULK_INSERT
|
|
377
366
|
for (vp = head; kp < d->ktail; kp++, vp += 2) {
|
|
378
367
|
*vp = d->get_key(p, kp);
|
|
379
368
|
if (sizeof(kp->buf) <= (size_t)kp->len) {
|
|
@@ -381,14 +370,6 @@ static void close_object_create(ojParser p) {
|
|
|
381
370
|
}
|
|
382
371
|
}
|
|
383
372
|
rb_hash_bulk_insert(d->vtail - head, head, arg);
|
|
384
|
-
#else
|
|
385
|
-
for (vp = head; kp < d->ktail; kp++, vp += 2) {
|
|
386
|
-
rb_hash_aset(arg, d->get_key(p, kp), *(vp + 1));
|
|
387
|
-
if (sizeof(kp->buf) <= (size_t)kp->len) {
|
|
388
|
-
OJ_R_FREE(kp->key);
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
#endif
|
|
392
373
|
obj = rb_funcall(clas, oj_json_create_id, 1, arg);
|
|
393
374
|
} else {
|
|
394
375
|
obj = rb_class_new_instance(0, NULL, clas);
|
|
@@ -599,7 +580,21 @@ static VALUE result(ojParser p) {
|
|
|
599
580
|
Usual d = (Usual)p->ctx;
|
|
600
581
|
|
|
601
582
|
if (d->vhead < d->vtail) {
|
|
602
|
-
|
|
583
|
+
long cnt = d->vtail - d->vhead;
|
|
584
|
+
volatile VALUE ary;
|
|
585
|
+
volatile VALUE *vp;
|
|
586
|
+
|
|
587
|
+
if (1 == cnt) {
|
|
588
|
+
return *d->vhead;
|
|
589
|
+
}
|
|
590
|
+
ary = rb_ary_new();
|
|
591
|
+
for (vp = d->vhead; vp < d->vtail; vp++) {
|
|
592
|
+
rb_ary_push(ary, *vp);
|
|
593
|
+
}
|
|
594
|
+
return ary;
|
|
595
|
+
}
|
|
596
|
+
if (d->raise_on_empty) {
|
|
597
|
+
rb_raise(oj_parse_error_class, "empty string");
|
|
603
598
|
}
|
|
604
599
|
return Qnil;
|
|
605
600
|
}
|
|
@@ -616,12 +611,16 @@ static void dfree(ojParser p) {
|
|
|
616
611
|
Usual d = (Usual)p->ctx;
|
|
617
612
|
|
|
618
613
|
cache_free(d->str_cache);
|
|
614
|
+
d->str_cache = NULL;
|
|
619
615
|
cache_free(d->attr_cache);
|
|
616
|
+
d->attr_cache = NULL;
|
|
620
617
|
if (NULL != d->sym_cache) {
|
|
621
618
|
cache_free(d->sym_cache);
|
|
619
|
+
d->sym_cache = NULL;
|
|
622
620
|
}
|
|
623
621
|
if (NULL != d->class_cache) {
|
|
624
622
|
cache_free(d->class_cache);
|
|
623
|
+
d->class_cache = NULL;
|
|
625
624
|
}
|
|
626
625
|
OJ_R_FREE(d->vhead);
|
|
627
626
|
OJ_R_FREE(d->chead);
|
|
@@ -648,6 +647,12 @@ static void mark(ojParser p) {
|
|
|
648
647
|
if (NULL != d->class_cache) {
|
|
649
648
|
cache_mark(d->class_cache);
|
|
650
649
|
}
|
|
650
|
+
if (Qnil != d->hash_class) {
|
|
651
|
+
rb_gc_mark(d->hash_class);
|
|
652
|
+
}
|
|
653
|
+
if (Qnil != d->array_class) {
|
|
654
|
+
rb_gc_mark(d->array_class);
|
|
655
|
+
}
|
|
651
656
|
for (vp = d->vhead; vp < d->vtail; vp++) {
|
|
652
657
|
if (Qundef != *vp) {
|
|
653
658
|
rb_gc_mark(*vp);
|
|
@@ -842,8 +847,8 @@ static VALUE opt_create_id_set(ojParser p, VALUE value) {
|
|
|
842
847
|
rb_check_type(value, T_STRING);
|
|
843
848
|
size_t len = RSTRING_LEN(value);
|
|
844
849
|
|
|
845
|
-
if (1 << sizeof(d->create_id_len) <= len) {
|
|
846
|
-
rb_raise(rb_eArgError, "The create_id values is limited to %d bytes.", 1 << sizeof(d->create_id_len));
|
|
850
|
+
if (1 << (8 * sizeof(d->create_id_len)) <= len) {
|
|
851
|
+
rb_raise(rb_eArgError, "The create_id values is limited to %d bytes.", 1 << (8 * sizeof(d->create_id_len)));
|
|
847
852
|
}
|
|
848
853
|
d->create_id_len = (uint8_t)len;
|
|
849
854
|
d->create_id = str_dup(RSTRING_PTR(value), len);
|
|
@@ -1058,14 +1063,28 @@ static VALUE opt_symbol_keys_set(ojParser p, VALUE value) {
|
|
|
1058
1063
|
if (NULL != d->sym_cache) {
|
|
1059
1064
|
cache_free(d->sym_cache);
|
|
1060
1065
|
d->sym_cache = NULL;
|
|
1066
|
+
d->key_cache = NULL;
|
|
1061
1067
|
}
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
}
|
|
1068
|
+
d->cache_keys = false;
|
|
1069
|
+
d->get_key = str_key;
|
|
1065
1070
|
}
|
|
1066
1071
|
return (NULL != d->sym_cache) ? Qtrue : Qfalse;
|
|
1067
1072
|
}
|
|
1068
1073
|
|
|
1074
|
+
static VALUE opt_raise_on_empty(ojParser p, VALUE value) {
|
|
1075
|
+
Usual d = (Usual)p->ctx;
|
|
1076
|
+
|
|
1077
|
+
return d->raise_on_empty ? Qtrue : Qfalse;
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
static VALUE opt_raise_on_empty_set(ojParser p, VALUE value) {
|
|
1081
|
+
Usual d = (Usual)p->ctx;
|
|
1082
|
+
|
|
1083
|
+
d->raise_on_empty = (Qtrue == value);
|
|
1084
|
+
|
|
1085
|
+
return d->raise_on_empty ? Qtrue : Qfalse;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1069
1088
|
static VALUE option(ojParser p, const char *key, VALUE value) {
|
|
1070
1089
|
struct opt *op;
|
|
1071
1090
|
struct opt opts[] = {
|
|
@@ -1095,6 +1114,8 @@ static VALUE option(ojParser p, const char *key, VALUE value) {
|
|
|
1095
1114
|
{.name = "omit_null=", .func = opt_omit_null_set},
|
|
1096
1115
|
{.name = "symbol_keys", .func = opt_symbol_keys},
|
|
1097
1116
|
{.name = "symbol_keys=", .func = opt_symbol_keys_set},
|
|
1117
|
+
{.name = "raise_on_empty", .func = opt_raise_on_empty},
|
|
1118
|
+
{.name = "raise_on_empty=", .func = opt_raise_on_empty_set},
|
|
1098
1119
|
{.name = NULL},
|
|
1099
1120
|
};
|
|
1100
1121
|
|
|
@@ -1129,6 +1150,7 @@ void oj_init_usual(ojParser p, Usual d) {
|
|
|
1129
1150
|
d->get_key = cache_key;
|
|
1130
1151
|
d->cache_keys = true;
|
|
1131
1152
|
d->ignore_json_create = false;
|
|
1153
|
+
d->raise_on_empty = false;
|
|
1132
1154
|
d->cache_str = 6;
|
|
1133
1155
|
d->array_class = Qnil;
|
|
1134
1156
|
d->hash_class = Qnil;
|
data/ext/oj/usual.h
CHANGED
data/ext/oj/val_stack.c
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
#include "odd.h"
|
|
9
9
|
#include "oj.h"
|
|
10
10
|
|
|
11
|
-
static void
|
|
11
|
+
static void stack_mark(void *ptr) {
|
|
12
12
|
ValStack stack = (ValStack)ptr;
|
|
13
13
|
Val v;
|
|
14
14
|
|
|
@@ -46,6 +46,17 @@ static void mark(void *ptr) {
|
|
|
46
46
|
#endif
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
static const rb_data_type_t oj_stack_type = {
|
|
50
|
+
"Oj/stack",
|
|
51
|
+
{
|
|
52
|
+
stack_mark,
|
|
53
|
+
NULL,
|
|
54
|
+
NULL,
|
|
55
|
+
},
|
|
56
|
+
0,
|
|
57
|
+
0,
|
|
58
|
+
};
|
|
59
|
+
|
|
49
60
|
VALUE
|
|
50
61
|
oj_stack_init(ValStack stack) {
|
|
51
62
|
#ifdef HAVE_PTHREAD_MUTEX_INIT
|
|
@@ -70,7 +81,7 @@ oj_stack_init(ValStack stack) {
|
|
|
70
81
|
stack->head->clen = 0;
|
|
71
82
|
stack->head->next = NEXT_NONE;
|
|
72
83
|
|
|
73
|
-
return
|
|
84
|
+
return TypedData_Wrap_Struct(oj_cstack_class, &oj_stack_type, stack);
|
|
74
85
|
}
|
|
75
86
|
|
|
76
87
|
const char *oj_stack_next_string(ValNext n) {
|
data/ext/oj/wab.c
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
// Workaround in case INFINITY is not defined in math.h or if the OS is CentOS
|
|
20
20
|
#define OJ_INFINITY (1.0 / 0.0)
|
|
21
21
|
|
|
22
|
-
static char hex_chars[
|
|
22
|
+
static char hex_chars[257] = "\
|
|
23
23
|
................................\
|
|
24
24
|
................xxxxxxxxxx......\
|
|
25
25
|
.xxxxxx.........................\
|
|
@@ -111,10 +111,11 @@ static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
111
111
|
|
|
112
112
|
static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
|
|
113
113
|
size_t size;
|
|
114
|
-
|
|
114
|
+
size_t i;
|
|
115
|
+
size_t cnt;
|
|
115
116
|
int d2 = depth + 1;
|
|
116
117
|
|
|
117
|
-
cnt =
|
|
118
|
+
cnt = RARRAY_LEN(a);
|
|
118
119
|
*out->cur++ = '[';
|
|
119
120
|
size = 2;
|
|
120
121
|
assure_size(out, size);
|
|
@@ -226,7 +227,7 @@ static void dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
226
227
|
} else if (oj_bigdecimal_class == clas) {
|
|
227
228
|
volatile VALUE rstr = oj_safe_string_convert(obj);
|
|
228
229
|
|
|
229
|
-
oj_dump_raw(RSTRING_PTR(rstr),
|
|
230
|
+
oj_dump_raw(RSTRING_PTR(rstr), RSTRING_LEN(rstr), out);
|
|
230
231
|
} else if (resolve_wab_uuid_class() == clas) {
|
|
231
232
|
oj_dump_str(oj_safe_string_convert(obj), depth, out, false);
|
|
232
233
|
} else if (resolve_uri_http_class() == clas) {
|
data/lib/oj/mimic.rb
CHANGED
data/lib/oj/schandler.rb
CHANGED
|
@@ -64,13 +64,14 @@ module Oj
|
|
|
64
64
|
#
|
|
65
65
|
# hash_end
|
|
66
66
|
#
|
|
67
|
-
#
|
|
68
|
-
#
|
|
69
|
-
# the key-value pair that follows.
|
|
67
|
+
# At the end of a JSON object element the hash_end() callback is called if
|
|
68
|
+
# public.
|
|
70
69
|
#
|
|
71
70
|
# hash_key
|
|
72
71
|
#
|
|
73
|
-
#
|
|
72
|
+
# When a hash key is encountered the hash_key() method is called with the
|
|
73
|
+
# parsed hash value key. The return value from the call is then used as the
|
|
74
|
+
# key in the key-value pair that follows.
|
|
74
75
|
#
|
|
75
76
|
# hash_set
|
|
76
77
|
#
|
data/lib/oj/version.rb
CHANGED
data/pages/Encoding.md
CHANGED
|
@@ -15,7 +15,7 @@ in a JSON document. The formatting follows these rules.
|
|
|
15
15
|
* The `'^'` character denotes a special key value when in a JSON Object sequence.
|
|
16
16
|
|
|
17
17
|
* A Ruby String that starts with `':'`or the sequence `'^i'` or `'^r'` are
|
|
18
|
-
encoded by
|
|
18
|
+
encoded by escaping the first character so that it appears as `'\u005e'` or
|
|
19
19
|
`'\u003a'` instead of `':'` or `'^'`.
|
|
20
20
|
|
|
21
21
|
* A `"^c"` JSON Object key indicates the value should be converted to a Ruby
|