oj 2.18.5 → 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 (166) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1452 -0
  3. data/README.md +53 -221
  4. data/RELEASE_NOTES.md +61 -0
  5. data/ext/oj/buf.h +54 -72
  6. data/ext/oj/cache.c +329 -0
  7. data/ext/oj/cache.h +22 -0
  8. data/ext/oj/cache8.c +61 -63
  9. data/ext/oj/cache8.h +12 -39
  10. data/ext/oj/circarray.c +38 -67
  11. data/ext/oj/circarray.h +16 -42
  12. data/ext/oj/code.c +214 -0
  13. data/ext/oj/code.h +40 -0
  14. data/ext/oj/compat.c +194 -110
  15. data/ext/oj/custom.c +1074 -0
  16. data/ext/oj/debug.c +126 -0
  17. data/ext/oj/dump.c +1276 -2494
  18. data/ext/oj/dump.h +110 -0
  19. data/ext/oj/dump_compat.c +897 -0
  20. data/ext/oj/dump_leaf.c +162 -0
  21. data/ext/oj/dump_object.c +710 -0
  22. data/ext/oj/dump_strict.c +399 -0
  23. data/ext/oj/encode.h +7 -42
  24. data/ext/oj/encoder.c +43 -0
  25. data/ext/oj/err.c +28 -53
  26. data/ext/oj/err.h +49 -46
  27. data/ext/oj/extconf.rb +33 -32
  28. data/ext/oj/fast.c +1082 -1098
  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 +919 -0
  34. data/ext/oj/object.c +545 -625
  35. data/ext/oj/odd.c +158 -168
  36. data/ext/oj/odd.h +32 -58
  37. data/ext/oj/oj.c +1727 -2080
  38. data/ext/oj/oj.h +334 -259
  39. data/ext/oj/parse.c +974 -753
  40. data/ext/oj/parse.h +97 -90
  41. data/ext/oj/parser.c +1600 -0
  42. data/ext/oj/parser.h +103 -0
  43. data/ext/oj/rails.c +1478 -0
  44. data/ext/oj/rails.h +18 -0
  45. data/ext/oj/reader.c +136 -163
  46. data/ext/oj/reader.h +76 -112
  47. data/ext/oj/resolve.c +45 -94
  48. data/ext/oj/resolve.h +7 -34
  49. data/ext/oj/rxclass.c +144 -0
  50. data/ext/oj/rxclass.h +26 -0
  51. data/ext/oj/saj.c +445 -511
  52. data/ext/oj/saj2.c +584 -0
  53. data/ext/oj/saj2.h +23 -0
  54. data/ext/oj/scp.c +82 -143
  55. data/ext/oj/simd.h +10 -0
  56. data/ext/oj/sparse.c +749 -644
  57. data/ext/oj/stream_writer.c +329 -0
  58. data/ext/oj/strict.c +114 -112
  59. data/ext/oj/string_writer.c +517 -0
  60. data/ext/oj/trace.c +72 -0
  61. data/ext/oj/trace.h +55 -0
  62. data/ext/oj/usual.c +1218 -0
  63. data/ext/oj/usual.h +69 -0
  64. data/ext/oj/util.c +136 -0
  65. data/ext/oj/util.h +20 -0
  66. data/ext/oj/val_stack.c +75 -72
  67. data/ext/oj/val_stack.h +94 -127
  68. data/ext/oj/validate.c +46 -0
  69. data/ext/oj/wab.c +586 -0
  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 +21 -13
  73. data/lib/oj/error.rb +10 -12
  74. data/lib/oj/json.rb +188 -0
  75. data/lib/oj/mimic.rb +165 -26
  76. data/lib/oj/saj.rb +20 -6
  77. data/lib/oj/schandler.rb +5 -4
  78. data/lib/oj/state.rb +135 -0
  79. data/lib/oj/version.rb +2 -3
  80. data/lib/oj.rb +3 -31
  81. data/pages/Advanced.md +22 -0
  82. data/pages/Compatibility.md +25 -0
  83. data/pages/Custom.md +23 -0
  84. data/pages/Encoding.md +65 -0
  85. data/pages/InstallOptions.md +20 -0
  86. data/pages/JsonGem.md +94 -0
  87. data/pages/Modes.md +161 -0
  88. data/pages/Options.md +337 -0
  89. data/pages/Parser.md +309 -0
  90. data/pages/Rails.md +167 -0
  91. data/pages/Security.md +20 -0
  92. data/pages/WAB.md +13 -0
  93. metadata +126 -163
  94. data/ext/oj/hash.c +0 -163
  95. data/ext/oj/hash.h +0 -46
  96. data/ext/oj/hash_test.c +0 -512
  97. data/test/_test_active.rb +0 -76
  98. data/test/_test_active_mimic.rb +0 -96
  99. data/test/_test_mimic_rails.rb +0 -126
  100. data/test/activesupport_datetime_test.rb +0 -23
  101. data/test/bug.rb +0 -51
  102. data/test/bug2.rb +0 -10
  103. data/test/bug3.rb +0 -46
  104. data/test/bug_fast.rb +0 -32
  105. data/test/bug_load.rb +0 -24
  106. data/test/crash.rb +0 -111
  107. data/test/curl/curl_oj.rb +0 -46
  108. data/test/curl/get_oj.rb +0 -24
  109. data/test/curl/just_curl.rb +0 -31
  110. data/test/curl/just_oj.rb +0 -51
  111. data/test/example.rb +0 -11
  112. data/test/files.rb +0 -29
  113. data/test/foo.rb +0 -24
  114. data/test/helper.rb +0 -27
  115. data/test/io.rb +0 -48
  116. data/test/isolated/shared.rb +0 -310
  117. data/test/isolated/test_mimic_after.rb +0 -13
  118. data/test/isolated/test_mimic_alone.rb +0 -12
  119. data/test/isolated/test_mimic_as_json.rb +0 -45
  120. data/test/isolated/test_mimic_before.rb +0 -13
  121. data/test/isolated/test_mimic_define.rb +0 -28
  122. data/test/isolated/test_mimic_rails_after.rb +0 -22
  123. data/test/isolated/test_mimic_rails_before.rb +0 -21
  124. data/test/isolated/test_mimic_rails_datetime.rb +0 -27
  125. data/test/isolated/test_mimic_redefine.rb +0 -15
  126. data/test/mod.rb +0 -16
  127. data/test/perf.rb +0 -107
  128. data/test/perf_compat.rb +0 -128
  129. data/test/perf_fast.rb +0 -164
  130. data/test/perf_file.rb +0 -64
  131. data/test/perf_object.rb +0 -138
  132. data/test/perf_saj.rb +0 -109
  133. data/test/perf_scp.rb +0 -151
  134. data/test/perf_simple.rb +0 -287
  135. data/test/perf_strict.rb +0 -128
  136. data/test/rails.rb +0 -50
  137. data/test/russian.rb +0 -18
  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 -55
  151. data/test/sample_json.rb +0 -37
  152. data/test/struct.rb +0 -29
  153. data/test/test_compat.rb +0 -398
  154. data/test/test_debian.rb +0 -53
  155. data/test/test_fast.rb +0 -458
  156. data/test/test_file.rb +0 -245
  157. data/test/test_gc.rb +0 -49
  158. data/test/test_hash.rb +0 -29
  159. data/test/test_object.rb +0 -745
  160. data/test/test_saj.rb +0 -186
  161. data/test/test_scp.rb +0 -396
  162. data/test/test_serializer.rb +0 -59
  163. data/test/test_strict.rb +0 -254
  164. data/test/test_various.rb +0 -1383
  165. data/test/test_writer.rb +0 -308
  166. data/test/write_timebars.rb +0 -31
