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