oj 3.16.1 → 3.16.4
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 +14 -0
- data/ext/oj/cache.c +4 -2
- data/ext/oj/cache.h +3 -2
- data/ext/oj/dump.c +39 -16
- data/ext/oj/extconf.rb +1 -2
- data/ext/oj/fast.c +10 -9
- 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 +131 -130
- data/ext/oj/oj.h +4 -3
- data/ext/oj/parser.c +67 -53
- data/ext/oj/parser.h +2 -2
- data/ext/oj/rails.c +23 -6
- data/ext/oj/reader.c +1 -1
- data/ext/oj/saj.c +2 -2
- data/ext/oj/stream_writer.c +35 -15
- data/ext/oj/string_writer.c +50 -16
- data/ext/oj/usual.c +20 -27
- data/ext/oj/usual.h +1 -0
- data/ext/oj/val_stack.c +13 -2
- data/lib/oj/schandler.rb +5 -4
- data/lib/oj/version.rb +1 -1
- data/test/activesupport6/encoding_test.rb +63 -28
- data/test/activesupport7/encoding_test.rb +72 -22
- data/test/foo.rb +3 -9
- data/test/json_gem/json_generator_test.rb +6 -0
- data/test/perf_dump.rb +1 -1
- data/test/prec.rb +4 -4
- data/test/test_custom.rb +2 -1
- data/test/test_object.rb +14 -0
- data/test/test_parser_debug.rb +1 -1
- data/test/test_parser_usual.rb +10 -0
- metadata +17 -3
data/ext/oj/parser.c
CHANGED
@@ -1114,9 +1114,6 @@ static void parse(ojParser p, const byte *json) {
|
|
1114
1114
|
p->map = trail_map;
|
1115
1115
|
}
|
1116
1116
|
}
|
1117
|
-
if (0 < p->depth) {
|
1118
|
-
parse_error(p, "parse error, not closed");
|
1119
|
-
}
|
1120
1117
|
if (0 == p->depth) {
|
1121
1118
|
switch (p->map[256]) {
|
1122
1119
|
case '0':
|
@@ -1164,6 +1161,17 @@ static void parser_mark(void *ptr) {
|
|
1164
1161
|
}
|
1165
1162
|
}
|
1166
1163
|
|
1164
|
+
static const rb_data_type_t oj_parser_type = {
|
1165
|
+
"Oj/parser",
|
1166
|
+
{
|
1167
|
+
parser_mark,
|
1168
|
+
parser_free,
|
1169
|
+
NULL,
|
1170
|
+
},
|
1171
|
+
0,
|
1172
|
+
0,
|
1173
|
+
};
|
1174
|
+
|
1167
1175
|
extern void oj_set_parser_validator(ojParser p);
|
1168
1176
|
extern void oj_set_parser_saj(ojParser p);
|
1169
1177
|
extern void oj_set_parser_usual(ojParser p);
|
@@ -1255,7 +1263,7 @@ static VALUE parser_new(int argc, VALUE *argv, VALUE self) {
|
|
1255
1263
|
rb_hash_foreach(ropts, opt_cb, (VALUE)p);
|
1256
1264
|
}
|
1257
1265
|
}
|
1258
|
-
return
|
1266
|
+
return TypedData_Wrap_Struct(parser_class, &oj_parser_type, p);
|
1259
1267
|
}
|
1260
1268
|
|
1261
1269
|
// Create a new parser without setting the delegate. The parser is
|
@@ -1275,7 +1283,7 @@ VALUE oj_parser_new(void) {
|
|
1275
1283
|
buf_init(&p->buf);
|
1276
1284
|
p->map = value_map;
|
1277
1285
|
|
1278
|
-
return
|
1286
|
+
return TypedData_Wrap_Struct(parser_class, &oj_parser_type, p);
|
1279
1287
|
}
|
1280
1288
|
|
1281
1289
|
// Set set the options from a hash (ropts).
|
@@ -1294,53 +1302,41 @@ void oj_parser_set_option(ojParser p, VALUE ropts) {
|
|
1294
1302
|
* - no options
|
1295
1303
|
*
|
1296
1304
|
* - *: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
|
1305
|
+
* - _cache_keys_ is a flag indicating hash keys should be cached.
|
1306
|
+
* - _cache_strings_ is a positive integer less than 35. Strings shorter than that length are cached.
|
1307
|
+
* - _handler_ is the SAJ handler
|
1304
1308
|
*
|
1305
1309
|
* - *: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.
|
1310
|
+
* - _cache_keys_ is a flag indicating hash keys should be cached.
|
1311
|
+
* - _cache_strings_ is a positive integer less than 35. Strings shorter than that length are cached.
|
1312
|
+
* - _cache_expunge_ dictates when the cache will be expunged where 0 never expunges,
|
1313
|
+
* 1 expunges slowly, 2 expunges faster, and 3 or higher expunges agressively.
|
1314
|
+
* - _capacity_ is the capacity of the parser's internal stack. The parser grows automatically
|
1315
|
+
* but can be updated directly with this call.
|
1316
|
+
* - _create_id_ if non-nil is the key that is used to specify the type of object to create
|
1317
|
+
* when parsing. Parsed JSON objects that include the specified element use the element
|
1318
|
+
* value as the name of the class to create an object from instead of a Hash.
|
1319
|
+
* - _decimal_ is the approach to how decimals are parsed. If _:auto_ then
|
1320
|
+
* the decimals with significant digits are 16 or less are Floats and long
|
1321
|
+
* ones are BigDecimal. _:ruby_ uses a call to Ruby to convert a string to a Float.
|
1322
|
+
* _:float_ always generates a Float. _:bigdecimal_ always results in a BigDecimal.
|
1323
|
+
* - _ignore_json_create_ is a flag that when set the class json_create method is
|
1324
|
+
* ignored on parsing in favor of creating an instance and populating directly.
|
1325
|
+
* - _missing_class_ is an indicator that determines how unknown class names are handled.
|
1326
|
+
* Valid values are _:auto_ which creates any missing classes on parse, :ignore which ignores
|
1327
|
+
* and continues as a Hash (default), and :raise which raises an exception if the class is not found.
|
1328
|
+
* - _omit_null_ is a flag that if true then null values in a map or object are omitted
|
1329
|
+
* from the resulting Hash or Object.
|
1330
|
+
* - _symbol_keys_ is a flag that indicates Hash keys should be parsed to Symbols versus Strings.
|
1337
1331
|
*/
|
1338
1332
|
static VALUE parser_missing(int argc, VALUE *argv, VALUE self) {
|
1339
|
-
ojParser p
|
1333
|
+
ojParser p;
|
1340
1334
|
const char *key = NULL;
|
1341
1335
|
volatile VALUE rkey = *argv;
|
1342
1336
|
volatile VALUE rv = Qnil;
|
1343
1337
|
|
1338
|
+
TypedData_Get_Struct(self, struct _ojParser, &oj_parser_type, p);
|
1339
|
+
|
1344
1340
|
#if HAVE_RB_EXT_RACTOR_SAFE
|
1345
1341
|
// This doesn't seem to do anything.
|
1346
1342
|
rb_ext_ractor_safe(true);
|
@@ -1366,9 +1362,11 @@ static VALUE parser_missing(int argc, VALUE *argv, VALUE self) {
|
|
1366
1362
|
* Returns the result according to the delegate of the parser.
|
1367
1363
|
*/
|
1368
1364
|
static VALUE parser_parse(VALUE self, VALUE json) {
|
1369
|
-
ojParser p
|
1365
|
+
ojParser p;
|
1370
1366
|
const byte *ptr = (const byte *)StringValuePtr(json);
|
1371
1367
|
|
1368
|
+
TypedData_Get_Struct(self, struct _ojParser, &oj_parser_type, p);
|
1369
|
+
|
1372
1370
|
parser_reset(p);
|
1373
1371
|
p->start(p);
|
1374
1372
|
parse(p, ptr);
|
@@ -1382,15 +1380,23 @@ static VALUE load_rescue(VALUE self, VALUE x) {
|
|
1382
1380
|
}
|
1383
1381
|
|
1384
1382
|
static VALUE load(VALUE self) {
|
1385
|
-
ojParser p
|
1383
|
+
ojParser p;
|
1386
1384
|
volatile VALUE rbuf = rb_str_new2("");
|
1387
1385
|
|
1386
|
+
TypedData_Get_Struct(self, struct _ojParser, &oj_parser_type, p);
|
1387
|
+
|
1388
1388
|
p->start(p);
|
1389
1389
|
while (true) {
|
1390
1390
|
rb_funcall(p->reader, oj_readpartial_id, 2, INT2NUM(16385), rbuf);
|
1391
1391
|
if (0 < RSTRING_LEN(rbuf)) {
|
1392
1392
|
parse(p, (byte *)StringValuePtr(rbuf));
|
1393
1393
|
}
|
1394
|
+
if (Qtrue == rb_funcall(p->reader, oj_eofq_id, 0)) {
|
1395
|
+
if (0 < p->depth) {
|
1396
|
+
parse_error(p, "parse error, not closed");
|
1397
|
+
}
|
1398
|
+
break;
|
1399
|
+
}
|
1394
1400
|
}
|
1395
1401
|
return Qtrue;
|
1396
1402
|
}
|
@@ -1403,7 +1409,9 @@ static VALUE load(VALUE self) {
|
|
1403
1409
|
* Returns the result according to the delegate of the parser.
|
1404
1410
|
*/
|
1405
1411
|
static VALUE parser_load(VALUE self, VALUE reader) {
|
1406
|
-
ojParser p
|
1412
|
+
ojParser p;
|
1413
|
+
|
1414
|
+
TypedData_Get_Struct(self, struct _ojParser, &oj_parser_type, p);
|
1407
1415
|
|
1408
1416
|
parser_reset(p);
|
1409
1417
|
p->reader = reader;
|
@@ -1420,10 +1428,12 @@ static VALUE parser_load(VALUE self, VALUE reader) {
|
|
1420
1428
|
* Returns the result according to the delegate of the parser.
|
1421
1429
|
*/
|
1422
1430
|
static VALUE parser_file(VALUE self, VALUE filename) {
|
1423
|
-
ojParser p
|
1431
|
+
ojParser p;
|
1424
1432
|
const char *path;
|
1425
1433
|
int fd;
|
1426
1434
|
|
1435
|
+
TypedData_Get_Struct(self, struct _ojParser, &oj_parser_type, p);
|
1436
|
+
|
1427
1437
|
path = StringValuePtr(filename);
|
1428
1438
|
|
1429
1439
|
parser_reset(p);
|
@@ -1467,7 +1477,9 @@ static VALUE parser_file(VALUE self, VALUE filename) {
|
|
1467
1477
|
* Returns the current state of the just_one [_Boolean_] option.
|
1468
1478
|
*/
|
1469
1479
|
static VALUE parser_just_one(VALUE self) {
|
1470
|
-
ojParser p
|
1480
|
+
ojParser p;
|
1481
|
+
|
1482
|
+
TypedData_Get_Struct(self, struct _ojParser, &oj_parser_type, p);
|
1471
1483
|
|
1472
1484
|
return p->just_one ? Qtrue : Qfalse;
|
1473
1485
|
}
|
@@ -1481,7 +1493,9 @@ static VALUE parser_just_one(VALUE self) {
|
|
1481
1493
|
* Returns the current state of the just_one [_Boolean_] option.
|
1482
1494
|
*/
|
1483
1495
|
static VALUE parser_just_one_set(VALUE self, VALUE v) {
|
1484
|
-
ojParser p
|
1496
|
+
ojParser p;
|
1497
|
+
|
1498
|
+
TypedData_Get_Struct(self, struct _ojParser, &oj_parser_type, p);
|
1485
1499
|
|
1486
1500
|
p->just_one = (Qtrue == v);
|
1487
1501
|
|
@@ -1505,7 +1519,7 @@ static VALUE parser_usual(VALUE self) {
|
|
1505
1519
|
buf_init(&p->buf);
|
1506
1520
|
p->map = value_map;
|
1507
1521
|
oj_set_parser_usual(p);
|
1508
|
-
usual_parser =
|
1522
|
+
usual_parser = TypedData_Wrap_Struct(parser_class, &oj_parser_type, p);
|
1509
1523
|
rb_gc_register_address(&usual_parser);
|
1510
1524
|
}
|
1511
1525
|
return usual_parser;
|
@@ -1528,7 +1542,7 @@ static VALUE parser_saj(VALUE self) {
|
|
1528
1542
|
buf_init(&p->buf);
|
1529
1543
|
p->map = value_map;
|
1530
1544
|
oj_set_parser_saj(p);
|
1531
|
-
saj_parser =
|
1545
|
+
saj_parser = TypedData_Wrap_Struct(parser_class, &oj_parser_type, p);
|
1532
1546
|
rb_gc_register_address(&saj_parser);
|
1533
1547
|
}
|
1534
1548
|
return saj_parser;
|
@@ -1550,7 +1564,7 @@ static VALUE parser_validate(VALUE self) {
|
|
1550
1564
|
buf_init(&p->buf);
|
1551
1565
|
p->map = value_map;
|
1552
1566
|
oj_set_parser_validator(p);
|
1553
|
-
validate_parser =
|
1567
|
+
validate_parser = TypedData_Wrap_Struct(parser_class, &oj_parser_type, p);
|
1554
1568
|
rb_gc_register_address(&validate_parser);
|
1555
1569
|
}
|
1556
1570
|
return validate_parser;
|
data/ext/oj/parser.h
CHANGED
@@ -32,9 +32,9 @@ typedef struct _num {
|
|
32
32
|
long double dub;
|
33
33
|
int64_t fixnum; // holds all digits
|
34
34
|
uint32_t len;
|
35
|
-
int16_t div;
|
35
|
+
int16_t div; // 10^div
|
36
36
|
int16_t exp;
|
37
|
-
uint8_t shift;
|
37
|
+
uint8_t shift; // shift of fixnum to get decimal
|
38
38
|
bool neg;
|
39
39
|
bool exp_neg;
|
40
40
|
// for numbers as strings, reuse buf
|
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/reader.c
CHANGED
@@ -101,7 +101,7 @@ int oj_reader_read(Reader reader) {
|
|
101
101
|
} else {
|
102
102
|
shift = reader->pro - reader->head - 1; // leave one character so we can backup one
|
103
103
|
}
|
104
|
-
if (0 >= shift) {
|
104
|
+
if (0 >= shift) { /* no space left so allocate more */
|
105
105
|
const char *old = reader->head;
|
106
106
|
size_t size = reader->end - reader->head + BUF_PAD;
|
107
107
|
|
data/ext/oj/saj.c
CHANGED
@@ -578,7 +578,7 @@ static void saj_parse(VALUE handler, char *json) {
|
|
578
578
|
/* initialize parse info */
|
579
579
|
pi.str = json;
|
580
580
|
pi.s = json;
|
581
|
-
#if IS_WINDOWS
|
581
|
+
#if IS_WINDOWS || !defined(HAVE_GETRLIMIT)
|
582
582
|
pi.stack_min = (void *)((char *)&obj - (512L * 1024L)); /* assume a 1M stack and give half to ruby */
|
583
583
|
#else
|
584
584
|
{
|
@@ -587,7 +587,7 @@ static void saj_parse(VALUE handler, char *json) {
|
|
587
587
|
if (0 == getrlimit(RLIMIT_STACK, &lim) && RLIM_INFINITY != lim.rlim_cur) {
|
588
588
|
pi.stack_min = (void *)((char *)&obj - (lim.rlim_cur / 4 * 3)); /* let 3/4ths of the stack be used only */
|
589
589
|
} else {
|
590
|
-
pi.stack_min = 0;
|
590
|
+
pi.stack_min = 0; /* indicates not to check stack limit */
|
591
591
|
}
|
592
592
|
}
|
593
593
|
#endif
|
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
|
}
|