data/ext/oj/saj.c CHANGED
@@ -1,73 +1,47 @@
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 "mem.h"
19
+ #include "oj.h"
46
20
 
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;
21
+ typedef struct _parseInfo {
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;
58
32
  } *ParseInfo;
59
33
 
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);
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);
71
45
 
72
46
  /* This JSON parser is a single pass, destructive, callback parser. It is a
73
47
  * single pass parse since it only make one pass over the characters in the
@@ -77,131 +51,111 @@ static void skip_comment(ParseInfo pi);
77
51
  * a SAX parser because it uses callback when document elements are
78
52
  * encountered.
79
53
  *
80
- * Parsing is very tolerant. Lack of headers and even mispelled element
54
+ * Parsing is very tolerant. Lack of headers and even misspelled element
81
55
  * endings are passed over without raising an error. A best attempt is made in
82
56
  * all cases to parse the string.
83
57
  */
84
58
 
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;
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;
91
64
 
92
65
  for (; pi->str < s && '\n' != *s; s--) {
93
- col++;
66
+ col++;
94
67
  }
95
68
  for (; pi->str < s; s--) {
96
- if ('\n' == *s) {
97
- jline++;
98
- }
69
+ if ('\n' == *s) {
70
+ jline++;
71
+ }
99
72
  }
