oj 3.16.1 → 3.16.2
Sign up to get free protection for your applications and to get access to all the features.
- 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;
|