oj 3.13.11 → 3.15.0

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.
Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +74 -0
  3. data/README.md +4 -2
  4. data/ext/oj/buf.h +11 -6
  5. data/ext/oj/cache.c +25 -24
  6. data/ext/oj/cache8.c +10 -9
  7. data/ext/oj/circarray.c +8 -6
  8. data/ext/oj/circarray.h +2 -2
  9. data/ext/oj/code.c +17 -24
  10. data/ext/oj/code.h +2 -2
  11. data/ext/oj/compat.c +17 -44
  12. data/ext/oj/custom.c +70 -141
  13. data/ext/oj/debug.c +3 -9
  14. data/ext/oj/dump.c +128 -118
  15. data/ext/oj/dump.h +12 -8
  16. data/ext/oj/dump_compat.c +564 -641
  17. data/ext/oj/dump_leaf.c +17 -63
  18. data/ext/oj/dump_object.c +70 -199
  19. data/ext/oj/dump_strict.c +22 -46
  20. data/ext/oj/encoder.c +1 -1
  21. data/ext/oj/err.c +2 -13
  22. data/ext/oj/err.h +9 -12
  23. data/ext/oj/extconf.rb +14 -5
  24. data/ext/oj/fast.c +75 -103
  25. data/ext/oj/intern.c +52 -50
  26. data/ext/oj/intern.h +4 -8
  27. data/ext/oj/mem.c +318 -0
  28. data/ext/oj/mem.h +53 -0
  29. data/ext/oj/mimic_json.c +75 -47
  30. data/ext/oj/object.c +49 -66
  31. data/ext/oj/odd.c +89 -67
  32. data/ext/oj/odd.h +15 -15
  33. data/ext/oj/oj.c +140 -99
  34. data/ext/oj/oj.h +80 -51
  35. data/ext/oj/parse.c +162 -184
  36. data/ext/oj/parse.h +7 -10
  37. data/ext/oj/parser.c +89 -34
  38. data/ext/oj/parser.h +18 -7
  39. data/ext/oj/rails.c +82 -146
  40. data/ext/oj/rails.h +1 -1
  41. data/ext/oj/reader.c +11 -12
  42. data/ext/oj/reader.h +4 -2
  43. data/ext/oj/resolve.c +3 -4
  44. data/ext/oj/rxclass.c +6 -5
  45. data/ext/oj/rxclass.h +1 -1
  46. data/ext/oj/saj.c +20 -31
  47. data/ext/oj/saj2.c +329 -93
  48. data/ext/oj/saj2.h +23 -0
  49. data/ext/oj/scp.c +3 -14
  50. data/ext/oj/sparse.c +26 -70
  51. data/ext/oj/stream_writer.c +12 -22
  52. data/ext/oj/strict.c +20 -52
  53. data/ext/oj/string_writer.c +21 -21
  54. data/ext/oj/trace.h +31 -4
  55. data/ext/oj/usual.c +105 -150
  56. data/ext/oj/usual.h +68 -0
  57. data/ext/oj/util.h +1 -1
  58. data/ext/oj/val_stack.c +1 -1
  59. data/ext/oj/val_stack.h +8 -7
  60. data/ext/oj/validate.c +21 -26
  61. data/ext/oj/wab.c +31 -68
  62. data/lib/oj/active_support_helper.rb +0 -1
  63. data/lib/oj/bag.rb +7 -1
  64. data/lib/oj/easy_hash.rb +4 -5
  65. data/lib/oj/error.rb +0 -1
  66. data/lib/oj/json.rb +4 -2
  67. data/lib/oj/mimic.rb +4 -2
  68. data/lib/oj/saj.rb +20 -6
  69. data/lib/oj/state.rb +9 -6
  70. data/lib/oj/version.rb +1 -2
  71. data/lib/oj.rb +2 -0
  72. data/pages/Compatibility.md +1 -1
  73. data/pages/InstallOptions.md +20 -0
  74. data/pages/Options.md +10 -0
  75. data/test/_test_active.rb +8 -9
  76. data/test/_test_active_mimic.rb +7 -8
  77. data/test/_test_mimic_rails.rb +17 -20
  78. data/test/activerecord/result_test.rb +5 -6
  79. data/test/{activesupport5 → activesupport7}/abstract_unit.rb +16 -12
  80. data/test/{activesupport5 → activesupport7}/decoding_test.rb +2 -10
  81. data/test/{activesupport5 → activesupport7}/encoding_test.rb +20 -34
  82. data/test/{activesupport5 → activesupport7}/encoding_test_cases.rb +6 -0
  83. data/test/{activesupport5 → activesupport7}/time_zone_test_helpers.rb +8 -0
  84. data/test/files.rb +15 -15
  85. data/test/foo.rb +9 -71
  86. data/test/helper.rb +11 -8
  87. data/test/isolated/shared.rb +3 -2
  88. data/test/json_gem/json_addition_test.rb +2 -2
  89. data/test/json_gem/json_common_interface_test.rb +4 -4
  90. data/test/json_gem/json_encoding_test.rb +0 -0
  91. data/test/json_gem/json_ext_parser_test.rb +1 -0
  92. data/test/json_gem/json_fixtures_test.rb +3 -2
  93. data/test/json_gem/json_generator_test.rb +48 -36
  94. data/test/json_gem/json_generic_object_test.rb +11 -11
  95. data/test/json_gem/json_parser_test.rb +54 -47
  96. data/test/json_gem/json_string_matching_test.rb +9 -9
  97. data/test/json_gem/test_helper.rb +7 -3
  98. data/test/mem.rb +13 -12
  99. data/test/perf.rb +21 -26
  100. data/test/perf_compat.rb +31 -33
  101. data/test/perf_dump.rb +50 -0
  102. data/test/perf_fast.rb +80 -82
  103. data/test/perf_file.rb +27 -29
  104. data/test/perf_object.rb +65 -69
  105. data/test/perf_once.rb +12 -11
  106. data/test/perf_parser.rb +42 -48
  107. data/test/perf_saj.rb +46 -54
  108. data/test/perf_scp.rb +57 -69
  109. data/test/perf_simple.rb +41 -39
  110. data/test/perf_strict.rb +68 -70
  111. data/test/perf_wab.rb +67 -69
  112. data/test/prec.rb +3 -3
  113. data/test/sample/change.rb +0 -1
  114. data/test/sample/dir.rb +0 -1
  115. data/test/sample/doc.rb +0 -1
  116. data/test/sample/file.rb +0 -1
  117. data/test/sample/group.rb +0 -1
  118. data/test/sample/hasprops.rb +0 -1
  119. data/test/sample/layer.rb +0 -1
  120. data/test/sample/rect.rb +0 -1
  121. data/test/sample/shape.rb +0 -1
  122. data/test/sample/text.rb +0 -1
  123. data/test/sample.rb +16 -16
  124. data/test/sample_json.rb +8 -8
  125. data/test/test_compat.rb +76 -42
  126. data/test/test_custom.rb +72 -51
  127. data/test/test_debian.rb +7 -10
  128. data/test/test_fast.rb +86 -90
  129. data/test/test_file.rb +41 -30
  130. data/test/test_gc.rb +16 -5
  131. data/test/test_generate.rb +5 -5
  132. data/test/test_hash.rb +4 -4
  133. data/test/test_integer_range.rb +9 -9
  134. data/test/test_null.rb +20 -20
  135. data/test/test_object.rb +85 -96
  136. data/test/test_parser.rb +6 -22
  137. data/test/test_parser_debug.rb +27 -0
  138. data/test/test_parser_saj.rb +115 -23
  139. data/test/test_parser_usual.rb +6 -6
  140. data/test/test_rails.rb +2 -2
  141. data/test/test_saj.rb +10 -8
  142. data/test/test_scp.rb +37 -39
  143. data/test/test_strict.rb +30 -32
  144. data/test/test_various.rb +147 -99
  145. data/test/test_wab.rb +48 -44
  146. data/test/test_writer.rb +47 -47
  147. data/test/tests.rb +13 -4
  148. data/test/tests_mimic.rb +12 -3
  149. data/test/tests_mimic_addition.rb +12 -3
  150. metadata +33 -144
  151. data/test/activesupport4/decoding_test.rb +0 -108
  152. data/test/activesupport4/encoding_test.rb +0 -531
  153. data/test/activesupport4/test_helper.rb +0 -41
  154. data/test/activesupport5/test_helper.rb +0 -72
  155. data/test/bar.rb +0 -16
  156. data/test/baz.rb +0 -16
  157. data/test/bug.rb +0 -16
  158. data/test/zoo.rb +0 -13