100
73
  sprintf(buf, "%s at line %d, column %d [%s:%d]", msg, jline, col, file, line);
101
74
  rb_funcall(pi->handler, oj_error_id, 3, rb_str_new2(buf), LONG2NUM(jline), LONG2NUM(col));
102
75
  }
103
76
 
104
- inline static void
105
- next_non_white(ParseInfo pi) {
77
+ inline static void next_non_white(ParseInfo pi) {
106
78
  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
- }
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
+ }
120
88
  }
121
89
  }
122
90
 
123
- inline static void
124
- call_add_value(VALUE handler, VALUE value, const char *key) {
125
- volatile VALUE k;
91
+ inline static void call_add_value(VALUE handler, VALUE value, const char *key) {
92
+ volatile VALUE k;
126
93
 
127
94
  if (0 == key) {
128
- k = Qnil;
95
+ k = Qnil;
129
96
  } else {
130
- k = rb_str_new2(key);
131
- k = oj_encode(k);
97
+ k = rb_utf8_str_new_cstr(key);
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_utf8_str_new_cstr(key);
145
109
  }
146
110
  rb_funcall(handler, method, 1, k);
147
111
  }
148
112
 
149
- static void
150
- skip_comment(ParseInfo pi) {
113
+ static void skip_comment(ParseInfo pi) {
151
114
  pi->s++; /* skip first / */
152
115
  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
- }
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
+ }
166
129
  } 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
- }
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
+ }
178
139
  } 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
- }
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
+ }
184
145
  }
185
146
  }
186
147
 
187
- static void
188
- read_next(ParseInfo pi, const char *key) {
189
- VALUE obj;
148
+ static void read_next(ParseInfo pi, const char *key) {
149
+ VALUE obj;
190
150
 
191
- if ((void*)&obj < pi->stack_min) {
192
- 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");
193
153
  }
194
- next_non_white(pi); /* skip white space */
154
+ next_non_white(pi); /* skip white space */
195
155
  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;
156
+ case '{': read_hash(pi, key); break;
157
+ case '[': read_array(pi, key); break;
158
+ case '"': read_str(pi, key); break;
205
159
  case '+':
206
160
  case '-':
207
161
  case '0':
@@ -213,113 +167,97 @@ read_next(ParseInfo pi, const char *key) {
213
167
  case '6':
214
168
  case '7':
215
169
  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;
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;
235
177
  }
236
178
  }
237
179
 
238
- static void
239
- read_hash(ParseInfo pi, const char *key) {
240
- const char *ks;
241
-
180
+ static void read_hash(ParseInfo pi, const char *key) {
181
+ const char *ks;
182
+
242
183
  if (pi->has_hash_start) {
243
- call_no_value(pi->handler, oj_hash_start_id, key);
184
+ call_no_value(pi->handler, oj_hash_start_id, key);
244
185
  }
245
186
  pi->s++;
246
187
  next_non_white(pi);
247
188
  if ('}' == *pi->s) {
248
- pi->s++;
189
+ pi->s++;
249
190
  } 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
- }
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
+ }
276
217
  }
277
218
  if (pi->has_hash_end) {
278
- call_no_value(pi->handler, oj_hash_end_id, key);
219
+ call_no_value(pi->handler, oj_hash_end_id, key);
279
220
  }
280
221
  }
281
222
 
282
- static void
283
- read_array(ParseInfo pi, const char *key) {
223
+ static void read_array(ParseInfo pi, const char *key) {
284
224
  if (pi->has_array_start) {
285
- call_no_value(pi->handler, oj_array_start_id, key);
225
+ call_no_value(pi->handler, oj_array_start_id, key);
286
226
  }
287
227
  pi->s++;
288
228
  next_non_white(pi);
289
229
  if (']' == *pi->s) {
290
- pi->s++;
230
+ pi->s++;
291
231
  } 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
- }
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
+ }
307
247
  }
