oj 2.18.3 → 3.13.14

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