oj 3.16.1 → 3.16.4

Sign up to get free protection for your applications and to get access to all the features.
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 Data_Wrap_Struct(parser_class, parser_mark, parser_free, p);
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 Data_Wrap_Struct(parser_class, parser_mark, parser_free, p);
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
- * - _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
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
- * - _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.
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 = (ojParser)DATA_PTR(self);
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 = (ojParser)DATA_PTR(self);
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 = (ojParser)DATA_PTR(self);
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 = (ojParser)DATA_PTR(self);
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 = (ojParser)DATA_PTR(self);
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 = (ojParser)DATA_PTR(self);
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 = (ojParser)DATA_PTR(self);
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 = Data_Wrap_Struct(parser_class, parser_mark, parser_free, p);
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 = Data_Wrap_Struct(parser_class, parser_mark, parser_free, p);
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 = Data_Wrap_Struct(parser_class, parser_mark, parser_free, p);
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; // 10^div
35
+ int16_t div; // 10^div
36
36
  int16_t exp;
37
- uint8_t shift; // shift of fixnum to get decimal
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 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};
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) { /* no space left so allocate more */
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; /* indicates not to check stack limit */
590
+ pi.stack_min = 0; /* indicates not to check stack limit */
591
591
  }
592
592
  }
593
593
  #endif
@@ -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
  }