308
248
  if (pi->has_array_end) {
309
- call_no_value(pi->handler, oj_array_end_id, key);
249
+ call_no_value(pi->handler, oj_array_end_id, key);
310
250
  }
311
251
  }
312
252
 
313
- static void
314
- read_str(ParseInfo pi, const char *key) {
315
- char *text;
253
+ static void read_str(ParseInfo pi, const char *key) {
254
+ char *text;
316
255
 
317
256
  text = read_quoted_value(pi);
318
257
  if (pi->has_add_value) {
319
- VALUE s = rb_str_new2(text);
258
+ VALUE s = rb_utf8_str_new_cstr(text);
320
259
 
321
- s = oj_encode(s);
322
- call_add_value(pi->handler, s, key);
260
+ call_add_value(pi->handler, s, key);
323
261
  }
324
262
  }
325
263
 
@@ -329,230 +267,224 @@ read_str(ParseInfo pi, const char *key) {
329
267
  #define NUM_MAX (FIXNUM_MAX >> 8)
330
268
  #endif
331
269
 
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;
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;
342
279
 
343
280
  if ('-' == *pi->s) {
344
- pi->s++;
345
- neg = 1;
281
+ pi->s++;
282
+ neg = 1;
346
283
  } else if ('+' == *pi->s) {
347
- pi->s++;
284
+ pi->s++;
348
285
  }
349
286
  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;
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;
367
304
  }
368
305
  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
- }
306
+ if (big) {
307
+ big++;
308
+ } else {
309
+ n = n * 10 + (*pi->s - '0');
310
+ if (NUM_MAX <= n) {
311
+ big = 1;
312
+ }
313
+ }
377
314
  }
378
315
  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
- }
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
+ }
387
324
  }
388
325
  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
- }
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
+ }
402
339
  }
403
340
  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;
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;
421
358
  } 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
- }
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
+ }
449
386
  }
450
387
  }
451
388
 
452
- static void
453
- read_true(ParseInfo pi, const char *key) {
389
+ static void read_true(ParseInfo pi, const char *key) {
454
390
  pi->s++;
455
391
  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);
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);
460
396
  }
461
397
  pi->s += 3;
462
398
  if (pi->has_add_value) {
463
- call_add_value(pi->handler, Qtrue, key);
399
+ call_add_value(pi->handler, Qtrue, key);
464
400
  }
465
401
  }
466
402
 
467
- static void
468
- read_false(ParseInfo pi, const char *key) {
403
+ static void read_false(ParseInfo pi, const char *key) {
469
404
  pi->s++;
470
405
  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);
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);
475
410
  }
476
411
  pi->s += 4;
477
412
  if (pi->has_add_value) {
478
- call_add_value(pi->handler, Qfalse, key);
413
+ call_add_value(pi->handler, Qfalse, key);
479
414
  }
480
415
  }
481
416
 
482
- static void
483
- read_nil(ParseInfo pi, const char *key) {
417
+ static void read_nil(ParseInfo pi, const char *key) {
484
418
  pi->s++;
485
419
  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);
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);
490
424
  }
491
425
  pi->s += 3;
492
426
  if (pi->has_add_value) {
493
- call_add_value(pi->handler, Qnil, key);
427
+ call_add_value(pi->handler, Qnil, key);
494
428
  }
495
429
  }
496
430
 
497
- static uint32_t
498
- read_hex(ParseInfo pi, char *h) {
499
- uint32_t b = 0;
500
- int i;
431
+ static uint32_t read_hex(ParseInfo pi, char *h) {
432
+ uint32_t b = 0;
433
+ int i;
501
434
 
502
435
  /* TBD this can be made faster with a table */
503
436
  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
- }
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
+ }
518
451
  }
519
452
  return b;
520
453
  }
521
454
 
