oj 3.16.1 → 3.16.2
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 +6 -0
- data/ext/oj/cache.c +4 -2
- data/ext/oj/cache.h +3 -2
- data/ext/oj/dump.c +5 -2
- data/ext/oj/fast.c +7 -6
- data/ext/oj/intern.c +23 -6
- data/ext/oj/mimic_json.c +3 -3
- data/ext/oj/object.c +13 -5
- data/ext/oj/oj.c +129 -130
- data/ext/oj/oj.h +3 -3
- data/ext/oj/parser.c +61 -50
- data/ext/oj/rails.c +23 -6
- data/ext/oj/stream_writer.c +35 -15
- data/ext/oj/string_writer.c +50 -16
- data/ext/oj/usual.c +20 -0
- data/ext/oj/usual.h +1 -0
- data/ext/oj/val_stack.c +13 -2
- data/lib/oj/version.rb +1 -1
- data/test/json_gem/json_generator_test.rb +6 -0
- data/test/test_custom.rb +2 -1
- data/test/test_object.rb +14 -0
- data/test/test_parser_usual.rb +10 -0
- metadata +16 -2
data/ext/oj/oj.h
CHANGED
@@ -262,6 +262,8 @@ extern void oj_dump_leaf_to_json(Leaf leaf, Options copts, Out out);
|
|
262
262
|
extern void oj_write_leaf_to_file(Leaf leaf, const char *path, Options copts);
|
263
263
|
extern char *oj_longlong_to_string(long long num, bool negative, char *buf);
|
264
264
|
|
265
|
+
extern StrWriter oj_str_writer_unwrap(VALUE writer);
|
266
|
+
|
265
267
|
extern void oj_str_writer_push_key(StrWriter sw, const char *key);
|
266
268
|
extern void oj_str_writer_push_object(StrWriter sw, const char *key);
|
267
269
|
extern void oj_str_writer_push_array(StrWriter sw, const char *key);
|
@@ -311,9 +313,7 @@ extern VALUE oj_ascii_only_sym;
|
|
311
313
|
extern VALUE oj_create_additions_sym;
|
312
314
|
extern VALUE oj_decimal_class_sym;
|
313
315
|
extern VALUE oj_hash_class_sym;
|
314
|
-
extern VALUE oj_in_sym;
|
315
316
|
extern VALUE oj_indent_sym;
|
316
|
-
extern VALUE oj_nanosecond_sym;
|
317
317
|
extern VALUE oj_max_nesting_sym;
|
318
318
|
extern VALUE oj_object_class_sym;
|
319
319
|
extern VALUE oj_object_nl_sym;
|
@@ -331,7 +331,6 @@ extern ID oj_array_append_id;
|
|
331
331
|
extern ID oj_array_end_id;
|
332
332
|
extern ID oj_array_start_id;
|
333
333
|
extern ID oj_as_json_id;
|
334
|
-
extern ID oj_at_id;
|
335
334
|
extern ID oj_begin_id;
|
336
335
|
extern ID oj_bigdecimal_id;
|
337
336
|
extern ID oj_end_id;
|
@@ -349,6 +348,7 @@ extern ID oj_json_create_id;
|
|
349
348
|
extern ID oj_length_id;
|
350
349
|
extern ID oj_new_id;
|
351
350
|
extern ID oj_parse_id;
|
351
|
+
extern ID oj_plus_id;
|
352
352
|
extern ID oj_pos_id;
|
353
353
|
extern ID oj_read_id;
|
354
354
|
extern ID oj_readpartial_id;
|
data/ext/oj/parser.c
CHANGED
@@ -1164,6 +1164,17 @@ static void parser_mark(void *ptr) {
|
|
1164
1164
|
}
|
1165
1165
|
}
|
1166
1166
|
|
1167
|
+
static const rb_data_type_t oj_parser_type = {
|
1168
|
+
"Oj/parser",
|
1169
|
+
{
|
1170
|
+
parser_mark,
|
1171
|
+
parser_free,
|
1172
|
+
NULL,
|
1173
|
+
},
|
1174
|
+
0,
|
1175
|
+
0,
|
1176
|
+
};
|
1177
|
+
|
1167
1178
|
extern void oj_set_parser_validator(ojParser p);
|
1168
1179
|
extern void oj_set_parser_saj(ojParser p);
|
1169
1180
|
extern void oj_set_parser_usual(ojParser p);
|
@@ -1255,7 +1266,7 @@ static VALUE parser_new(int argc, VALUE *argv, VALUE self) {
|
|
1255
1266
|
rb_hash_foreach(ropts, opt_cb, (VALUE)p);
|
1256
1267
|
}
|
1257
1268
|
}
|
1258
|
-
return
|
1269
|
+
return TypedData_Wrap_Struct(parser_class, &oj_parser_type, p);
|
1259
1270
|
}
|
1260
1271
|
|
1261
1272
|
// Create a new parser without setting the delegate. The parser is
|
@@ -1275,7 +1286,7 @@ VALUE oj_parser_new(void) {
|
|
1275
1286
|
buf_init(&p->buf);
|
1276
1287
|
p->map = value_map;
|
1277
1288
|
|
1278
|
-
return
|
1289
|
+
return TypedData_Wrap_Struct(parser_class, &oj_parser_type, p);
|
1279
1290
|
}
|
1280
1291
|
|
1281
1292
|
// Set set the options from a hash (ropts).
|
@@ -1294,53 +1305,41 @@ void oj_parser_set_option(ojParser p, VALUE ropts) {
|
|
1294
1305
|
* - no options
|
1295
1306
|
*
|
1296
1307
|
* - *:saj*
|
1297
|
-
* -
|
1298
|
-
* -
|
1299
|
-
* -
|
1300
|
-
* that length are cached.
|
1301
|
-
* - _cache_strings_ returns the value of the _cache_strings_ integer value.
|
1302
|
-
* - _handler=_ sets the SAJ handler
|
1303
|
-
* - _handler_ returns the SAJ handler
|
1308
|
+
* - _cache_keys_ is a flag indicating hash keys should be cached.
|
1309
|
+
* - _cache_strings_ is a positive integer less than 35. Strings shorter than that length are cached.
|
1310
|
+
* - _handler_ is the SAJ handler
|
1304
1311
|
*
|
1305
1312
|
* - *:usual*
|
1306
|
-
* -
|
1307
|
-
* -
|
1308
|
-
* -
|
1309
|
-
*
|
1310
|
-
* -
|
1311
|
-
*
|
1312
|
-
*
|
1313
|
-
*
|
1314
|
-
*
|
1315
|
-
*
|
1316
|
-
*
|
1317
|
-
*
|
1318
|
-
*
|
1319
|
-
*
|
1320
|
-
*
|
1321
|
-
*
|
1322
|
-
* _:
|
1323
|
-
*
|
1324
|
-
*
|
1325
|
-
*
|
1326
|
-
* -
|
1327
|
-
* ignored on parsing in favor of creating an instance and populating directly.
|
1328
|
-
* - _missing_class_ return the value of the _missing_class_ indicator.
|
1329
|
-
* - _missing_class=_ sets the value of the _missing_class_ flag. Valid values are _:auto_ which creates any missing
|
1330
|
-
* classes on parse, :ignore which ignores and continues as a Hash (default), and :raise which raises an exception if
|
1331
|
-
* the class is not found.
|
1332
|
-
* - _omit_null=_ sets the _omit_null_ flag. If true then null values in a map or object are omitted from the
|
1333
|
-
* resulting Hash or Object.
|
1334
|
-
* - _omit_null_ returns the value of the _omit_null_ flag.
|
1335
|
-
* - _symbol_keys=_ sets the flag that indicates Hash keys should be parsed to Symbols versus Strings.
|
1336
|
-
* - _symbol_keys_ returns the value of the _symbol_keys_ flag.
|
1313
|
+
* - _cache_keys_ is a flag indicating hash keys should be cached.
|
1314
|
+
* - _cache_strings_ is a positive integer less than 35. Strings shorter than that length are cached.
|
1315
|
+
* - _cache_expunge_ dictates when the cache will be expunged where 0 never expunges,
|
1316
|
+
* 1 expunges slowly, 2 expunges faster, and 3 or higher expunges agressively.
|
1317
|
+
* - _capacity_ is the capacity of the parser's internal stack. The parser grows automatically
|
1318
|
+
* but can be updated directly with this call.
|
1319
|
+
* - _create_id_ if non-nil is the key that is used to specify the type of object to create
|
1320
|
+
* when parsing. Parsed JSON objects that include the specified element use the element
|
1321
|
+
* value as the name of the class to create an object from instead of a Hash.
|
1322
|
+
* - _decimal_ is the approach to how decimals are parsed. If _:auto_ then
|
1323
|
+
* the decimals with significant digits are 16 or less are Floats and long
|
1324
|
+
* ones are BigDecimal. _:ruby_ uses a call to Ruby to convert a string to a Float.
|
1325
|
+
* _:float_ always generates a Float. _:bigdecimal_ always results in a BigDecimal.
|
1326
|
+
* - _ignore_json_create_ is a flag that when set the class json_create method is
|
1327
|
+
* ignored on parsing in favor of creating an instance and populating directly.
|
1328
|
+
* - _missing_class_ is an indicator that determines how unknown class names are handled.
|
1329
|
+
* Valid values are _:auto_ which creates any missing classes on parse, :ignore which ignores
|
1330
|
+
* and continues as a Hash (default), and :raise which raises an exception if the class is not found.
|
1331
|
+
* - _omit_null_ is a flag that if true then null values in a map or object are omitted
|
1332
|
+
* from the resulting Hash or Object.
|
1333
|
+
* - _symbol_keys_ is a flag that indicates Hash keys should be parsed to Symbols versus Strings.
|
1337
1334
|
*/
|
1338
1335
|
static VALUE parser_missing(int argc, VALUE *argv, VALUE self) {
|
1339
|
-
ojParser p
|
1336
|
+
ojParser p;
|
1340
1337
|
const char *key = NULL;
|
1341
1338
|
volatile VALUE rkey = *argv;
|
1342
1339
|
volatile VALUE rv = Qnil;
|
1343
1340
|
|
1341
|
+
TypedData_Get_Struct(self, struct _ojParser, &oj_parser_type, p);
|
1342
|
+
|
1344
1343
|
#if HAVE_RB_EXT_RACTOR_SAFE
|
1345
1344
|
// This doesn't seem to do anything.
|
1346
1345
|
rb_ext_ractor_safe(true);
|
@@ -1366,9 +1365,11 @@ static VALUE parser_missing(int argc, VALUE *argv, VALUE self) {
|
|
1366
1365
|
* Returns the result according to the delegate of the parser.
|
1367
1366
|
*/
|
1368
1367
|
static VALUE parser_parse(VALUE self, VALUE json) {
|
1369
|
-
ojParser p
|
1368
|
+
ojParser p;
|
1370
1369
|
const byte *ptr = (const byte *)StringValuePtr(json);
|
1371
1370
|
|
1371
|
+
TypedData_Get_Struct(self, struct _ojParser, &oj_parser_type, p);
|
1372
|
+
|
1372
1373
|
parser_reset(p);
|
1373
1374
|
p->start(p);
|
1374
1375
|
parse(p, ptr);
|
@@ -1382,9 +1383,11 @@ static VALUE load_rescue(VALUE self, VALUE x) {
|
|
1382
1383
|
}
|
1383
1384
|
|
1384
1385
|
static VALUE load(VALUE self) {
|
1385
|
-
ojParser p
|
1386
|
+
ojParser p;
|
1386
1387
|
volatile VALUE rbuf = rb_str_new2("");
|
1387
1388
|
|
1389
|
+
TypedData_Get_Struct(self, struct _ojParser, &oj_parser_type, p);
|
1390
|
+
|
1388
1391
|
p->start(p);
|
1389
1392
|
while (true) {
|
1390
1393
|
rb_funcall(p->reader, oj_readpartial_id, 2, INT2NUM(16385), rbuf);
|
@@ -1403,7 +1406,9 @@ static VALUE load(VALUE self) {
|
|
1403
1406
|
* Returns the result according to the delegate of the parser.
|
1404
1407
|
*/
|
1405
1408
|
static VALUE parser_load(VALUE self, VALUE reader) {
|
1406
|
-
ojParser p
|
1409
|
+
ojParser p;
|
1410
|
+
|
1411
|
+
TypedData_Get_Struct(self, struct _ojParser, &oj_parser_type, p);
|
1407
1412
|
|
1408
1413
|
parser_reset(p);
|
1409
1414
|
p->reader = reader;
|
@@ -1420,10 +1425,12 @@ static VALUE parser_load(VALUE self, VALUE reader) {
|
|
1420
1425
|
* Returns the result according to the delegate of the parser.
|
1421
1426
|
*/
|
1422
1427
|
static VALUE parser_file(VALUE self, VALUE filename) {
|
1423
|
-
ojParser p
|
1428
|
+
ojParser p;
|
1424
1429
|
const char *path;
|
1425
1430
|
int fd;
|
1426
1431
|
|
1432
|
+
TypedData_Get_Struct(self, struct _ojParser, &oj_parser_type, p);
|
1433
|
+
|
1427
1434
|
path = StringValuePtr(filename);
|
1428
1435
|
|
1429
1436
|
parser_reset(p);
|
@@ -1467,7 +1474,9 @@ static VALUE parser_file(VALUE self, VALUE filename) {
|
|
1467
1474
|
* Returns the current state of the just_one [_Boolean_] option.
|
1468
1475
|
*/
|
1469
1476
|
static VALUE parser_just_one(VALUE self) {
|
1470
|
-
ojParser p
|
1477
|
+
ojParser p;
|
1478
|
+
|
1479
|
+
TypedData_Get_Struct(self, struct _ojParser, &oj_parser_type, p);
|
1471
1480
|
|
1472
1481
|
return p->just_one ? Qtrue : Qfalse;
|
1473
1482
|
}
|
@@ -1481,7 +1490,9 @@ static VALUE parser_just_one(VALUE self) {
|
|
1481
1490
|
* Returns the current state of the just_one [_Boolean_] option.
|
1482
1491
|
*/
|
1483
1492
|
static VALUE parser_just_one_set(VALUE self, VALUE v) {
|
1484
|
-
ojParser p
|
1493
|
+
ojParser p;
|
1494
|
+
|
1495
|
+
TypedData_Get_Struct(self, struct _ojParser, &oj_parser_type, p);
|
1485
1496
|
|
1486
1497
|
p->just_one = (Qtrue == v);
|
1487
1498
|
|
@@ -1505,7 +1516,7 @@ static VALUE parser_usual(VALUE self) {
|
|
1505
1516
|
buf_init(&p->buf);
|
1506
1517
|
p->map = value_map;
|
1507
1518
|
oj_set_parser_usual(p);
|
1508
|
-
usual_parser =
|
1519
|
+
usual_parser = TypedData_Wrap_Struct(parser_class, &oj_parser_type, p);
|
1509
1520
|
rb_gc_register_address(&usual_parser);
|
1510
1521
|
}
|
1511
1522
|
return usual_parser;
|
@@ -1528,7 +1539,7 @@ static VALUE parser_saj(VALUE self) {
|
|
1528
1539
|
buf_init(&p->buf);
|
1529
1540
|
p->map = value_map;
|
1530
1541
|
oj_set_parser_saj(p);
|
1531
|
-
saj_parser =
|
1542
|
+
saj_parser = TypedData_Wrap_Struct(parser_class, &oj_parser_type, p);
|
1532
1543
|
rb_gc_register_address(&saj_parser);
|
1533
1544
|
}
|
1534
1545
|
return saj_parser;
|
@@ -1550,7 +1561,7 @@ static VALUE parser_validate(VALUE self) {
|
|
1550
1561
|
buf_init(&p->buf);
|
1551
1562
|
p->map = value_map;
|
1552
1563
|
oj_set_parser_validator(p);
|
1553
|
-
validate_parser =
|
1564
|
+
validate_parser = TypedData_Wrap_Struct(parser_class, &oj_parser_type, p);
|
1554
1565
|
rb_gc_register_address(&validate_parser);
|
1555
1566
|
}
|
1556
1567
|
return validate_parser;
|
data/ext/oj/rails.c
CHANGED
@@ -639,6 +639,17 @@ static void encoder_mark(void *ptr) {
|
|
639
639
|
}
|
640
640
|
}
|
641
641
|
|
642
|
+
static const rb_data_type_t oj_encoder_type = {
|
643
|
+
"Oj/encoder",
|
644
|
+
{
|
645
|
+
encoder_mark,
|
646
|
+
encoder_free,
|
647
|
+
NULL,
|
648
|
+
},
|
649
|
+
0,
|
650
|
+
0,
|
651
|
+
};
|
652
|
+
|
642
653
|
/* Document-method: new
|
643
654
|
* call-seq: new(options=nil)
|
644
655
|
*
|
@@ -656,7 +667,7 @@ static VALUE encoder_new(int argc, VALUE *argv, VALUE self) {
|
|
656
667
|
oj_parse_options(*argv, &e->opts);
|
657
668
|
e->arg = *argv;
|
658
669
|
}
|
659
|
-
return
|
670
|
+
return TypedData_Wrap_Struct(encoder_class, &oj_encoder_type, e);
|
660
671
|
}
|
661
672
|
|
662
673
|
static VALUE resolve_classpath(const char *name) {
|
@@ -748,7 +759,8 @@ static void optimize(int argc, VALUE *argv, ROptTable rot, bool on) {
|
|
748
759
|
* - *classes* [_Class_] a list of classes to optimize
|
749
760
|
*/
|
750
761
|
static VALUE encoder_optimize(int argc, VALUE *argv, VALUE self) {
|
751
|
-
Encoder e
|
762
|
+
Encoder e;
|
763
|
+
TypedData_Get_Struct(self, struct _encoder, &oj_encoder_type, e);
|
752
764
|
|
753
765
|
optimize(argc, argv, &e->ropts, true);
|
754
766
|
|
@@ -804,7 +816,8 @@ rails_mimic_json(VALUE self) {
|
|
804
816
|
* - *classes* [_Class_] a list of classes to deoptimize
|
805
817
|
*/
|
806
818
|
static VALUE encoder_deoptimize(int argc, VALUE *argv, VALUE self) {
|
807
|
-
Encoder e
|
819
|
+
Encoder e;
|
820
|
+
TypedData_Get_Struct(self, struct _encoder, &oj_encoder_type, e);
|
808
821
|
|
809
822
|
optimize(argc, argv, &e->ropts, false);
|
810
823
|
|
@@ -833,8 +846,11 @@ static VALUE rails_deoptimize(int argc, VALUE *argv, VALUE self) {
|
|
833
846
|
* @return true if the class is being optimized for rails and false otherwise
|
834
847
|
*/
|
835
848
|
static VALUE encoder_optimized(VALUE self, VALUE clas) {
|
836
|
-
Encoder e
|
837
|
-
ROpt ro
|
849
|
+
Encoder e;
|
850
|
+
ROpt ro;
|
851
|
+
|
852
|
+
TypedData_Get_Struct(self, struct _encoder, &oj_encoder_type, e);
|
853
|
+
ro = oj_rails_get_opt(&e->ropts, clas);
|
838
854
|
|
839
855
|
if (NULL == ro) {
|
840
856
|
return Qfalse;
|
@@ -940,7 +956,8 @@ static VALUE encode(VALUE obj, ROptTable ropts, Options opts, int argc, VALUE *a
|
|
940
956
|
* Returns encoded object as a JSON string.
|
941
957
|
*/
|
942
958
|
static VALUE encoder_encode(VALUE self, VALUE obj) {
|
943
|
-
Encoder e
|
959
|
+
Encoder e;
|
960
|
+
TypedData_Get_Struct(self, struct _encoder, &oj_encoder_type, e);
|
944
961
|
|
945
962
|
if (Qnil != e->arg) {
|
946
963
|
VALUE argv[1] = {e->arg};
|
data/ext/oj/stream_writer.c
CHANGED
@@ -21,6 +21,17 @@ static void stream_writer_free(void *ptr) {
|
|
21
21
|
OJ_R_FREE(ptr);
|
22
22
|
}
|
23
23
|
|
24
|
+
static const rb_data_type_t oj_stream_writer_type = {
|
25
|
+
"Oj/stream_writer",
|
26
|
+
{
|
27
|
+
NULL,
|
28
|
+
stream_writer_free,
|
29
|
+
NULL,
|
30
|
+
},
|
31
|
+
0,
|
32
|
+
0,
|
33
|
+
};
|
34
|
+
|
24
35
|
static void stream_writer_reset_buf(StreamWriter sw) {
|
25
36
|
sw->sw.out.cur = sw->sw.out.buf;
|
26
37
|
*sw->sw.out.cur = '\0';
|
@@ -120,7 +131,7 @@ static VALUE stream_writer_new(int argc, VALUE *argv, VALUE self) {
|
|
120
131
|
sw->type = type;
|
121
132
|
sw->fd = fd;
|
122
133
|
|
123
|
-
return
|
134
|
+
return TypedData_Wrap_Struct(oj_stream_writer_class, &oj_stream_writer_type, sw);
|
124
135
|
}
|
125
136
|
|
126
137
|
/* Document-method: push_key
|
@@ -133,7 +144,8 @@ static VALUE stream_writer_new(int argc, VALUE *argv, VALUE self) {
|
|
133
144
|
* - *key* [_String_] the key pending for the next push
|
134
145
|
*/
|
135
146
|
static VALUE stream_writer_push_key(VALUE self, VALUE key) {
|
136
|
-
StreamWriter sw
|
147
|
+
StreamWriter sw;
|
148
|
+
TypedData_Get_Struct(self, struct _streamWriter, &oj_stream_writer_type, sw);
|
137
149
|
|
138
150
|
oj_str_writer_push_key(&sw->sw, StringValuePtr(key));
|
139
151
|
if (sw->flush_limit < sw->sw.out.cur - sw->sw.out.buf) {
|
@@ -151,7 +163,8 @@ static VALUE stream_writer_push_key(VALUE self, VALUE key) {
|
|
151
163
|
* - *key* [_String_] the key if adding to an object in the JSON document
|
152
164
|
*/
|
153
165
|
static VALUE stream_writer_push_object(int argc, VALUE *argv, VALUE self) {
|
154
|
-
StreamWriter sw
|
166
|
+
StreamWriter sw;
|
167
|
+
TypedData_Get_Struct(self, struct _streamWriter, &oj_stream_writer_type, sw);
|
155
168
|
|
156
169
|
switch (argc) {
|
157
170
|
case 0: oj_str_writer_push_object(&sw->sw, 0); break;
|
@@ -179,7 +192,8 @@ static VALUE stream_writer_push_object(int argc, VALUE *argv, VALUE self) {
|
|
179
192
|
* - *key* [_String_] the key if adding to an object in the JSON document
|
180
193
|
*/
|
181
194
|
static VALUE stream_writer_push_array(int argc, VALUE *argv, VALUE self) {
|
182
|
-
StreamWriter sw
|
195
|
+
StreamWriter sw;
|
196
|
+
TypedData_Get_Struct(self, struct _streamWriter, &oj_stream_writer_type, sw);
|
183
197
|
|
184
198
|
switch (argc) {
|
185
199
|
case 0: oj_str_writer_push_array(&sw->sw, 0); break;
|
@@ -206,15 +220,16 @@ static VALUE stream_writer_push_array(int argc, VALUE *argv, VALUE self) {
|
|
206
220
|
* - *key* [_String_] the key if adding to an object in the JSON document
|
207
221
|
*/
|
208
222
|
static VALUE stream_writer_push_value(int argc, VALUE *argv, VALUE self) {
|
209
|
-
StreamWriter sw
|
223
|
+
StreamWriter sw;
|
224
|
+
TypedData_Get_Struct(self, struct _streamWriter, &oj_stream_writer_type, sw);
|
210
225
|
|
211
226
|
switch (argc) {
|
212
|
-
case 1: oj_str_writer_push_value((StrWriter)
|
227
|
+
case 1: oj_str_writer_push_value((StrWriter)sw, *argv, 0); break;
|
213
228
|
case 2:
|
214
229
|
if (Qnil == argv[1]) {
|
215
|
-
oj_str_writer_push_value((StrWriter)
|
230
|
+
oj_str_writer_push_value((StrWriter)sw, *argv, 0);
|
216
231
|
} else {
|
217
|
-
oj_str_writer_push_value((StrWriter)
|
232
|
+
oj_str_writer_push_value((StrWriter)sw, *argv, StringValuePtr(argv[1]));
|
218
233
|
}
|
219
234
|
break;
|
220
235
|
default: rb_raise(rb_eArgError, "Wrong number of argument to 'push_value'."); break;
|
@@ -235,15 +250,16 @@ static VALUE stream_writer_push_value(int argc, VALUE *argv, VALUE self) {
|
|
235
250
|
* - *key* [_String_] the key if adding to an object in the JSON document
|
236
251
|
*/
|
237
252
|
static VALUE stream_writer_push_json(int argc, VALUE *argv, VALUE self) {
|
238
|
-
StreamWriter sw
|
253
|
+
StreamWriter sw;
|
254
|
+
TypedData_Get_Struct(self, struct _streamWriter, &oj_stream_writer_type, sw);
|
239
255
|
|
240
256
|
switch (argc) {
|
241
|
-
case 1: oj_str_writer_push_json((StrWriter)
|
257
|
+
case 1: oj_str_writer_push_json((StrWriter)sw, StringValuePtr(*argv), 0); break;
|
242
258
|
case 2:
|
243
259
|
if (Qnil == argv[1]) {
|
244
|
-
oj_str_writer_push_json((StrWriter)
|
260
|
+
oj_str_writer_push_json((StrWriter)sw, StringValuePtr(*argv), 0);
|
245
261
|
} else {
|
246
|
-
oj_str_writer_push_json((StrWriter)
|
262
|
+
oj_str_writer_push_json((StrWriter)sw, StringValuePtr(*argv), StringValuePtr(argv[1]));
|
247
263
|
}
|
248
264
|
break;
|
249
265
|
default: rb_raise(rb_eArgError, "Wrong number of argument to 'push_json'."); break;
|
@@ -261,7 +277,8 @@ static VALUE stream_writer_push_json(int argc, VALUE *argv, VALUE self) {
|
|
261
277
|
* currently open.
|
262
278
|
*/
|
263
279
|
static VALUE stream_writer_pop(VALUE self) {
|
264
|
-
StreamWriter sw
|
280
|
+
StreamWriter sw;
|
281
|
+
TypedData_Get_Struct(self, struct _streamWriter, &oj_stream_writer_type, sw);
|
265
282
|
|
266
283
|
oj_str_writer_pop(&sw->sw);
|
267
284
|
if (sw->flush_limit < sw->sw.out.cur - sw->sw.out.buf) {
|
@@ -277,7 +294,8 @@ static VALUE stream_writer_pop(VALUE self) {
|
|
277
294
|
* currently open.
|
278
295
|
*/
|
279
296
|
static VALUE stream_writer_pop_all(VALUE self) {
|
280
|
-
StreamWriter sw
|
297
|
+
StreamWriter sw;
|
298
|
+
TypedData_Get_Struct(self, struct _streamWriter, &oj_stream_writer_type, sw);
|
281
299
|
|
282
300
|
oj_str_writer_pop_all(&sw->sw);
|
283
301
|
stream_writer_write(sw);
|
@@ -291,7 +309,9 @@ static VALUE stream_writer_pop_all(VALUE self) {
|
|
291
309
|
* Flush any remaining characters in the buffer.
|
292
310
|
*/
|
293
311
|
static VALUE stream_writer_flush(VALUE self) {
|
294
|
-
|
312
|
+
StreamWriter sw;
|
313
|
+
TypedData_Get_Struct(self, struct _streamWriter, &oj_stream_writer_type, sw);
|
314
|
+
stream_writer_write(sw);
|
295
315
|
|
296
316
|
return Qnil;
|
297
317
|
}
|
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,8 +467,9 @@ 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
|
-
|
470
|
+
StrWriter sw;
|
471
|
+
TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
|
472
|
+
VALUE rstr = rb_str_new(sw->out.buf, sw->out.cur - sw->out.buf);
|
439
473
|
|
440
474
|
return oj_encode(rstr);
|
441
475
|
}
|
data/ext/oj/usual.c
CHANGED
@@ -601,6 +601,9 @@ static VALUE result(ojParser p) {
|
|
601
601
|
if (d->vhead < d->vtail) {
|
602
602
|
return *d->vhead;
|
603
603
|
}
|
604
|
+
if (d->raise_on_empty) {
|
605
|
+
rb_raise(oj_parse_error_class, "empty string");
|
606
|
+
}
|
604
607
|
return Qnil;
|
605
608
|
}
|
606
609
|
|
@@ -1066,6 +1069,20 @@ static VALUE opt_symbol_keys_set(ojParser p, VALUE value) {
|
|
1066
1069
|
return (NULL != d->sym_cache) ? Qtrue : Qfalse;
|
1067
1070
|
}
|
1068
1071
|
|
1072
|
+
static VALUE opt_raise_on_empty(ojParser p, VALUE value) {
|
1073
|
+
Usual d = (Usual)p->ctx;
|
1074
|
+
|
1075
|
+
return d->raise_on_empty ? Qtrue : Qfalse;
|
1076
|
+
}
|
1077
|
+
|
1078
|
+
static VALUE opt_raise_on_empty_set(ojParser p, VALUE value) {
|
1079
|
+
Usual d = (Usual)p->ctx;
|
1080
|
+
|
1081
|
+
d->raise_on_empty = (Qtrue == value);
|
1082
|
+
|
1083
|
+
return d->raise_on_empty ? Qtrue : Qfalse;
|
1084
|
+
}
|
1085
|
+
|
1069
1086
|
static VALUE option(ojParser p, const char *key, VALUE value) {
|
1070
1087
|
struct opt *op;
|
1071
1088
|
struct opt opts[] = {
|
@@ -1095,6 +1112,8 @@ static VALUE option(ojParser p, const char *key, VALUE value) {
|
|
1095
1112
|
{.name = "omit_null=", .func = opt_omit_null_set},
|
1096
1113
|
{.name = "symbol_keys", .func = opt_symbol_keys},
|
1097
1114
|
{.name = "symbol_keys=", .func = opt_symbol_keys_set},
|
1115
|
+
{.name = "raise_on_empty", .func = opt_raise_on_empty},
|
1116
|
+
{.name = "raise_on_empty=", .func = opt_raise_on_empty_set},
|
1098
1117
|
{.name = NULL},
|
1099
1118
|
};
|
1100
1119
|
|
@@ -1129,6 +1148,7 @@ void oj_init_usual(ojParser p, Usual d) {
|
|
1129
1148
|
d->get_key = cache_key;
|
1130
1149
|
d->cache_keys = true;
|
1131
1150
|
d->ignore_json_create = false;
|
1151
|
+
d->raise_on_empty = false;
|
1132
1152
|
d->cache_str = 6;
|
1133
1153
|
d->array_class = Qnil;
|
1134
1154
|
d->hash_class = Qnil;
|