oj 2.18.3 → 3.13.14

Sign up to get free protection for your applications and to get access to all the features.
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);