522
- static char*
523
- unicode_to_chars(ParseInfo pi, char *t, uint32_t code) {
455
+ static char *unicode_to_chars(ParseInfo pi, char *t, uint32_t code) {
524
456
  if (0x0000007F >= code) {
525
- *t = (char)code;
457
+ *t = (char)code;
526
458
  } else if (0x000007FF >= code) {
527
- *t++ = 0xC0 | (code >> 6);
528
- *t = 0x80 | (0x3F & code);
459
+ *t++ = 0xC0 | (code >> 6);
460
+ *t = 0x80 | (0x3F & code);
529
461
  } else if (0x0000FFFF >= code) {
530
- *t++ = 0xE0 | (code >> 12);
531
- *t++ = 0x80 | ((code >> 6) & 0x3F);
532
- *t = 0x80 | (0x3F & code);
462
+ *t++ = 0xE0 | (code >> 12);
463
+ *t++ = 0x80 | ((code >> 6) & 0x3F);
464
+ *t = 0x80 | (0x3F & code);
533
465
  } 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);
466
+ *t++ = 0xF0 | (code >> 18);
467
+ *t++ = 0x80 | ((code >> 12) & 0x3F);
468
+ *t++ = 0x80 | ((code >> 6) & 0x3F);
469
+ *t = 0x80 | (0x3F & code);
538
470
  } 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);
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);
544
476
  } 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);
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);
551
483
  } else {
552
- if (pi->has_error) {
553
- call_error("invalid Unicode", pi, __FILE__, __LINE__);
554
- }
555
- 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);
556
488
  }
557
489
  return t;
558
490
  }
@@ -560,119 +492,117 @@ unicode_to_chars(ParseInfo pi, char *t, uint32_t code) {
560
492
  /* Assume the value starts immediately and goes until the quote character is
561
493
  * reached again. Do not read the character after the terminating quote.
562
494
  */
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 */
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 */
571
502
  t++;
572
503
  value = h;
573
504
  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 */
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 */
625
556
  pi->s = h + 1;
626
557
 
627
558
  return value;
628
559
  }
629
560
 
630
- static void
631
- saj_parse(VALUE handler, char *json) {
632
- volatile VALUE obj = Qnil;
633
- struct _ParseInfo pi;
561
+ static void saj_parse(VALUE handler, char *json) {
562
+ volatile VALUE obj = Qnil;
563
+ struct _parseInfo pi;
634
564
 
635
565
  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);
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);
640
570
  }
641
571
  /* skip UTF-8 BOM if present */
642
572
  if (0xEF == (uint8_t)*json && 0xBB == (uint8_t)json[1] && 0xBF == (uint8_t)json[2]) {
643
- json += 3;
573
+ json += 3;
644
574
  }
645
575
  /* initialize parse info */
646
576
  pi.str = json;
647
- pi.s = json;
648
- #if IS_WINDOWS
649
- 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 */
650
580
  #else
651
581
  {
652
- struct rlimit lim;
582
+ struct rlimit lim;
653
583
 
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
- }
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
+ }
659
589
  }
660
590
  #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);
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);
664
594
  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);
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);
668
598
  read_next(&pi, 0);
669
599
  next_non_white(&pi);
670
600
  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
- }
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
+ }
676
606
  }
677
607
  }
678
608
 
@@ -682,54 +612,58 @@ saj_parse(VALUE handler, char *json) {
682
612
  * if the JSON is malformed.
683
613
  * @param [Oj::Saj] handler Saj (responds to Oj::Saj methods) like handler
684
614
  * @param [IO|String] io IO Object to read from
615
+ * @deprecated The sc_parse() method along with the ScHandler is the preferred
616
+ * callback parser. It is slightly faster and handles streams while the
617
+ * saj_parse() method requires a complete read before parsing.
618
+ * @see sc_parse
685
619
  */
686
620
  VALUE
687
621
  oj_saj_parse(int argc, VALUE *argv, VALUE self) {
688
- char *json = 0;
689
- size_t len = 0;
690
- VALUE input = argv[1];
622
+ char *json = 0;
623
+ size_t len = 0;
624
+ VALUE input = argv[1];
691
625
 
692
626
  if (argc < 2) {
693
- 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");
694
628
  }
695
629
  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));
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));
700
634
  } 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));
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));
709
643
  #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';
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';
721
655
  #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
- }
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
+ }
730
664
  }
731
665
  saj_parse(*argv, json);
732
- xfree(json);
666
+ OJ_R_FREE(json);
733
667
 
734
668
  return Qnil;
735
669
  }