oj 3.11.0 → 3.16.5

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 (173) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1421 -0
  3. data/README.md +20 -5
  4. data/RELEASE_NOTES.md +61 -0
  5. data/ext/oj/buf.h +48 -38
  6. data/ext/oj/cache.c +329 -0
  7. data/ext/oj/cache.h +22 -0
  8. data/ext/oj/cache8.c +60 -62
  9. data/ext/oj/cache8.h +8 -7
  10. data/ext/oj/circarray.c +35 -35
  11. data/ext/oj/circarray.h +11 -9
  12. data/ext/oj/code.c +156 -174
  13. data/ext/oj/code.h +19 -18
  14. data/ext/oj/compat.c +140 -197
  15. data/ext/oj/custom.c +737 -879
  16. data/ext/oj/debug.c +126 -0
  17. data/ext/oj/dump.c +830 -835
  18. data/ext/oj/dump.h +65 -53
  19. data/ext/oj/dump_compat.c +566 -642
  20. data/ext/oj/dump_leaf.c +95 -182
  21. data/ext/oj/dump_object.c +518 -659
  22. data/ext/oj/dump_strict.c +301 -334
  23. data/ext/oj/encode.h +3 -4
  24. data/ext/oj/encoder.c +43 -0
  25. data/ext/oj/err.c +27 -24
  26. data/ext/oj/err.h +38 -13
  27. data/ext/oj/extconf.rb +23 -7
  28. data/ext/oj/fast.c +1043 -1073
  29. data/ext/oj/intern.c +313 -0
  30. data/ext/oj/intern.h +22 -0
  31. data/ext/oj/mem.c +318 -0
  32. data/ext/oj/mem.h +53 -0
  33. data/ext/oj/mimic_json.c +449 -423
  34. data/ext/oj/object.c +530 -576
  35. data/ext/oj/odd.c +155 -138
  36. data/ext/oj/odd.h +24 -22
  37. data/ext/oj/oj.c +1331 -993
  38. data/ext/oj/oj.h +306 -292
  39. data/ext/oj/parse.c +934 -938
  40. data/ext/oj/parse.h +73 -70
  41. data/ext/oj/parser.c +1600 -0
  42. data/ext/oj/parser.h +101 -0
  43. data/ext/oj/rails.c +795 -845
  44. data/ext/oj/rails.h +7 -7
  45. data/ext/oj/reader.c +132 -140
  46. data/ext/oj/reader.h +67 -78
  47. data/ext/oj/resolve.c +40 -59
  48. data/ext/oj/resolve.h +3 -2
  49. data/ext/oj/rxclass.c +67 -67
  50. data/ext/oj/rxclass.h +11 -9
  51. data/ext/oj/saj.c +441 -480
  52. data/ext/oj/saj2.c +584 -0
  53. data/ext/oj/saj2.h +23 -0
  54. data/ext/oj/scp.c +78 -111
  55. data/ext/oj/sparse.c +726 -730
  56. data/ext/oj/stream_writer.c +146 -165
  57. data/ext/oj/strict.c +103 -123
  58. data/ext/oj/string_writer.c +241 -253
  59. data/ext/oj/trace.c +29 -33
  60. data/ext/oj/trace.h +41 -11
  61. data/ext/oj/usual.c +1218 -0
  62. data/ext/oj/usual.h +69 -0
  63. data/ext/oj/util.c +103 -103
  64. data/ext/oj/util.h +3 -2
  65. data/ext/oj/val_stack.c +60 -49
  66. data/ext/oj/val_stack.h +79 -85
  67. data/ext/oj/validate.c +46 -0
  68. data/ext/oj/wab.c +307 -350
  69. data/lib/oj/active_support_helper.rb +1 -3
  70. data/lib/oj/bag.rb +8 -1
  71. data/lib/oj/easy_hash.rb +9 -9
  72. data/lib/oj/error.rb +1 -2
  73. data/lib/oj/json.rb +162 -150
  74. data/lib/oj/mimic.rb +9 -19
  75. data/lib/oj/saj.rb +20 -6
  76. data/lib/oj/schandler.rb +5 -4
  77. data/lib/oj/state.rb +12 -8
  78. data/lib/oj/version.rb +1 -2
  79. data/lib/oj.rb +2 -0
  80. data/pages/Compatibility.md +1 -1
  81. data/pages/InstallOptions.md +20 -0
  82. data/pages/JsonGem.md +15 -0
  83. data/pages/Modes.md +8 -3
  84. data/pages/Options.md +43 -5
  85. data/pages/Parser.md +309 -0
  86. data/pages/Rails.md +14 -2
  87. data/test/_test_active.rb +8 -9
  88. data/test/_test_active_mimic.rb +7 -8
  89. data/test/_test_mimic_rails.rb +17 -20
  90. data/test/activerecord/result_test.rb +12 -8
  91. data/test/activesupport6/encoding_test.rb +63 -28
  92. data/test/{activesupport5 → activesupport7}/abstract_unit.rb +16 -12
  93. data/test/{activesupport5 → activesupport7}/decoding_test.rb +2 -10
  94. data/test/{activesupport5 → activesupport7}/encoding_test.rb +86 -50
  95. data/test/{activesupport5 → activesupport7}/encoding_test_cases.rb +6 -0
  96. data/test/{activesupport5 → activesupport7}/time_zone_test_helpers.rb +8 -0
  97. data/test/files.rb +15 -15
  98. data/test/foo.rb +17 -43
  99. data/test/helper.rb +16 -3
  100. data/test/isolated/shared.rb +3 -2
  101. data/test/json_gem/json_addition_test.rb +2 -2
  102. data/test/json_gem/json_common_interface_test.rb +8 -6
  103. data/test/json_gem/json_encoding_test.rb +0 -0
  104. data/test/json_gem/json_ext_parser_test.rb +1 -0
  105. data/test/json_gem/json_fixtures_test.rb +3 -2
  106. data/test/json_gem/json_generator_test.rb +71 -41
  107. data/test/json_gem/json_generic_object_test.rb +11 -11
  108. data/test/json_gem/json_parser_test.rb +54 -47
  109. data/test/json_gem/json_string_matching_test.rb +9 -9
  110. data/test/json_gem/test_helper.rb +12 -0
  111. data/test/mem.rb +34 -0
  112. data/test/perf.rb +22 -27
  113. data/test/perf_compat.rb +31 -33
  114. data/test/perf_dump.rb +50 -0
  115. data/test/perf_fast.rb +80 -82
  116. data/test/perf_file.rb +27 -29
  117. data/test/perf_object.rb +65 -69
  118. data/test/perf_once.rb +59 -0
  119. data/test/perf_parser.rb +183 -0
  120. data/test/perf_saj.rb +46 -54
  121. data/test/perf_scp.rb +58 -69
  122. data/test/perf_simple.rb +41 -39
  123. data/test/perf_strict.rb +74 -82
  124. data/test/perf_wab.rb +67 -69
  125. data/test/prec.rb +5 -5
  126. data/test/sample/change.rb +0 -1
  127. data/test/sample/dir.rb +0 -1
  128. data/test/sample/doc.rb +0 -1
  129. data/test/sample/file.rb +0 -1
  130. data/test/sample/group.rb +0 -1
  131. data/test/sample/hasprops.rb +0 -1
  132. data/test/sample/layer.rb +0 -1
  133. data/test/sample/rect.rb +0 -1
  134. data/test/sample/shape.rb +0 -1
  135. data/test/sample/text.rb +0 -1
  136. data/test/sample.rb +16 -16
  137. data/test/sample_json.rb +8 -8
  138. data/test/test_compat.rb +97 -45
  139. data/test/test_custom.rb +73 -51
  140. data/test/test_debian.rb +7 -10
  141. data/test/test_fast.rb +135 -79
  142. data/test/test_file.rb +41 -30
  143. data/test/test_gc.rb +16 -5
  144. data/test/test_generate.rb +21 -0
  145. data/test/test_hash.rb +15 -5
  146. data/test/test_integer_range.rb +9 -9
  147. data/test/test_null.rb +20 -20
  148. data/test/test_object.rb +99 -96
  149. data/test/test_parser.rb +11 -0
  150. data/test/test_parser_debug.rb +27 -0
  151. data/test/test_parser_saj.rb +337 -0
  152. data/test/test_parser_usual.rb +251 -0
  153. data/test/test_rails.rb +2 -2
  154. data/test/test_saj.rb +10 -8
  155. data/test/test_scp.rb +38 -40
  156. data/test/test_strict.rb +40 -32
  157. data/test/test_various.rb +165 -84
  158. data/test/test_wab.rb +48 -44
  159. data/test/test_writer.rb +47 -47
  160. data/test/tests.rb +13 -5
  161. data/test/tests_mimic.rb +12 -3
  162. data/test/tests_mimic_addition.rb +12 -3
  163. metadata +75 -127
  164. data/ext/oj/hash.c +0 -135
  165. data/ext/oj/hash.h +0 -18
  166. data/ext/oj/hash_test.c +0 -484
  167. data/test/activesupport4/decoding_test.rb +0 -108
  168. data/test/activesupport4/encoding_test.rb +0 -531
  169. data/test/activesupport4/test_helper.rb +0 -41
  170. data/test/activesupport5/test_helper.rb +0 -72
  171. data/test/bar.rb +0 -35
  172. data/test/baz.rb +0 -16
  173. data/test/zoo.rb +0 -13