data/ext/oj/reader.c CHANGED
@@ -6,12 +6,15 @@
6
6
  #include <stdlib.h>
7
7
  #include <strings.h>
8
8
  #include <sys/types.h>
9
+ #ifdef NEEDS_UIO
9
10
  #if NEEDS_UIO
10
11
  #include <sys/uio.h>
11
12
  #endif
13
+ #endif
12
14
  #include <time.h>
13
15
  #include <unistd.h>
14
16
 
17
+ #include "mem.h"
15
18
  #include "oj.h"
16
19
  #include "reader.h"
17
20
  #include "ruby.h"
@@ -61,8 +64,7 @@ void oj_reader_init(Reader reader, VALUE io, int fd, bool to_s) {
61
64
  reader->tail = reader->head;
62
65
  reader->read_end = reader->head + RSTRING_LEN(s);
63
66
  } else if (rb_cFile == io_class && Qnil != (stat = rb_funcall(io, oj_stat_id, 0)) &&
64
- Qnil != (ftype = rb_funcall(stat, oj_ftype_id, 0)) &&
65
- 0 == strcmp("file", StringValuePtr(ftype)) &&
67
+ Qnil != (ftype = rb_funcall(stat, oj_ftype_id, 0)) && 0 == strcmp("file", StringValuePtr(ftype)) &&
66
68
  0 == FIX2INT(rb_funcall(io, oj_pos_id, 0))) {
67
69
  reader->read_func = read_from_fd;
68
70
  reader->fd = FIX2INT(rb_funcall(io, oj_fileno_id, 0));
@@ -73,7 +75,7 @@ void oj_reader_init(Reader reader, VALUE io, int fd, bool to_s) {
73
75
  reader->read_func = read_from_io;
74
76
  reader->io = io;
75
77
  } else if (to_s) {
76
- volatile VALUE rstr = rb_funcall(io, oj_to_s_id, 0);
78
+ volatile VALUE rstr = oj_safe_string_convert(io);
77
79
 
78
80
  reader->read_func = 0;
79
81
  reader->in_str = StringValuePtr(rstr);
@@ -81,8 +83,7 @@ void oj_reader_init(Reader reader, VALUE io, int fd, bool to_s) {
81
83
  reader->tail = reader->head;
82
84
  reader->read_end = reader->head + RSTRING_LEN(rstr);
83
85
  } else {
84
- rb_raise(rb_eArgError,
85
- "parser io argument must be a String or respond to readpartial() or read().\n");
86
+ rb_raise(rb_eArgError, "parser io argument must be a String or respond to readpartial() or read().\n");
86
87
  }
87
88
  }
88
89
 
@@ -105,10 +106,10 @@ int oj_reader_read(Reader reader) {
105
106
  size_t size = reader->end - reader->head + BUF_PAD;
106
107
 
107
108
  if (reader->head == reader->base) {
108
- reader->head = ALLOC_N(char, size * 2);
109
+ reader->head = OJ_R_ALLOC_N(char, size * 2);
109
110
  memcpy((char *)reader->head, old, size);
110
111
  } else {
111
- REALLOC_N(reader->head, char, size * 2);
112
+ OJ_R_REALLOC_N(reader->head, char, size * 2);
112
113
  }
113
114
  reader->free_head = 1;
114
115
  reader->end = reader->head + size * 2 - BUF_PAD;
@@ -121,9 +122,7 @@ int oj_reader_read(Reader reader) {
121
122
  reader->str = reader->head + (reader->str - old);
122
123
  }
123
124
  } else {
124
- memmove((char *)reader->head,
125
- reader->head + shift,
126
- reader->read_end - (reader->head + shift));
125
+ memmove((char *)reader->head, reader->head + shift, reader->read_end - (reader->head + shift));
127
126
  reader->tail -= shift;
128
127
  reader->read_end -= shift;
129
128
  if (0 != reader->pro) {
@@ -155,7 +154,7 @@ static VALUE partial_io_cb(VALUE rbuf) {
155
154
  Reader reader = (Reader)rbuf;
156
155
  VALUE args[1];
157
156
  VALUE rstr;
158
- char * str;
157
+ char *str;
159
158
  size_t cnt;
160
159
 
161
160
  args[0] = ULONG2NUM(reader->end - reader->tail);
@@ -176,7 +175,7 @@ static VALUE io_cb(VALUE rbuf) {
176
175
  Reader reader = (Reader)rbuf;
177
176
  VALUE args[1];
178
177
  VALUE rstr;
179
- char * str;
178
+ char *str;
180
179
  size_t cnt;
181
180
 
182
181
  args[0] = ULONG2NUM(reader->end - reader->tail);
data/ext/oj/reader.h CHANGED
@@ -4,6 +4,8 @@
4
4
  #ifndef OJ_READER_H
5
5
  #define OJ_READER_H
6
6
 
7
+ #include "mem.h"
8
+
7
9
  typedef struct _reader {
8
10
  char base[0x00001000];
9
11
  char *head;
@@ -22,7 +24,7 @@ typedef struct _reader {
22
24
  VALUE io;
23
25
  const char *in_str;
24
26
  };
25
- } * Reader;
27
+ } *Reader;
26
28
 
27
29
  extern void oj_reader_init(Reader reader, VALUE io, int fd, bool to_s);
28
30
  extern int oj_reader_read(Reader reader);
@@ -114,7 +116,7 @@ static inline int reader_expect(Reader reader, const char *s) {
114
116
 
115
117
  static inline void reader_cleanup(Reader reader) {
116
118
  if (reader->free_head && 0 != reader->head) {
117
- xfree((char *)reader->head);
119
+ OJ_R_FREE((char *)reader->head);
118
120
  reader->head = 0;
119
121
  reader->free_head = 0;
120
122
  }
data/ext/oj/resolve.c CHANGED
@@ -27,12 +27,11 @@ inline static VALUE resolve_classname(VALUE mod, const char *classname, int auto
27
27
  return clas;
28
28
  }
29
29
 
30
- static VALUE
31
- resolve_classpath(ParseInfo pi, const char *name, size_t len, int auto_define, VALUE error_class) {
30
+ static VALUE resolve_classpath(ParseInfo pi, const char *name, size_t len, int auto_define, VALUE error_class) {
32
31
  char class_name[1024];
33
32
  VALUE clas;
34
- char * end = class_name + sizeof(class_name) - 1;
35
- char * s;
33
+ char *end = class_name + sizeof(class_name) - 1;
34
+ char *s;
36
35
  const char *n = name;
37
36
 
38
37
  clas = rb_cObject;
data/ext/oj/rxclass.c CHANGED
@@ -10,6 +10,7 @@
10
10
  #include <regex.h>
11
11
  #endif
12
12
 
13
+ #include "mem.h"
13
14
  #include "rxclass.h"
14
15
 
15
16
  typedef struct _rxC {
@@ -20,7 +21,7 @@ typedef struct _rxC {
20
21
  #endif
21
22
  VALUE clas;
22
23
  char src[256];
23
- } * RxC;
24
+ } *RxC;
24
25
 
25
26
  void oj_rxclass_init(RxClass rc) {
26
27
  *rc->err = '\0';
@@ -37,13 +38,13 @@ void oj_rxclass_cleanup(RxClass rc) {
37
38
  if (Qnil == rxc->rrx) {
38
39
  regfree(&rxc->rx);
39
40
  }
40
- xfree(rxc);
41
+ OJ_R_FREE(rxc);
41
42
  #endif
42
43
  }
43
44
  }
44
45
 
45
46
  void oj_rxclass_rappend(RxClass rc, VALUE rx, VALUE clas) {
46
- RxC rxc = ALLOC_N(struct _rxC, 1);
47
+ RxC rxc = OJ_R_ALLOC_N(struct _rxC, 1);
47
48
 
48
49
  memset(rxc, 0, sizeof(struct _rxC));
49
50
  rxc->rrx = rx;
@@ -70,7 +71,7 @@ int oj_rxclass_append(RxClass rc, const char *expr, VALUE clas) {
70
71
  (unsigned long)sizeof(rxc->src));
71
72
  return EINVAL;
72
73
  }
73
- rxc = ALLOC_N(struct _rxC, 1);
74
+ rxc = OJ_R_ALLOC_N(struct _rxC, 1);
74
75
  rxc->next = 0;
75
76
  rxc->clas = clas;
76
77
 
@@ -80,7 +81,7 @@ int oj_rxclass_append(RxClass rc, const char *expr, VALUE clas) {
80
81
  rxc->rrx = Qnil;
81
82
  if (0 != (err = regcomp(&rxc->rx, expr, flags))) {
82
83
  regerror(err, &rxc->rx, rc->err, sizeof(rc->err));
83
- free(rxc);
84
+ OJ_FREE(rxc);
84
85
  return err;
85
86
  }
86
87
  #endif
data/ext/oj/rxclass.h CHANGED
@@ -14,7 +14,7 @@ typedef struct _rxClass {
14
14
  struct _rxC *head;
15
15
  struct _rxC *tail;
16
16
  char err[128];
17
- } * RxClass;
17
+ } *RxClass;
18
18
 
19
19
  extern void oj_rxclass_init(RxClass rc);
20
20
  extern void oj_rxclass_cleanup(RxClass rc);
data/ext/oj/saj.c CHANGED
@@ -15,6 +15,7 @@
15
15
  #define OJ_INFINITY (1.0 / 0.0)
16
16
 
17
17
  #include "encode.h"
18
+ #include "mem.h"
18
19
  #include "oj.h"
19
20
 
20
21
  typedef struct _parseInfo {
@@ -28,7 +29,7 @@ typedef struct _parseInfo {
28
29
  int has_array_end;
29
30
  int has_add_value;
30
31
  int has_error;
31
- } * ParseInfo;
32
+ } *ParseInfo;
32
33
 
33
34
  static void read_next(ParseInfo pi, const char *key);
34
35
  static void read_hash(ParseInfo pi, const char *key);
@@ -210,10 +211,7 @@ static void read_hash(ParseInfo pi, const char *key) {
210
211
  pi->s++;
211
212
  } else {
212
213
  if (pi->has_error) {
213
- call_error("invalid format, expected , or } while in an object",
214
- pi,
215
- __FILE__,
216
- __LINE__);
214
+ call_error("invalid format, expected , or } while in an object", pi, __FILE__, __LINE__);
217
215
  }
218
216
  raise_error("invalid format, expected , or } while in an object", pi->str, pi->s);
219
217
  }
@@ -243,10 +241,7 @@ static void read_array(ParseInfo pi, const char *key) {
243
241
  break;
244
242
  } else {
245
243
  if (pi->has_error) {
246
- call_error("invalid format, expected , or ] while in an array",
247
- pi,
248
- __FILE__,
249
- __LINE__);
244
+ call_error("invalid format, expected , or ] while in an array", pi, __FILE__, __LINE__);
250
245
  }
251
246
  raise_error("invalid format, expected , or ] while in an array", pi->str, pi->s);
252
247
  }
@@ -276,7 +271,7 @@ static void read_str(ParseInfo pi, const char *key) {
276
271
  #endif
277
272
 
278
273
  static void read_num(ParseInfo pi, const char *key) {
279
- char * start = pi->s;
274
+ char *start = pi->s;
280
275
  int64_t n = 0;
281
276
  long a = 0;
282
277
  long div = 1;
@@ -351,9 +346,7 @@ static void read_num(ParseInfo pi, const char *key) {
351
346
 
352
347
  *pi->s = '\0';
353
348
  if (pi->has_add_value) {
354
- call_add_value(pi->handler,
355
- rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new2(start)),
356
- key);
349
+ call_add_value(pi->handler, rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new2(start)), key);
357
350
  }
358
351
  *pi->s = c;
359
352
  } else {
@@ -371,9 +364,7 @@ static void read_num(ParseInfo pi, const char *key) {
371
364
 
372
365
  *pi->s = '\0';
373
366
  if (pi->has_add_value) {
374
- call_add_value(pi->handler,
375
- rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new2(start)),
376
- key);
367
+ call_add_value(pi->handler, rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new2(start)), key);
377
368
  }
378
369
  *pi->s = c;
379
370
  } else {
@@ -505,9 +496,9 @@ static char *unicode_to_chars(ParseInfo pi, char *t, uint32_t code) {
505
496
  * reached again. Do not read the character after the terminating quote.
506
497
  */
507
498
  static char *read_quoted_value(ParseInfo pi) {
508
- char * value = 0;
509
- char * h = pi->s; /* head */
510
- char * t = h; /* tail */
499
+ char *value = 0;
500
+ char *h = pi->s; /* head */
501
+ char *t = h; /* tail */
511
502
  uint32_t code;
512
503
 
513
504
  h++; /* skip quote character */
@@ -588,15 +579,13 @@ static void saj_parse(VALUE handler, char *json) {
588
579
  pi.str = json;
589
580
  pi.s = json;
590
581
  #if IS_WINDOWS
591
- pi.stack_min = (void *)((char *)&obj -
592
- (512 * 1024)); /* assume a 1M stack and give half to ruby */
582
+ pi.stack_min = (void *)((char *)&obj - (512L * 1024L)); /* assume a 1M stack and give half to ruby */
593
583
  #else
594
584
  {
595
585
  struct rlimit lim;
596
586
 
597
587
  if (0 == getrlimit(RLIMIT_STACK, &lim) && RLIM_INFINITY != lim.rlim_cur) {
598
- pi.stack_min = (void *)((char *)&obj - (lim.rlim_cur / 4 *
599
- 3)); /* let 3/4ths of the stack be used only */
588
+ pi.stack_min = (void *)((char *)&obj - (lim.rlim_cur / 4 * 3)); /* let 3/4ths of the stack be used only */
600
589
  } else {
601
590
  pi.stack_min = 0; /* indicates not to check stack limit */
602
591
  }
@@ -633,7 +622,7 @@ static void saj_parse(VALUE handler, char *json) {
633
622
  */
634
623
  VALUE
635
624
  oj_saj_parse(int argc, VALUE *argv, VALUE self) {
636
- char * json = 0;
625
+ char *json = 0;
637
626
  size_t len = 0;
638
627
  VALUE input = argv[1];
639
628
 
@@ -643,7 +632,7 @@ oj_saj_parse(int argc, VALUE *argv, VALUE self) {
643
632
  if (rb_type(input) == T_STRING) {
644
633
  // the json string gets modified so make a copy of it
645
634
  len = RSTRING_LEN(input) + 1;
646
- json = ALLOC_N(char, len);
635
+ json = OJ_R_ALLOC_N(char, len);
647
636
  strcpy(json, StringValuePtr(input));
648
637
  } else {
649
638
  VALUE clas = rb_obj_class(input);
@@ -652,8 +641,8 @@ oj_saj_parse(int argc, VALUE *argv, VALUE self) {
652
641
  if (oj_stringio_class == clas) {
653
642
  s = rb_funcall2(input, oj_string_id, 0, 0);
654
643
  len = RSTRING_LEN(s) + 1;
655
- json = ALLOC_N(char, len);
656
- strcpy(json, rb_string_value_cstr((VALUE *)&s));
644
+ json = OJ_R_ALLOC_N(char, len);
645
+ strcpy(json, StringValueCStr(s));
657
646
  #if !IS_WINDOWS
658
647
  } else if (rb_cFile == clas && 0 == FIX2INT(rb_funcall(input, oj_pos_id, 0))) {
659
648
  int fd = FIX2INT(rb_funcall(input, oj_fileno_id, 0));
@@ -661,7 +650,7 @@ oj_saj_parse(int argc, VALUE *argv, VALUE self) {
661
650
 
662
651
  len = lseek(fd, 0, SEEK_END);
663
652
  lseek(fd, 0, SEEK_SET);
664
- json = ALLOC_N(char, len + 1);
653
+ json = OJ_R_ALLOC_N(char, len + 1);
665
654
  if (0 >= (cnt = read(fd, json, len)) || cnt != (ssize_t)len) {
666
655
  rb_raise(rb_eIOError, "failed to read from IO Object.");
667
656
  }
@@ -670,14 +659,14 @@ oj_saj_parse(int argc, VALUE *argv, VALUE self) {
670
659
  } else if (rb_respond_to(input, oj_read_id)) {
671
660
  s = rb_funcall2(input, oj_read_id, 0, 0);
672
661
  len = RSTRING_LEN(s) + 1;
673
- json = ALLOC_N(char, len);
674
- strcpy(json, rb_string_value_cstr((VALUE *)&s));
662
+ json = OJ_R_ALLOC_N(char, len);
663
+ strcpy(json, StringValueCStr(s));
675
664
  } else {
676
665
  rb_raise(rb_eArgError, "saj_parse() expected a String or IO Object.");
677
666
  }
678
667
  }
679
668
  saj_parse(*argv, json);
680
- xfree(json);
669
+ OJ_R_FREE(json);
681
670
 
682
671
  return Qnil;
683
672
  }