oj 3.16.1 → 3.16.2

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