data/ext/oj/saj.c CHANGED
@@ -1,45 +1,47 @@
1
1
  // Copyright (c) 2012 Peter Ohler. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file in the project root for license details.
2
3
 
3
4
  #if !IS_WINDOWS
4
- #include <sys/resource.h> /* for getrlimit() on linux */
5
+ #include <sys/resource.h> /* for getrlimit() on linux */
5
6
  #endif
6
- #include <stdlib.h>
7
+ #include <math.h>
7
8
  #include <stdio.h>
9
+ #include <stdlib.h>
8
10
  #include <string.h>
9
- #include <math.h>
10
11
  #include <sys/types.h>
11
12
  #include <unistd.h>
12
13
 
13
14
  // Workaround in case INFINITY is not defined in math.h or if the OS is CentOS
14
- #define OJ_INFINITY (1.0/0.0)
15
+ #define OJ_INFINITY (1.0 / 0.0)
15
16
 
16
- #include "oj.h"
17
17
  #include "encode.h"
18
+ #include "mem.h"
19
+ #include "oj.h"
18
20
 
19
21
  typedef struct _parseInfo {
20
- char *str; /* buffer being read from */
21
- char *s; /* current position in buffer */
22
- void *stack_min;
23
- VALUE handler;
24
- int has_hash_start;
25
- int has_hash_end;
26
- int has_array_start;
27
- int has_array_end;
28
- int has_add_value;
29
- int has_error;
22
+ char *str; /* buffer being read from */
23
+ char *s; /* current position in buffer */
24
+ void *stack_min;
25
+ VALUE handler;
26
+ int has_hash_start;
27
+ int has_hash_end;
28
+ int has_array_start;
29
+ int has_array_end;
30
+ int has_add_value;
31
+ int has_error;
30
32
  } *ParseInfo;
31
33
 
32
- static void read_next(ParseInfo pi, const char *key);
33
- static void read_hash(ParseInfo pi, const char *key);
34
- static void read_array(ParseInfo pi, const char *key);
35
- static void read_str(ParseInfo pi, const char *key);
36
- static void read_num(ParseInfo pi, const char *key);
37
- static void read_true(ParseInfo pi, const char *key);
38
- static void read_false(ParseInfo pi, const char *key);
39
- static void read_nil(ParseInfo pi, const char *key);
40
- static void next_non_white(ParseInfo pi);
41
- static char* read_quoted_value(ParseInfo pi);
42
- static void skip_comment(ParseInfo pi);
34
+ static void read_next(ParseInfo pi, const char *key);
35
+ static void read_hash(ParseInfo pi, const char *key);
36
+ static void read_array(ParseInfo pi, const char *key);
37
+ static void read_str(ParseInfo pi, const char *key);
38
+ static void read_num(ParseInfo pi, const char *key);
39
+ static void read_true(ParseInfo pi, const char *key);
40
+ static void read_false(ParseInfo pi, const char *key);
41
+ static void read_nil(ParseInfo pi, const char *key);
42
+ static void next_non_white(ParseInfo pi);
43
+ static char *read_quoted_value(ParseInfo pi);
44
+ static void skip_comment(ParseInfo pi);
43
45
 
44
46
  /* This JSON parser is a single pass, destructive, callback parser. It is a
45
47
  * single pass parse since it only make one pass over the characters in the
@@ -54,126 +56,108 @@ static void skip_comment(ParseInfo pi);
54
56
  * all cases to parse the string.
55
57
  */
56
58
 
