oj 3.9.1 → 3.16.11

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