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.
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 Data_Wrap_Struct(parser_class, parser_mark, parser_free, p);
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 Data_Wrap_Struct(parser_class, parser_mark, parser_free, p);
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
- * - _cache_keys=_ sets the value of the _cache_keys_ flag.
1298
- * - _cache_keys_ returns the value of the _cache_keys_ flag.
1299
- * - _cache_strings=_ sets the value of the _cache_strings_ to an positive integer less than 35. Strings shorter than
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
- * - _cache_keys=_ sets the value of the _cache_keys_ flag.
1307
- * - _cache_keys_ returns the value of the _cache_keys_ flag.
1308
- * - _cache_strings=_ sets the value of the _cache_strings_ to a positive integer less than 35. Strings shorter than
1309
- * that length are cached.
1310
- * - _cache_strings_ returns the value of the _cache_strings_ integer value.
1311
- * - _cache_expunge=_ sets the value of the _cache_expunge_ where 0 never expunges, 1 expunges slowly, 2 expunges
1312
- * faster, and 3 or higher expunges agressively.
1313
- * - _cache_expunge_ returns the value of the _cache_expunge_ integer value.
1314
- * - _capacity=_ sets the capacity of the parser. The parser grows automatically but can be updated directly with this
1315
- * call.
1316
- * - _capacity_ returns the current capacity of the parser's internal stack.
1317
- * - _create_id_ returns the value _create_id_ or _nil_ if there is no _create_id_.
1318
- * - _create_id=_ sets the value _create_id_ or if _nil_ unsets it. Parsed JSON objects that include the specified
1319
- * element use the element value as the name of the class to create an object from instead of a Hash.
1320
- * - _decimal=_ sets the approach to how decimals are parser. If _:auto_ then the decimals with significant digits are
1321
- * 16 or less are Floats and long 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
- * - _decimal_ returns the value of the decimal conversion option which can be :auto (default), :ruby, :float, or
1324
- * :bigdecimal.
1325
- * - _ignore_json_create_ returns the value of the _ignore_json_create_ flag.
1326
- * - _ignore_json_create=_ sets the value of the _ignore_json_create_ flag. When set the class json_create method is
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 = (ojParser)DATA_PTR(self);
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 = (ojParser)DATA_PTR(self);
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 = (ojParser)DATA_PTR(self);
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 = (ojParser)DATA_PTR(self);
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 = (ojParser)DATA_PTR(self);
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 = (ojParser)DATA_PTR(self);
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 = (ojParser)DATA_PTR(self);
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 = Data_Wrap_Struct(parser_class, parser_mark, parser_free, p);
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 = Data_Wrap_Struct(parser_class, parser_mark, parser_free, p);
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 = Data_Wrap_Struct(parser_class, parser_mark, parser_free, p);
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 Data_Wrap_Struct(encoder_class, encoder_mark, encoder_free, e);
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 = (Encoder)DATA_PTR(self);
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 = (Encoder)DATA_PTR(self);
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 = (Encoder)DATA_PTR(self);
837
- ROpt ro = oj_rails_get_opt(&e->ropts, clas);
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 = (Encoder)DATA_PTR(self);
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};
@@ -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 Data_Wrap_Struct(oj_stream_writer_class, 0, stream_writer_free, sw);
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 = (StreamWriter)DATA_PTR(self);
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 = (StreamWriter)DATA_PTR(self);
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 = (StreamWriter)DATA_PTR(self);
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 = (StreamWriter)DATA_PTR(self);
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)DATA_PTR(self), *argv, 0); break;
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)DATA_PTR(self), *argv, 0);
230
+ oj_str_writer_push_value((StrWriter)sw, *argv, 0);
216
231
  } else {
217
- oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, StringValuePtr(argv[1]));
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 = (StreamWriter)DATA_PTR(self);
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)DATA_PTR(self), StringValuePtr(*argv), 0); break;
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)DATA_PTR(self), StringValuePtr(*argv), 0);
260
+ oj_str_writer_push_json((StrWriter)sw, StringValuePtr(*argv), 0);
245
261
  } else {
246
- oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), StringValuePtr(argv[1]));
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 = (StreamWriter)DATA_PTR(self);
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 = (StreamWriter)DATA_PTR(self);
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
- stream_writer_write((StreamWriter)DATA_PTR(self));
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
  }
@@ -225,7 +225,7 @@ void oj_str_writer_pop_all(StrWriter sw) {
225
225
  }
226
226
  }
227
227
 
228
- static void str_writer_free(void *ptr) {
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 Data_Wrap_Struct(oj_string_writer_class, 0, str_writer_free, sw);
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 = (StrWriter)DATA_PTR(self);
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 = (StrWriter)DATA_PTR(self);
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 = (StrWriter)DATA_PTR(self);
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((StrWriter)DATA_PTR(self), *argv, 0); break;
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((StrWriter)DATA_PTR(self), *argv, 0);
379
+ oj_str_writer_push_value(sw, *argv, 0);
357
380
  } else {
358
- oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, StringValuePtr(argv[1]));
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((StrWriter)DATA_PTR(self), StringValuePtr(*argv), 0); break;
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((StrWriter)DATA_PTR(self), StringValuePtr(*argv), 0);
406
+ oj_str_writer_push_json(sw, StringValuePtr(*argv), 0);
381
407
  } else {
382
- oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), StringValuePtr(argv[1]));
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
- oj_str_writer_pop((StrWriter)DATA_PTR(self));
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
- oj_str_writer_pop_all((StrWriter)DATA_PTR(self));
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 = (StrWriter)DATA_PTR(self);
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 = (StrWriter)DATA_PTR(self);
438
- VALUE rstr = rb_str_new(sw->out.buf, sw->out.cur - sw->out.buf);
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;
data/ext/oj/usual.h CHANGED
@@ -60,6 +60,7 @@ typedef struct _usual {
60
60
  uint8_t miss_class;
61
61
  bool cache_keys;
62
62
  bool ignore_json_create;
63
+ bool raise_on_empty;
63
64
  } *Usual;
64
65
 
65
66
  // Initialize the parser with the usual delegate. If the usual delegate is