57
- inline static void
58
- call_error(const char *msg, ParseInfo pi, const char* file, int line) {
59
- char buf[128];
60
- const char *s = pi->s;
61
- int jline = 1;
62
- int col = 1;
59
+ inline static void call_error(const char *msg, ParseInfo pi, const char *file, int line) {
60
+ char buf[128];
61
+ const char *s = pi->s;
62
+ int jline = 1;
63
+ int col = 1;
63
64
 
64
65
  for (; pi->str < s && '\n' != *s; s--) {
65
- col++;
66
+ col++;
66
67
  }
67
68
  for (; pi->str < s; s--) {
68
- if ('\n' == *s) {
69
- jline++;
70
- }
69
+ if ('\n' == *s) {
70
+ jline++;
71
+ }
71
72
  }
72
73
  sprintf(buf, "%s at line %d, column %d [%s:%d]", msg, jline, col, file, line);
73
74
  rb_funcall(pi->handler, oj_error_id, 3, rb_str_new2(buf), LONG2NUM(jline), LONG2NUM(col));
74
75
  }
75
76
 
76
- inline static void
77
- next_non_white(ParseInfo pi) {
77
+ inline static void next_non_white(ParseInfo pi) {
78
78
  for (; 1; pi->s++) {
79
- switch(*pi->s) {
80
- case ' ':
81
- case '\t':
82
- case '\f':
83
- case '\n':
84
- case '\r':
85
- break;
86
- case '/':
87
- skip_comment(pi);
88
- break;
89
- default:
90
- return;
91
- }
79
+ switch (*pi->s) {
80
+ case ' ':
81
+ case '\t':
82
+ case '\f':
83
+ case '\n':
84
+ case '\r': break;
85
+ case '/': skip_comment(pi); break;
86
+ default: return;
87
+ }
92
88
  }
93
89
  }
94
90
 
95
- inline static void
96
- call_add_value(VALUE handler, VALUE value, const char *key) {
97
- volatile VALUE k;
91
+ inline static void call_add_value(VALUE handler, VALUE value, const char *key) {
92
+ volatile VALUE k;
98
93
 
99
94
  if (0 == key) {
100
- k = Qnil;
95
+ k = Qnil;
101
96
  } else {
102
- k = rb_str_new2(key);
103
- k = oj_encode(k);
97
+ k = rb_str_new2(key);
98
+ k = oj_encode(k);
104
99
  }
105
100
  rb_funcall(handler, oj_add_value_id, 2, value, k);
106
101
  }
107
102
 
108
- inline static void
109
- call_no_value(VALUE handler, ID method, const char *key) {
110
- volatile VALUE k;
103
+ inline static void call_no_value(VALUE handler, ID method, const char *key) {
104
+ volatile VALUE k;
111
105
 
112
106
  if (0 == key) {
113
- k = Qnil;
107
+ k = Qnil;
114
108
  } else {
115
- k = rb_str_new2(key);
116
- k = oj_encode(k);
109
+ k = rb_str_new2(key);
110
+ k = oj_encode(k);
117
111
  }
118
112
  rb_funcall(handler, method, 1, k);
119
113
  }
120
114
 
121
- static void
122
- skip_comment(ParseInfo pi) {
115
+ static void skip_comment(ParseInfo pi) {
123
116
  pi->s++; /* skip first / */
124
117
  if ('*' == *pi->s) {
125
- pi->s++;
126
- for (; '\0' != *pi->s; pi->s++) {
127
- if ('*' == *pi->s && '/' == *(pi->s + 1)) {
128
- pi->s++;
129
- return;
130
- } else if ('\0' == *pi->s) {
131
- if (pi->has_error) {
132
- call_error("comment not terminated", pi, __FILE__, __LINE__);
133
- } else {
134
- raise_error("comment not terminated", pi->str, pi->s);
135
- }
136
- }
137
- }
118
+ pi->s++;
119
+ for (; '\0' != *pi->s; pi->s++) {
120
+ if ('*' == *pi->s && '/' == *(pi->s + 1)) {
121
+ pi->s++;
122
+ return;
123
+ } else if ('\0' == *pi->s) {
124
+ if (pi->has_error) {
125
+ call_error("comment not terminated", pi, __FILE__, __LINE__);
126
+ } else {
127
+ raise_error("comment not terminated", pi->str, pi->s);
128
+ }
129
+ }
130
+ }
138
131
  } else if ('/' == *pi->s) {
139
- for (; 1; pi->s++) {
140
- switch (*pi->s) {
141
- case '\n':
142
- case '\r':
143
- case '\f':
144
- case '\0':
145
- return;
146
- default:
147
- break;
148
- }
149
- }
132
+ for (; 1; pi->s++) {
133
+ switch (*pi->s) {
134
+ case '\n':
135
+ case '\r':
136
+ case '\f':
137
+ case '\0': return;
138
+ default: break;
139
+ }
140
+ }
150
141
  } else {
151
- if (pi->has_error) {
152
- call_error("invalid comment", pi, __FILE__, __LINE__);
153
- } else {
154
- raise_error("invalid comment", pi->str, pi->s);
155
- }
142
+ if (pi->has_error) {
143
+ call_error("invalid comment", pi, __FILE__, __LINE__);
144
+ } else {
145
+ raise_error("invalid comment", pi->str, pi->s);
146
+ }
156
147
  }
157
148
  }
158
149
 
159
- static void
160
- read_next(ParseInfo pi, const char *key) {
161
- VALUE obj;
150
+ static void read_next(ParseInfo pi, const char *key) {
151
+ VALUE obj;
162
152
 
163
- if ((void*)&obj < pi->stack_min) {
164
- rb_raise(rb_eSysStackError, "JSON is too deeply nested");
153
+ if ((void *)&obj < pi->stack_min) {
154
+ rb_raise(rb_eSysStackError, "JSON is too deeply nested");
165
155
  }
166
- next_non_white(pi); /* skip white space */
156
+ next_non_white(pi); /* skip white space */
167
157
  switch (*pi->s) {
168
- case '{':
169
- read_hash(pi, key);
170
- break;
171
- case '[':
172
- read_array(pi, key);
173
- break;
174
- case '"':
175
- read_str(pi, key);
176
- break;
158
+ case '{': read_hash(pi, key); break;
159
+ case '[': read_array(pi, key); break;
160
+ case '"': read_str(pi, key); break;
177
161
  case '+':
178
162
  case '-':
179
163
  case '0':
@@ -185,113 +169,98 @@ read_next(ParseInfo pi, const char *key) {
185
169
  case '6':
186
170
  case '7':
187
171
  case '8':
188
- case '9':
189
- read_num(pi, key);
190
- break;
191
- case 'I':
192
- read_num(pi, key);
193
- break;
194
- case 't':
195
- read_true(pi, key);
196
- break;
197
- case 'f':
198
- read_false(pi, key);
199
- break;
200
- case 'n':
201
- read_nil(pi, key);
202
- break;
203
- case '\0':
204
- return;
205
- default:
206
- return;
172
+ case '9': read_num(pi, key); break;
173
+ case 'I': read_num(pi, key); break;
174
+ case 't': read_true(pi, key); break;
175
+ case 'f': read_false(pi, key); break;
176
+ case 'n': read_nil(pi, key); break;
177
+ case '\0': return;
178
+ default: return;
207
179
  }
208
180
  }
209
181
 
210
- static void
211
- read_hash(ParseInfo pi, const char *key) {
212
- const char *ks;
182
+ static void read_hash(ParseInfo pi, const char *key) {
183
+ const char *ks;
213
184
 
214
185
  if (pi->has_hash_start) {
215
- call_no_value(pi->handler, oj_hash_start_id, key);
186
+ call_no_value(pi->handler, oj_hash_start_id, key);
216
187
  }
217
188
  pi->s++;
218
189
  next_non_white(pi);
219
190
  if ('}' == *pi->s) {
220
- pi->s++;
191
+ pi->s++;
221
192
  } else {
222
- while (1) {
223
- next_non_white(pi);
224
- ks = read_quoted_value(pi);
225
- next_non_white(pi);
226
- if (':' == *pi->s) {
227
- pi->s++;
228
- } else {
229
- if (pi->has_error) {
230
- call_error("invalid format, expected :", pi, __FILE__, __LINE__);
231
- }
232
- raise_error("invalid format, expected :", pi->str, pi->s);
233
- }
234
- read_next(pi, ks);
235
- next_non_white(pi);
236
- if ('}' == *pi->s) {
237
- pi->s++;
238
- break;
239
- } else if (',' == *pi->s) {
240
- pi->s++;
241
- } else {
242
- if (pi->has_error) {
243
- call_error("invalid format, expected , or } while in an object", pi, __FILE__, __LINE__);
244
- }
245
- raise_error("invalid format, expected , or } while in an object", pi->str, pi->s);
246
- }
247
- }
193
+ while (1) {
194
+ next_non_white(pi);
195
+ ks = read_quoted_value(pi);
196
+ next_non_white(pi);
197
+ if (':' == *pi->s) {
198
+ pi->s++;
199
+ } else {
200
+ if (pi->has_error) {
201
+ call_error("invalid format, expected :", pi, __FILE__, __LINE__);
202
+ }
203
+ raise_error("invalid format, expected :", pi->str, pi->s);
204
+ }
205
+ read_next(pi, ks);
206
+ next_non_white(pi);
207
+ if ('}' == *pi->s) {
208
+ pi->s++;
209
+ break;
210
+ } else if (',' == *pi->s) {
211
+ pi->s++;
212
+ } else {
213
+ if (pi->has_error) {
214
+ call_error("invalid format, expected , or } while in an object", pi, __FILE__, __LINE__);
215
+ }
216
+ raise_error("invalid format, expected , or } while in an object", pi->str, pi->s);
217
+ }
218
+ }
248
219
  }
249
220
  if (pi->has_hash_end) {
250
- call_no_value(pi->handler, oj_hash_end_id, key);
221
+ call_no_value(pi->handler, oj_hash_end_id, key);
251
222
  }
252
223
  }
253
224
 
254
- static void
255
- read_array(ParseInfo pi, const char *key) {
225
+ static void read_array(ParseInfo pi, const char *key) {
256
226
  if (pi->has_array_start) {
257
- call_no_value(pi->handler, oj_array_start_id, key);
227
+ call_no_value(pi->handler, oj_array_start_id, key);
258
228
  }
259
229
  pi->s++;
260
230
  next_non_white(pi);
261
231
  if (']' == *pi->s) {
262
- pi->s++;
232
+ pi->s++;
263
233
  } else {
264
- while (1) {
265
- read_next(pi, 0);
266
- next_non_white(pi);
267
- if (',' == *pi->s) {
268
- pi->s++;
269
- } else if (']' == *pi->s) {
270
- pi->s++;
271
- break;
272
- } else {
273
- if (pi->has_error) {
274
- call_error("invalid format, expected , or ] while in an array", pi, __FILE__, __LINE__);
275
- }
276
- raise_error("invalid format, expected , or ] while in an array", pi->str, pi->s);
277
- }
278
- }
234
+ while (1) {
235
+ read_next(pi, 0);
236
+ next_non_white(pi);
237
+ if (',' == *pi->s) {
238
+ pi->s++;
239
+ } else if (']' == *pi->s) {
240
+ pi->s++;
241
+ break;
242
+ } else {
243
+ if (pi->has_error) {
244
+ call_error("invalid format, expected , or ] while in an array", pi, __FILE__, __LINE__);
245
+ }
246
+ raise_error("invalid format, expected , or ] while in an array", pi->str, pi->s);
247
+ }
248
+ }
279
249
  }
280
250
  if (pi->has_array_end) {
281
- call_no_value(pi->handler, oj_array_end_id, key);
251
+ call_no_value(pi->handler, oj_array_end_id, key);
282
252
  }
283
253
  }
284
254
 
285
- static void
286
- read_str(ParseInfo pi, const char *key) {
287
- char *text;
255
+ static void read_str(ParseInfo pi, const char *key) {
256
+ char *text;
288
257
 
289
258
  text = read_quoted_value(pi);
290
259
  if (pi->has_add_value) {
291
- VALUE s = rb_str_new2(text);
260
+ VALUE s = rb_str_new2(text);
292
261
 
293
- s = oj_encode(s);
294
- call_add_value(pi->handler, s, key);
262
+ s = oj_encode(s);
263
+ call_add_value(pi->handler, s, key);
295
264
  }
296
265
  }
297
266
 
@@ -301,230 +270,224 @@ read_str(ParseInfo pi, const char *key) {
301
270
  #define NUM_MAX (FIXNUM_MAX >> 8)
302
271
  #endif
303
272
 
304
- static void
305
- read_num(ParseInfo pi, const char *key) {
306
- char *start = pi->s;
307
- int64_t n = 0;
308
- long a = 0;
309
- long div = 1;
310
- long e = 0;
311
- int neg = 0;
312
- int eneg = 0;
313
- int big = 0;
273
+ static void read_num(ParseInfo pi, const char *key) {
274
+ char *start = pi->s;
275
+ int64_t n = 0;
276
+ long a = 0;
277
+ long div = 1;
278
+ long e = 0;
279
+ int neg = 0;
280
+ int eneg = 0;
281
+ int big = 0;
314
282
 
315
283
  if ('-' == *pi->s) {
316
- pi->s++;
317
- neg = 1;
284
+ pi->s++;
285
+ neg = 1;
318
286
  } else if ('+' == *pi->s) {
319
- pi->s++;
287
+ pi->s++;
320
288
  }
321
289
  if ('I' == *pi->s) {
322
- if (0 != strncmp("Infinity", pi->s, 8)) {
323
- if (pi->has_error) {
324
- call_error("number or other value", pi, __FILE__, __LINE__);
325
- }
326
- raise_error("number or other value", pi->str, pi->s);
327
- }
328
- pi->s += 8;
329
- if (neg) {
330
- if (pi->has_add_value) {
331
- call_add_value(pi->handler, rb_float_new(-OJ_INFINITY), key);
332
- }
333
- } else {
334
- if (pi->has_add_value) {
335
- call_add_value(pi->handler, rb_float_new(OJ_INFINITY), key);
336
- }
337
- }
338
- return;
290
+ if (0 != strncmp("Infinity", pi->s, 8)) {
291
+ if (pi->has_error) {
292
+ call_error("number or other value", pi, __FILE__, __LINE__);
293
+ }
294
+ raise_error("number or other value", pi->str, pi->s);
295
+ }
296
+ pi->s += 8;
297
+ if (neg) {
298
+ if (pi->has_add_value) {
299
+ call_add_value(pi->handler, rb_float_new(-OJ_INFINITY), key);
300
+ }
301
+ } else {
302
+ if (pi->has_add_value) {
303
+ call_add_value(pi->handler, rb_float_new(OJ_INFINITY), key);
304
+ }
305
+ }
306
+ return;
339
307
  }
340
308
  for (; '0' <= *pi->s && *pi->s <= '9'; pi->s++) {
341
- if (big) {
342
- big++;
343
- } else {
344
- n = n * 10 + (*pi->s - '0');
345
- if (NUM_MAX <= n) {
346
- big = 1;
347
- }
348
- }
309
+ if (big) {
310
+ big++;
311
+ } else {
312
+ n = n * 10 + (*pi->s - '0');
313
+ if (NUM_MAX <= n) {
314
+ big = 1;
315
+ }
316
+ }
349
317
  }
350
318
  if ('.' == *pi->s) {
351
- pi->s++;
352
- for (; '0' <= *pi->s && *pi->s <= '9'; pi->s++) {
353
- a = a * 10 + (*pi->s - '0');
354
- div *= 10;
355
- if (NUM_MAX <= div) {
356
- big = 1;
357
- }
358
- }
319
+ pi->s++;
320
+ for (; '0' <= *pi->s && *pi->s <= '9'; pi->s++) {
321
+ a = a * 10 + (*pi->s - '0');
322
+ div *= 10;
323
+ if (NUM_MAX <= div) {
324
+ big = 1;
325
+ }
326
+ }
359
327
  }
360
328
  if ('e' == *pi->s || 'E' == *pi->s) {
361
- pi->s++;
362
- if ('-' == *pi->s) {
363
- pi->s++;
364
- eneg = 1;
365
- } else if ('+' == *pi->s) {
366
- pi->s++;
367
- }
368
- for (; '0' <= *pi->s && *pi->s <= '9'; pi->s++) {
369
- e = e * 10 + (*pi->s - '0');
370
- if (NUM_MAX <= e) {
371
- big = 1;
372
- }
373
- }
329
+ pi->s++;
330
+ if ('-' == *pi->s) {
331
+ pi->s++;
332
+ eneg = 1;
333
+ } else if ('+' == *pi->s) {
334
+ pi->s++;
335
+ }
336
+ for (; '0' <= *pi->s && *pi->s <= '9'; pi->s++) {
337
+ e = e * 10 + (*pi->s - '0');
338
+ if (NUM_MAX <= e) {
339
+ big = 1;
340
+ }
341
+ }
374
342
  }
375
343
  if (0 == e && 0 == a && 1 == div) {
376
- if (big) {
377
- char c = *pi->s;
378
-
379
- *pi->s = '\0';
380
- if (pi->has_add_value) {
381
- call_add_value(pi->handler, rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new2(start)), key);
382
- }
383
- *pi->s = c;
384
- } else {
385
- if (neg) {
386
- n = -n;
387
- }
388
- if (pi->has_add_value) {
389
- call_add_value(pi->handler, LONG2NUM(n), key);
390
- }
391
- }
392
- return;
344
+ if (big) {
345
+ char c = *pi->s;
346
+
347
+ *pi->s = '\0';
348
+ if (pi->has_add_value) {
349
+ call_add_value(pi->handler, rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new2(start)), key);
350
+ }
351
+ *pi->s = c;
352
+ } else {
353
+ if (neg) {
354
+ n = -n;
355
+ }
356
+ if (pi->has_add_value) {
357
+ call_add_value(pi->handler, LONG2NUM(n), key);
358
+ }
359
+ }
360
+ return;
393
361
  } else { /* decimal */
394
- if (big) {
395
- char c = *pi->s;
396
-
397
- *pi->s = '\0';
398
- if (pi->has_add_value) {
399
- call_add_value(pi->handler, rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new2(start)), key);
400
- }
401
- *pi->s = c;
402
- } else {
403
- double d = (double)n + (double)a / (double)div;
404
-
405
- if (neg) {
406
- d = -d;
407
- }
408
- if (1 < big) {
409
- e += big - 1;
410
- }
411
- if (0 != e) {
412
- if (eneg) {
413
- e = -e;
414
- }
415
- d *= pow(10.0, e);
416
- }
417
- if (pi->has_add_value) {
418
- call_add_value(pi->handler, rb_float_new(d), key);
419
- }
420
- }
362
+ if (big) {
363
+ char c = *pi->s;
364
+
365
+ *pi->s = '\0';
366
+ if (pi->has_add_value) {
367
+ call_add_value(pi->handler, rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new2(start)), key);
368
+ }
369
+ *pi->s = c;
370
+ } else {
371
+ double d = (double)n + (double)a / (double)div;
372
+
373
+ if (neg) {
374
+ d = -d;
375
+ }
376
+ if (1 < big) {
377
+ e += big - 1;
378
+ }
379
+ if (0 != e) {
380
+ if (eneg) {
381
+ e = -e;
382
+ }
383
+ d *= pow(10.0, e);
384
+ }
385
+ if (pi->has_add_value) {
386
+ call_add_value(pi->handler, rb_float_new(d), key);
387
+ }
388
+ }
421
389
  }
422
390
  }
423
391
 
424
- static void
425
- read_true(ParseInfo pi, const char *key) {
392
+ static void read_true(ParseInfo pi, const char *key) {
426
393
  pi->s++;
427
394
  if ('r' != *pi->s || 'u' != *(pi->s + 1) || 'e' != *(pi->s + 2)) {
428
- if (pi->has_error) {
429
- call_error("invalid format, expected 'true'", pi, __FILE__, __LINE__);
430
- }
431
- raise_error("invalid format, expected 'true'", pi->str, pi->s);
395
+ if (pi->has_error) {
396
+ call_error("invalid format, expected 'true'", pi, __FILE__, __LINE__);
397
+ }
398
+ raise_error("invalid format, expected 'true'", pi->str, pi->s);
432
399
  }
433
400
  pi->s += 3;
434
401
  if (pi->has_add_value) {
435
- call_add_value(pi->handler, Qtrue, key);
402
+ call_add_value(pi->handler, Qtrue, key);
436
403
  }
437
404
  }
438
405
 
439
- static void
440
- read_false(ParseInfo pi, const char *key) {
406
+ static void read_false(ParseInfo pi, const char *key) {
441
407
  pi->s++;
442
408
  if ('a' != *pi->s || 'l' != *(pi->s + 1) || 's' != *(pi->s + 2) || 'e' != *(pi->s + 3)) {
443
- if (pi->has_error) {
444
- call_error("invalid format, expected 'false'", pi, __FILE__, __LINE__);
445
- }
446
- raise_error("invalid format, expected 'false'", pi->str, pi->s);
409
+ if (pi->has_error) {
410
+ call_error("invalid format, expected 'false'", pi, __FILE__, __LINE__);
411
+ }
412
+ raise_error("invalid format, expected 'false'", pi->str, pi->s);
447
413
  }
448
414
  pi->s += 4;
449
415
  if (pi->has_add_value) {
450
- call_add_value(pi->handler, Qfalse, key);
416
+ call_add_value(pi->handler, Qfalse, key);
451
417
  }
452
418
  }
453
419
 
454
- static void
455
- read_nil(ParseInfo pi, const char *key) {
420
+ static void read_nil(ParseInfo pi, const char *key) {
456
421
  pi->s++;
457
422
  if ('u' != *pi->s || 'l' != *(pi->s + 1) || 'l' != *(pi->s + 2)) {
458
- if (pi->has_error) {
459
- call_error("invalid format, expected 'null'", pi, __FILE__, __LINE__);
460
- }
461
- raise_error("invalid format, expected 'null'", pi->str, pi->s);
423
+ if (pi->has_error) {
424
+ call_error("invalid format, expected 'null'", pi, __FILE__, __LINE__);
425
+ }
426
+ raise_error("invalid format, expected 'null'", pi->str, pi->s);
462
427
  }
463
428
  pi->s += 3;
464
429
  if (pi->has_add_value) {
465
- call_add_value(pi->handler, Qnil, key);
430
+ call_add_value(pi->handler, Qnil, key);
466
431
  }
467
432
  }
468
433
 
469
- static uint32_t
470
- read_hex(ParseInfo pi, char *h) {
471
- uint32_t b = 0;
472
- int i;
434
+ static uint32_t read_hex(ParseInfo pi, char *h) {
435
+ uint32_t b = 0;
436
+ int i;
473
437
 
474
438
  /* TBD this can be made faster with a table */
475
439
  for (i = 0; i < 4; i++, h++) {
476
- b = b << 4;
477
- if ('0' <= *h && *h <= '9') {
478
- b += *h - '0';
479
- } else if ('A' <= *h && *h <= 'F') {
480
- b += *h - 'A' + 10;
481
- } else if ('a' <= *h && *h <= 'f') {
482
- b += *h - 'a' + 10;
483
- } else {
484
- pi->s = h;
485
- if (pi->has_error) {
486
- call_error("invalid hex character", pi, __FILE__, __LINE__);
487
- }
488
- raise_error("invalid hex character", pi->str, pi->s);
489
- }
440
+ b = b << 4;
441
+ if ('0' <= *h && *h <= '9') {
442
+ b += *h - '0';
443
+ } else if ('A' <= *h && *h <= 'F') {
444
+ b += *h - 'A' + 10;
445
+ } else if ('a' <= *h && *h <= 'f') {
446
+ b += *h - 'a' + 10;
447
+ } else {
448
+ pi->s = h;
449
+ if (pi->has_error) {
450
+ call_error("invalid hex character", pi, __FILE__, __LINE__);
451
+ }
452
+ raise_error("invalid hex character", pi->str, pi->s);
453
+ }
490
454
  }
491
455
  return b;
492
456
  }
493
457
 
494
- static char*
495
- unicode_to_chars(ParseInfo pi, char *t, uint32_t code) {
458
+ static char *unicode_to_chars(ParseInfo pi, char *t, uint32_t code) {
496
459
  if (0x0000007F >= code) {
497
- *t = (char)code;
460
+ *t = (char)code;
498
461
  } else if (0x000007FF >= code) {
499
- *t++ = 0xC0 | (code >> 6);
500
- *t = 0x80 | (0x3F & code);
462
+ *t++ = 0xC0 | (code >> 6);
463
+ *t = 0x80 | (0x3F & code);
501
464
  } else if (0x0000FFFF >= code) {
502
- *t++ = 0xE0 | (code >> 12);
503
- *t++ = 0x80 | ((code >> 6) & 0x3F);
504
- *t = 0x80 | (0x3F & code);
465
+ *t++ = 0xE0 | (code >> 12);
466
+ *t++ = 0x80 | ((code >> 6) & 0x3F);
467
+ *t = 0x80 | (0x3F & code);
505
468
  } else if (0x001FFFFF >= code) {
506
- *t++ = 0xF0 | (code >> 18);
507
- *t++ = 0x80 | ((code >> 12) & 0x3F);
508
- *t++ = 0x80 | ((code >> 6) & 0x3F);
509
- *t = 0x80 | (0x3F & code);
469
+ *t++ = 0xF0 | (code >> 18);
470
+ *t++ = 0x80 | ((code >> 12) & 0x3F);
471
+ *t++ = 0x80 | ((code >> 6) & 0x3F);
472
+ *t = 0x80 | (0x3F & code);
510
473
  } else if (0x03FFFFFF >= code) {
511
- *t++ = 0xF8 | (code >> 24);
512
- *t++ = 0x80 | ((code >> 18) & 0x3F);
513
- *t++ = 0x80 | ((code >> 12) & 0x3F);
514
- *t++ = 0x80 | ((code >> 6) & 0x3F);
515
- *t = 0x80 | (0x3F & code);
474
+ *t++ = 0xF8 | (code >> 24);
475
+ *t++ = 0x80 | ((code >> 18) & 0x3F);
476
+ *t++ = 0x80 | ((code >> 12) & 0x3F);
477
+ *t++ = 0x80 | ((code >> 6) & 0x3F);
478
+ *t = 0x80 | (0x3F & code);
516
479
  } else if (0x7FFFFFFF >= code) {
517
- *t++ = 0xFC | (code >> 30);
518
- *t++ = 0x80 | ((code >> 24) & 0x3F);
519
- *t++ = 0x80 | ((code >> 18) & 0x3F);
520
- *t++ = 0x80 | ((code >> 12) & 0x3F);
521
- *t++ = 0x80 | ((code >> 6) & 0x3F);
522
- *t = 0x80 | (0x3F & code);
480
+ *t++ = 0xFC | (code >> 30);
481
+ *t++ = 0x80 | ((code >> 24) & 0x3F);
482
+ *t++ = 0x80 | ((code >> 18) & 0x3F);
483
+ *t++ = 0x80 | ((code >> 12) & 0x3F);
484
+ *t++ = 0x80 | ((code >> 6) & 0x3F);
485
+ *t = 0x80 | (0x3F & code);
523
486
  } else {
524
- if (pi->has_error) {
525
- call_error("invalid Unicode", pi, __FILE__, __LINE__);
526
- }
527
- raise_error("invalid Unicode", pi->str, pi->s);
487
+ if (pi->has_error) {
488
+ call_error("invalid Unicode", pi, __FILE__, __LINE__);
489
+ }
490
+ raise_error("invalid Unicode", pi->str, pi->s);
528
491
  }
529
492
  return t;
530
493
  }
@@ -532,119 +495,117 @@ unicode_to_chars(ParseInfo pi, char *t, uint32_t code) {
532
495
  /* Assume the value starts immediately and goes until the quote character is
533
496
  * reached again. Do not read the character after the terminating quote.
534
497
  */
535
- static char*
536
- read_quoted_value(ParseInfo pi) {
537
- char *value = 0;
538
- char *h = pi->s; /* head */
539
- char *t = h; /* tail */
540
- uint32_t code;
541
-
542
- h++; /* skip quote character */
498
+ static char *read_quoted_value(ParseInfo pi) {
499
+ char *value = 0;
500
+ char *h = pi->s; /* head */
501
+ char *t = h; /* tail */
502
+ uint32_t code;
503
+
504
+ h++; /* skip quote character */
543
505
  t++;
544
506
  value = h;
545
507
  for (; '"' != *h; h++, t++) {
546
- if ('\0' == *h) {
547
- pi->s = h;
548
- raise_error("quoted string not terminated", pi->str, pi->s);
549
- } else if ('\\' == *h) {
550
- h++;
551
- switch (*h) {
552
- case 'n': *t = '\n'; break;
553
- case 'r': *t = '\r'; break;
554
- case 't': *t = '\t'; break;
555
- case 'f': *t = '\f'; break;
556
- case 'b': *t = '\b'; break;
557
- case '"': *t = '"'; break;
558
- case '/': *t = '/'; break;
559
- case '\\': *t = '\\'; break;
560
- case 'u':
561
- h++;
562
- code = read_hex(pi, h);
563
- h += 3;
564
- if (0x0000D800 <= code && code <= 0x0000DFFF) {
565
- uint32_t c1 = (code - 0x0000D800) & 0x000003FF;
566
- uint32_t c2;
567
-
568
- h++;
569
- if ('\\' != *h || 'u' != *(h + 1)) {
570
- pi->s = h;
571
- if (pi->has_error) {
572
- call_error("invalid escaped character", pi, __FILE__, __LINE__);
573
- }
574
- raise_error("invalid escaped character", pi->str, pi->s);
575
- }
576
- h += 2;
577
- c2 = read_hex(pi, h);
578
- h += 3;
579
- c2 = (c2 - 0x0000DC00) & 0x000003FF;
580
- code = ((c1 << 10) | c2) + 0x00010000;
581
- }
582
- t = unicode_to_chars(pi, t, code);
583
- break;
584
- default:
585
- pi->s = h;
586
- if (pi->has_error) {
587
- call_error("invalid escaped character", pi, __FILE__, __LINE__);
588
- }
589
- raise_error("invalid escaped character", pi->str, pi->s);
590
- break;
591
- }
592
- } else if (t != h) {
593
- *t = *h;
594
- }
595
- }
596
- *t = '\0'; /* terminate value */
508
+ if ('\0' == *h) {
509
+ pi->s = h;
510
+ raise_error("quoted string not terminated", pi->str, pi->s);
511
+ } else if ('\\' == *h) {
512
+ h++;
513
+ switch (*h) {
514
+ case 'n': *t = '\n'; break;
515
+ case 'r': *t = '\r'; break;
516
+ case 't': *t = '\t'; break;
517
+ case 'f': *t = '\f'; break;
518
+ case 'b': *t = '\b'; break;
519
+ case '"': *t = '"'; break;
520
+ case '/': *t = '/'; break;
521
+ case '\\': *t = '\\'; break;
522
+ case 'u':
523
+ h++;
524
+ code = read_hex(pi, h);
525
+ h += 3;
526
+ if (0x0000D800 <= code && code <= 0x0000DFFF) {
527
+ uint32_t c1 = (code - 0x0000D800) & 0x000003FF;
528
+ uint32_t c2;
529
+
530
+ h++;
531
+ if ('\\' != *h || 'u' != *(h + 1)) {
532
+ pi->s = h;
533
+ if (pi->has_error) {
534
+ call_error("invalid escaped character", pi, __FILE__, __LINE__);
535
+ }
536
+ raise_error("invalid escaped character", pi->str, pi->s);
537
+ }
538
+ h += 2;
539
+ c2 = read_hex(pi, h);
540
+ h += 3;
541
+ c2 = (c2 - 0x0000DC00) & 0x000003FF;
542
+ code = ((c1 << 10) | c2) + 0x00010000;
543
+ }
544
+ t = unicode_to_chars(pi, t, code);
545
+ break;
546
+ default:
547
+ pi->s = h;
548
+ if (pi->has_error) {
549
+ call_error("invalid escaped character", pi, __FILE__, __LINE__);
550
+ }
551
+ raise_error("invalid escaped character", pi->str, pi->s);
552
+ break;
553
+ }
554
+ } else if (t != h) {
555
+ *t = *h;
556
+ }
557
+ }
558
+ *t = '\0'; /* terminate value */
597
559
  pi->s = h + 1;
598
560
 
599
561
  return value;
600
562
  }
601
563
 
602
- static void
603
- saj_parse(VALUE handler, char *json) {
604
- volatile VALUE obj = Qnil;
605
- struct _parseInfo pi;
564
+ static void saj_parse(VALUE handler, char *json) {
565
+ volatile VALUE obj = Qnil;
566
+ struct _parseInfo pi;
606
567
 
607
568
  if (0 == json) {
608
- if (pi.has_error) {
609
- call_error("Invalid arg, xml string can not be null", &pi, __FILE__, __LINE__);
610
- }
611
- raise_error("Invalid arg, xml string can not be null", json, 0);
569
+ if (pi.has_error) {
570
+ call_error("Invalid arg, xml string can not be null", &pi, __FILE__, __LINE__);
571
+ }
572
+ raise_error("Invalid arg, xml string can not be null", json, 0);
612
573
  }
613
574
  /* skip UTF-8 BOM if present */
614
575
  if (0xEF == (uint8_t)*json && 0xBB == (uint8_t)json[1] && 0xBF == (uint8_t)json[2]) {
615
- json += 3;
576
+ json += 3;
616
577
  }
617
578
  /* initialize parse info */
618
579
  pi.str = json;
619
- pi.s = json;
620
- #if IS_WINDOWS
621
- pi.stack_min = (void*)((char*)&obj - (512 * 1024)); /* assume a 1M stack and give half to ruby */
580
+ pi.s = json;
581
+ #if IS_WINDOWS || !defined(HAVE_GETRLIMIT)
582
+ pi.stack_min = (void *)((char *)&obj - (512L * 1024L)); /* assume a 1M stack and give half to ruby */
622
583
  #else
623
584
  {
624
- struct rlimit lim;
585
+ struct rlimit lim;
625
586
 
626
- if (0 == getrlimit(RLIMIT_STACK, &lim) && RLIM_INFINITY != lim.rlim_cur) {
627
- pi.stack_min = (void*)((char*)&obj - (lim.rlim_cur / 4 * 3)); /* let 3/4ths of the stack be used only */
628
- } else {
629
- pi.stack_min = 0; /* indicates not to check stack limit */
630
- }
587
+ if (0 == getrlimit(RLIMIT_STACK, &lim) && RLIM_INFINITY != lim.rlim_cur) {
588
+ pi.stack_min = (void *)((char *)&obj - (lim.rlim_cur / 4 * 3)); /* let 3/4ths of the stack be used only */
589
+ } else {
590
+ pi.stack_min = 0; /* indicates not to check stack limit */
591
+ }
631
592
  }
632
593
  #endif
633
- pi.handler = handler;
634
- pi.has_hash_start = rb_respond_to(handler, oj_hash_start_id);
635
- pi.has_hash_end = rb_respond_to(handler, oj_hash_end_id);
594
+ pi.handler = handler;
595
+ pi.has_hash_start = rb_respond_to(handler, oj_hash_start_id);
596
+ pi.has_hash_end = rb_respond_to(handler, oj_hash_end_id);
636
597
  pi.has_array_start = rb_respond_to(handler, oj_array_start_id);
637
- pi.has_array_end = rb_respond_to(handler, oj_array_end_id);
638
- pi.has_add_value = rb_respond_to(handler, oj_add_value_id);
639
- pi.has_error = rb_respond_to(handler, oj_error_id);
598
+ pi.has_array_end = rb_respond_to(handler, oj_array_end_id);
599
+ pi.has_add_value = rb_respond_to(handler, oj_add_value_id);
600
+ pi.has_error = rb_respond_to(handler, oj_error_id);
640
601
  read_next(&pi, 0);
641
602
  next_non_white(&pi);
642
603
  if ('\0' != *pi.s) {
643
- if (pi.has_error) {
644
- call_error("invalid format, extra characters", &pi, __FILE__, __LINE__);
645
- } else {
646
- raise_error("invalid format, extra characters", pi.str, pi.s);
647
- }
604
+ if (pi.has_error) {
605
+ call_error("invalid format, extra characters", &pi, __FILE__, __LINE__);
606
+ } else {
607
+ raise_error("invalid format, extra characters", pi.str, pi.s);
608
+ }
648
609
  }
649
610
  }
650
611
 
@@ -656,56 +617,56 @@ saj_parse(VALUE handler, char *json) {
656
617
  * @param [IO|String] io IO Object to read from
657
618
  * @deprecated The sc_parse() method along with the ScHandler is the preferred
658
619
  * callback parser. It is slightly faster and handles streams while the
659
- * saj_parse() methos requires a complete read before parsing.
620
+ * saj_parse() method requires a complete read before parsing.
660
621
  * @see sc_parse
661
622
  */
662
623
  VALUE
663
624
  oj_saj_parse(int argc, VALUE *argv, VALUE self) {
664
- char *json = 0;
665
- size_t len = 0;
666
- VALUE input = argv[1];
625
+ char *json = 0;
626
+ size_t len = 0;
627
+ VALUE input = argv[1];
667
628
 
668
629
  if (argc < 2) {
669
- rb_raise(rb_eArgError, "Wrong number of arguments to saj_parse.\n");
630
+ rb_raise(rb_eArgError, "Wrong number of arguments to saj_parse.\n");
670
631
  }
671
632
  if (rb_type(input) == T_STRING) {
672
- // the json string gets modified so make a copy of it
673
- len = RSTRING_LEN(input) + 1;
674
- json = ALLOC_N(char, len);
675
- strcpy(json, StringValuePtr(input));
633
+ // the json string gets modified so make a copy of it
634
+ len = RSTRING_LEN(input) + 1;
635
+ json = OJ_R_ALLOC_N(char, len);
636
+ strcpy(json, StringValuePtr(input));
676
637
  } else {
677
- VALUE clas = rb_obj_class(input);
678
- volatile VALUE s;
679
-
680
- if (oj_stringio_class == clas) {
681
- s = rb_funcall2(input, oj_string_id, 0, 0);
682
- len = RSTRING_LEN(s) + 1;
683
- json = ALLOC_N(char, len);
684
- strcpy(json, rb_string_value_cstr((VALUE*)&s));
638
+ VALUE clas = rb_obj_class(input);
639
+ volatile VALUE s;
640
+
641
+ if (oj_stringio_class == clas) {
642
+ s = rb_funcall2(input, oj_string_id, 0, 0);
643
+ len = RSTRING_LEN(s) + 1;
644
+ json = OJ_R_ALLOC_N(char, len);
645
+ strcpy(json, StringValueCStr(s));
685
646
  #if !IS_WINDOWS
686
- } else if (rb_cFile == clas && 0 == FIX2INT(rb_funcall(input, oj_pos_id, 0))) {
687
- int fd = FIX2INT(rb_funcall(input, oj_fileno_id, 0));
688
- ssize_t cnt;
689
-
690
- len = lseek(fd, 0, SEEK_END);
691
- lseek(fd, 0, SEEK_SET);
692
- json = ALLOC_N(char, len + 1);
693
- if (0 >= (cnt = read(fd, json, len)) || cnt != (ssize_t)len) {
694
- rb_raise(rb_eIOError, "failed to read from IO Object.");
695
- }
696
- json[len] = '\0';
647
+ } else if (rb_cFile == clas && 0 == FIX2INT(rb_funcall(input, oj_pos_id, 0))) {
648
+ int fd = FIX2INT(rb_funcall(input, oj_fileno_id, 0));
649
+ ssize_t cnt;
650
+
651
+ len = lseek(fd, 0, SEEK_END);
652
+ lseek(fd, 0, SEEK_SET);
653
+ json = OJ_R_ALLOC_N(char, len + 1);
654
+ if (0 >= (cnt = read(fd, json, len)) || cnt != (ssize_t)len) {
655
+ rb_raise(rb_eIOError, "failed to read from IO Object.");
656
+ }
657
+ json[len] = '\0';
697
658
  #endif
698
- } else if (rb_respond_to(input, oj_read_id)) {
699
- s = rb_funcall2(input, oj_read_id, 0, 0);
700
- len = RSTRING_LEN(s) + 1;
701
- json = ALLOC_N(char, len);
702
- strcpy(json, rb_string_value_cstr((VALUE*)&s));
703
- } else {
704
- rb_raise(rb_eArgError, "saj_parse() expected a String or IO Object.");
705
- }
659
+ } else if (rb_respond_to(input, oj_read_id)) {
660
+ s = rb_funcall2(input, oj_read_id, 0, 0);
661
+ len = RSTRING_LEN(s) + 1;
662
+ json = OJ_R_ALLOC_N(char, len);
663
+ strcpy(json, StringValueCStr(s));
664
+ } else {
665
+ rb_raise(rb_eArgError, "saj_parse() expected a String or IO Object.");
666
+ }
706
667
  }
707
668
  saj_parse(*argv, json);
708
- xfree(json);
669
+ OJ_R_FREE(json);
709
670
 
710
671
  return Qnil;
711
672
  }