oj 1.2.9 → 1.2.10
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of oj might be problematic. Click here for more details.
- data/README.md +20 -6
- data/ext/oj/dump.c +121 -19
- data/ext/oj/extconf.rb +1 -0
- data/ext/oj/load.c +74 -17
- data/ext/oj/oj.c +76 -4
- data/ext/oj/oj.h +19 -1
- data/lib/oj/version.rb +1 -1
- data/test/boo.rb +26 -0
- data/test/bug.rb +18 -0
- data/test/{perf2.rb → foo.rb} +12 -30
- data/test/tests.rb +122 -2
- data/test/where.rb +54 -0
- metadata +25 -30
- data/test/perf1.rb +0 -64
- data/test/perf_obj_old.rb +0 -213
data/README.md
CHANGED
@@ -24,9 +24,17 @@ A fast JSON parser and Object marshaller as a Ruby gem.
|
|
24
24
|
|
25
25
|
## <a name="release">Release Notes</a>
|
26
26
|
|
27
|
-
### Release 1.2.
|
27
|
+
### Release 1.2.10
|
28
28
|
|
29
|
-
-
|
29
|
+
- Added check for circular on loading of circular dumped JSON.
|
30
|
+
|
31
|
+
- Added support for direct serialization of BigDecimal, Rational, Date, and DateTime.
|
32
|
+
|
33
|
+
- Added json.rb to $" in mimic mode to avoid pulling in the real JSON by accident.
|
34
|
+
|
35
|
+
- Oj is now thread safe for all functions.
|
36
|
+
|
37
|
+
- The / (solidus) character is now placed in strings without being escaped.
|
30
38
|
|
31
39
|
## <a name="description">Description</a>
|
32
40
|
|
@@ -55,7 +63,10 @@ to_hash() is more flexible and produces more consistent output so it has a
|
|
55
63
|
preference over the to_json() method. If neither the to_json() or to_hash()
|
56
64
|
methods exist then the Oj internal Object variable encoding is used.
|
57
65
|
|
58
|
-
Oj is compatible with Ruby 1.8.7, 1.9.2, 1.9.3, JRuby, RBX, and the latest
|
66
|
+
Oj is compatible with Ruby 1.8.7, 1.9.2, 1.9.3, JRuby, RBX, and the latest
|
67
|
+
2.0dev. Note that JRuby now disables support for extentions by default. JRuby
|
68
|
+
can be build with extensions enabled. Check the documenation for JRuby
|
69
|
+
installs in your environment.
|
59
70
|
|
60
71
|
Oj is also compatible with Rails. Just make sure the Oj gem is installed and
|
61
72
|
[multi_json](https://github.com/intridea/multi_json) will pick it up and use it.
|
@@ -352,13 +363,16 @@ excaping the first character so that it appears as `\u005e` or `\u003a` instead
|
|
352
363
|
class. The sequence `{"^c":"Oj::Bag"}` is read as the Oj::Bag class.
|
353
364
|
|
354
365
|
6. A `"^t"` JSON Object key indicates the value should be converted to a Ruby
|
355
|
-
Time. The sequence `{"^t":1325775487.000000}` is read as Jan 5, 2012 at
|
366
|
+
Time. The sequence `{"^t":1325775487.000000}` is read as Jan 5, 2012 at
|
367
|
+
23:58:07.
|
356
368
|
|
357
|
-
|
369
|
+
7. A `"^o"` JSON Object key indicates the value should be converted to a Ruby
|
358
370
|
Object. The first entry in the JSON Object must be a class with the `"^o"`
|
359
371
|
key. After that each entry is treated as a variable of the Object where the
|
360
372
|
key is the variable name without the preceeding `@`. An example is
|
361
|
-
`{"^o":"Oj::Bag","x":58,"y":"marbles"}`.
|
373
|
+
`{"^o":"Oj::Bag","x":58,"y":"marbles"}`. `"^O"` is the same except that it is
|
374
|
+
for built in or odd classes that don't obey the normal Ruby rules. Examples
|
375
|
+
are Rational, Date, and DateTime.
|
362
376
|
|
363
377
|
8. A `"^u"` JSON Object key indicates the value should be converted to a Ruby
|
364
378
|
Struct. The first entry in the JSON Object must be a class with the `"^u"`
|
data/ext/oj/dump.c
CHANGED
@@ -67,6 +67,7 @@ static void dump_false(Out out);
|
|
67
67
|
static void dump_fixnum(VALUE obj, Out out);
|
68
68
|
static void dump_bignum(VALUE obj, Out out);
|
69
69
|
static void dump_float(VALUE obj, Out out);
|
70
|
+
static void dump_raw(const char *str, size_t cnt, Out out);
|
70
71
|
static void dump_cstr(const char *str, size_t cnt, int is_sym, int escape1, Out out);
|
71
72
|
static void dump_hex(u_char c, Out out);
|
72
73
|
static void dump_str_comp(VALUE obj, Out out);
|
@@ -82,7 +83,7 @@ static int hash_cb_object(VALUE key, VALUE value, Out out);
|
|
82
83
|
static void dump_hash(VALUE obj, int depth, int mode, Out out);
|
83
84
|
static void dump_time(VALUE obj, Out out);
|
84
85
|
static void dump_data_comp(VALUE obj, Out out);
|
85
|
-
static void dump_data_obj(VALUE obj, Out out);
|
86
|
+
static void dump_data_obj(VALUE obj, int depth, Out out);
|
86
87
|
static void dump_obj_comp(VALUE obj, int depth, Out out);
|
87
88
|
static void dump_obj_obj(VALUE obj, int depth, Out out);
|
88
89
|
#if HAS_RSTRUCT
|
@@ -92,7 +93,8 @@ static void dump_struct_obj(VALUE obj, int depth, Out out);
|
|
92
93
|
#if HAS_IVAR_HELPERS
|
93
94
|
static int dump_attr_cb(ID key, VALUE value, Out out);
|
94
95
|
#endif
|
95
|
-
static void dump_obj_attrs(VALUE obj,
|
96
|
+
static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out);
|
97
|
+
static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out);
|
96
98
|
|
97
99
|
static void grow(Out out, size_t len);
|
98
100
|
static size_t hibit_friendly_size(const u_char *str, size_t len);
|
@@ -111,7 +113,7 @@ static const char hex_chars[17] = "0123456789abcdef";
|
|
111
113
|
|
112
114
|
static char hibit_friendly_chars[256] = "\
|
113
115
|
66666666222622666666666666666666\
|
114
|
-
|
116
|
+
11211111111111111111111111111111\
|
115
117
|
11111111111111111111111111112111\
|
116
118
|
11111111111111111111111111111111\
|
117
119
|
11111111111111111111111111111111\
|
@@ -223,6 +225,16 @@ dump_hex(u_char c, Out out) {
|
|
223
225
|
*out->cur++ = hex_chars[d];
|
224
226
|
}
|
225
227
|
|
228
|
+
static void
|
229
|
+
dump_raw(const char *str, size_t cnt, Out out) {
|
230
|
+
if (out->end - out->cur <= (long)cnt + 10) {
|
231
|
+
grow(out, cnt + 10);
|
232
|
+
}
|
233
|
+
memcpy(out->cur, str, cnt);
|
234
|
+
out->cur += cnt;
|
235
|
+
*out->cur = '\0';
|
236
|
+
}
|
237
|
+
|
226
238
|
const char*
|
227
239
|
dump_unicode(const char *str, const char *end, Out out) {
|
228
240
|
uint32_t code = 0;
|
@@ -635,6 +647,7 @@ dump_array(VALUE a, int depth, Out out) {
|
|
635
647
|
}
|
636
648
|
if (0 < out->opts->dump_opts->indent_size) {
|
637
649
|
int i;
|
650
|
+
|
638
651
|
for (i = depth; 0 < i; i--) {
|
639
652
|
strcpy(out->cur, out->opts->dump_opts->indent);
|
640
653
|
out->cur += out->opts->dump_opts->indent_size;
|
@@ -934,18 +947,27 @@ dump_time(VALUE obj, Out out) {
|
|
934
947
|
|
935
948
|
static void
|
936
949
|
dump_data_comp(VALUE obj, Out out) {
|
937
|
-
VALUE
|
950
|
+
VALUE clas = rb_obj_class(obj);
|
938
951
|
|
939
952
|
if (rb_cTime == clas) {
|
940
953
|
dump_time(obj, out);
|
941
954
|
} else {
|
942
|
-
|
955
|
+
VALUE rstr;
|
956
|
+
|
957
|
+
if (oj_bigdecimal_class == clas) {
|
958
|
+
//rstr = rb_funcall(obj, oj_to_s_id, 1, rb_intern("E"));
|
959
|
+
rstr = rb_funcall(obj, oj_to_s_id, 0);
|
960
|
+
dump_raw(StringValuePtr(rstr), RSTRING_LEN(rstr), out);
|
961
|
+
} else {
|
962
|
+
rstr = rb_funcall(obj, oj_to_s_id, 0);
|
963
|
+
dump_cstr(StringValuePtr(rstr), RSTRING_LEN(rstr), 0, 0, out);
|
964
|
+
}
|
943
965
|
}
|
944
966
|
}
|
945
967
|
|
946
968
|
static void
|
947
|
-
dump_data_obj(VALUE obj, Out out) {
|
948
|
-
VALUE
|
969
|
+
dump_data_obj(VALUE obj, int depth, Out out) {
|
970
|
+
VALUE clas = rb_obj_class(obj);
|
949
971
|
|
950
972
|
if (rb_cTime == clas) {
|
951
973
|
if (out->end - out->cur <= 6) {
|
@@ -961,7 +983,14 @@ dump_data_obj(VALUE obj, Out out) {
|
|
961
983
|
*out->cur++ = '}';
|
962
984
|
*out->cur = '\0';
|
963
985
|
} else {
|
964
|
-
|
986
|
+
VALUE clas = rb_obj_class(obj);
|
987
|
+
Odd odd = oj_get_odd(clas);
|
988
|
+
|
989
|
+
if (0 == odd) {
|
990
|
+
dump_nil(out);
|
991
|
+
} else {
|
992
|
+
dump_odd(obj, odd, clas, depth + 1, out);
|
993
|
+
}
|
965
994
|
}
|
966
995
|
}
|
967
996
|
|
@@ -987,7 +1016,21 @@ dump_obj_comp(VALUE obj, int depth, Out out) {
|
|
987
1016
|
memcpy(out->cur, s, len);
|
988
1017
|
out->cur += len;
|
989
1018
|
} else {
|
990
|
-
|
1019
|
+
VALUE clas = rb_obj_class(obj);
|
1020
|
+
|
1021
|
+
if (oj_bigdecimal_class == clas) {
|
1022
|
+
VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
|
1023
|
+
|
1024
|
+
dump_raw(StringValuePtr(rstr), RSTRING_LEN(rstr), out);
|
1025
|
+
} else {
|
1026
|
+
Odd odd = oj_get_odd(clas);
|
1027
|
+
|
1028
|
+
if (0 == odd) {
|
1029
|
+
dump_obj_attrs(obj, 0, 0, depth, out);
|
1030
|
+
} else {
|
1031
|
+
dump_odd(obj, odd, 0, depth + 1, out);
|
1032
|
+
}
|
1033
|
+
}
|
991
1034
|
}
|
992
1035
|
*out->cur = '\0';
|
993
1036
|
}
|
@@ -997,7 +1040,14 @@ dump_obj_obj(VALUE obj, int depth, Out out) {
|
|
997
1040
|
long id = check_circular(obj, out);
|
998
1041
|
|
999
1042
|
if (0 <= id) {
|
1000
|
-
|
1043
|
+
VALUE clas = rb_obj_class(obj);
|
1044
|
+
Odd odd = oj_get_odd(clas);
|
1045
|
+
|
1046
|
+
if (0 == odd) {
|
1047
|
+
dump_obj_attrs(obj, clas, id, depth, out);
|
1048
|
+
} else {
|
1049
|
+
dump_odd(obj, odd, clas, depth + 1, out);
|
1050
|
+
}
|
1001
1051
|
}
|
1002
1052
|
}
|
1003
1053
|
|
@@ -1033,7 +1083,7 @@ dump_attr_cb(ID key, VALUE value, Out out) {
|
|
1033
1083
|
#endif
|
1034
1084
|
|
1035
1085
|
static void
|
1036
|
-
dump_obj_attrs(VALUE obj,
|
1086
|
+
dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out) {
|
1037
1087
|
size_t size;
|
1038
1088
|
int d2 = depth + 1;
|
1039
1089
|
|
@@ -1041,8 +1091,8 @@ dump_obj_attrs(VALUE obj, int with_class, slot_t id, int depth, Out out) {
|
|
1041
1091
|
grow(out, 2);
|
1042
1092
|
}
|
1043
1093
|
*out->cur++ = '{';
|
1044
|
-
if (
|
1045
|
-
const char *class_name = rb_class2name(
|
1094
|
+
if (0 != clas) {
|
1095
|
+
const char *class_name = rb_class2name(clas);
|
1046
1096
|
int clen = (int)strlen(class_name);
|
1047
1097
|
|
1048
1098
|
size = d2 * out->indent + clen + 10;
|
@@ -1085,13 +1135,15 @@ dump_obj_attrs(VALUE obj, int with_class, slot_t id, int depth, Out out) {
|
|
1085
1135
|
|
1086
1136
|
cnt = (int)RARRAY_LEN(vars);
|
1087
1137
|
#endif
|
1088
|
-
if (
|
1138
|
+
if (0 != clas && 0 < cnt) {
|
1089
1139
|
*out->cur++ = ',';
|
1090
1140
|
}
|
1091
1141
|
out->depth = depth + 1;
|
1092
1142
|
#if HAS_IVAR_HELPERS
|
1093
1143
|
rb_ivar_foreach(obj, dump_attr_cb, (VALUE)out);
|
1094
|
-
out->cur
|
1144
|
+
if (',' == *(out->cur - 1)) {
|
1145
|
+
out->cur--; // backup to overwrite last comma
|
1146
|
+
}
|
1095
1147
|
#else
|
1096
1148
|
size = d2 * out->indent + 1;
|
1097
1149
|
for (i = cnt; 0 < i; i--, np++) {
|
@@ -1197,6 +1249,56 @@ dump_struct_obj(VALUE obj, int depth, Out out) {
|
|
1197
1249
|
}
|
1198
1250
|
#endif
|
1199
1251
|
|
1252
|
+
static void
|
1253
|
+
dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
|
1254
|
+
ID *idp;
|
1255
|
+
VALUE v;
|
1256
|
+
const char *name;
|
1257
|
+
size_t size;
|
1258
|
+
int d2 = depth + 1;
|
1259
|
+
|
1260
|
+
if (out->end - out->cur <= 2) {
|
1261
|
+
grow(out, 2);
|
1262
|
+
}
|
1263
|
+
*out->cur++ = '{';
|
1264
|
+
if (0 != clas) {
|
1265
|
+
const char *class_name = rb_class2name(clas);
|
1266
|
+
int clen = (int)strlen(class_name);
|
1267
|
+
|
1268
|
+
size = d2 * out->indent + clen + 10;
|
1269
|
+
if (out->end - out->cur <= (long)size) {
|
1270
|
+
grow(out, size);
|
1271
|
+
}
|
1272
|
+
fill_indent(out, d2);
|
1273
|
+
*out->cur++ = '"';
|
1274
|
+
*out->cur++ = '^';
|
1275
|
+
*out->cur++ = 'O';
|
1276
|
+
*out->cur++ = '"';
|
1277
|
+
*out->cur++ = ':';
|
1278
|
+
dump_cstr(class_name, clen, 0, 0, out);
|
1279
|
+
*out->cur++ = ',';
|
1280
|
+
}
|
1281
|
+
size = d2 * out->indent + 1;
|
1282
|
+
for (idp = odd->attrs; 0 != *idp; idp++) {
|
1283
|
+
if (out->end - out->cur <= (long)size) {
|
1284
|
+
grow(out, size);
|
1285
|
+
}
|
1286
|
+
name = rb_id2name(*idp);
|
1287
|
+
v = rb_funcall(obj, *idp, 0);
|
1288
|
+
fill_indent(out, d2);
|
1289
|
+
dump_cstr(name, strlen(name), 0, 0, out);
|
1290
|
+
*out->cur++ = ':';
|
1291
|
+
dump_val(v, d2, out);
|
1292
|
+
if (out->end - out->cur <= 2) {
|
1293
|
+
grow(out, 2);
|
1294
|
+
}
|
1295
|
+
*out->cur++ = ',';
|
1296
|
+
}
|
1297
|
+
out->cur--;
|
1298
|
+
*out->cur++ = '}';
|
1299
|
+
*out->cur = '\0';
|
1300
|
+
}
|
1301
|
+
|
1200
1302
|
static void
|
1201
1303
|
raise_strict(VALUE obj) {
|
1202
1304
|
rb_raise(rb_eTypeError, "Failed to dump %s Object to JSON in strict mode.\n", rb_class2name(rb_obj_class(obj)));
|
@@ -1240,6 +1342,9 @@ dump_val(VALUE obj, int depth, Out out) {
|
|
1240
1342
|
default: dump_class_obj(obj, out); break;
|
1241
1343
|
}
|
1242
1344
|
break;
|
1345
|
+
#if (defined T_RATIONAL && defined RRATIONAL)
|
1346
|
+
case T_RATIONAL:
|
1347
|
+
#endif
|
1243
1348
|
case T_OBJECT:
|
1244
1349
|
switch (out->opts->mode) {
|
1245
1350
|
case StrictMode: raise_strict(obj); break;
|
@@ -1255,7 +1360,7 @@ dump_val(VALUE obj, int depth, Out out) {
|
|
1255
1360
|
case NullMode: dump_nil(out); break;
|
1256
1361
|
case CompatMode: dump_data_comp(obj, out); break;
|
1257
1362
|
case ObjectMode:
|
1258
|
-
default: dump_data_obj(obj, out); break;
|
1363
|
+
default: dump_data_obj(obj, depth, out); break;
|
1259
1364
|
}
|
1260
1365
|
break;
|
1261
1366
|
#if HAS_RSTRUCT
|
@@ -1271,9 +1376,6 @@ dump_val(VALUE obj, int depth, Out out) {
|
|
1271
1376
|
#endif
|
1272
1377
|
#if (defined T_COMPLEX && defined RCOMPLEX)
|
1273
1378
|
case T_COMPLEX:
|
1274
|
-
#endif
|
1275
|
-
#if (defined T_RATIONAL && defined RRATIONAL)
|
1276
|
-
case T_RATIONAL:
|
1277
1379
|
#endif
|
1278
1380
|
case T_REGEXP:
|
1279
1381
|
switch (out->opts->mode) {
|
data/ext/oj/extconf.rb
CHANGED
@@ -24,6 +24,7 @@ dflags = {
|
|
24
24
|
'HAS_IVAR_HELPERS' => ('ruby' == type && ('1' == version[0] && '9' == version[1]) || '2' <= version[0]) ? 1 : 0,
|
25
25
|
'HAS_PROC_WITH_BLOCK' => ('ruby' == type && ('1' == version[0] && '9' == version[1]) || '2' <= version[0]) ? 1 : 0,
|
26
26
|
'HAS_TOP_LEVEL_ST_H' => ('ree' == type || ('ruby' == type && '1' == version[0] && '8' == version[1])) ? 1 : 0,
|
27
|
+
'SAFE_CACHE' => nil,
|
27
28
|
}
|
28
29
|
# This is a monster hack to get around issues with 1.9.3-p0 on CentOS 5.4. SO
|
29
30
|
# some reason math.h and string.h contents are not processed. Might be a
|
data/ext/oj/load.c
CHANGED
@@ -28,6 +28,7 @@
|
|
28
28
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
29
|
*/
|
30
30
|
|
31
|
+
#include <pthread.h> // TBD LOCK
|
31
32
|
#include <stdlib.h>
|
32
33
|
#include <stdio.h>
|
33
34
|
#include <string.h>
|
@@ -157,6 +158,9 @@ classname2class(const char *name, ParseInfo pi) {
|
|
157
158
|
VALUE *slot;
|
158
159
|
int auto_define = (Yes == pi->options->auto_define);
|
159
160
|
|
161
|
+
#ifdef SAFE_CACHE
|
162
|
+
pthread_mutex_lock(&oj_cache_mutex);
|
163
|
+
#endif
|
160
164
|
if (Qundef == (clas = oj_cache_get(oj_class_cache, name, &slot))) {
|
161
165
|
char class_name[1024];
|
162
166
|
char *s;
|
@@ -183,6 +187,9 @@ classname2class(const char *name, ParseInfo pi) {
|
|
183
187
|
*slot = clas;
|
184
188
|
}
|
185
189
|
}
|
190
|
+
#ifdef SAFE_CACHE
|
191
|
+
pthread_mutex_unlock(&oj_cache_mutex);
|
192
|
+
#endif
|
186
193
|
return clas;
|
187
194
|
}
|
188
195
|
|
@@ -370,6 +377,9 @@ read_obj(ParseInfo pi) {
|
|
370
377
|
int obj_type = T_NONE;
|
371
378
|
const char *json_class_name = 0;
|
372
379
|
Mode mode = pi->options->mode;
|
380
|
+
Odd odd = 0;
|
381
|
+
VALUE odd_args[MAX_ODD_ARGS];
|
382
|
+
VALUE *vp;
|
373
383
|
|
374
384
|
pi->s++;
|
375
385
|
next_non_white(pi);
|
@@ -420,6 +430,16 @@ read_obj(ParseInfo pi) {
|
|
420
430
|
obj_type = T_OBJECT;
|
421
431
|
key = Qundef;
|
422
432
|
break;
|
433
|
+
case 'O': // Odd class
|
434
|
+
if (0 == (odd = oj_get_odd(read_next(pi, T_CLASS)))) {
|
435
|
+
raise_error("Not a valid build in class.", pi->str, pi->s);
|
436
|
+
}
|
437
|
+
obj = Qundef;
|
438
|
+
key = Qundef;
|
439
|
+
for (vp = odd_args + MAX_ODD_ARGS - 1; odd_args <=vp; vp--) {
|
440
|
+
*vp = Qnil;
|
441
|
+
}
|
442
|
+
break;
|
423
443
|
case 'u': // Struct
|
424
444
|
obj = read_next(pi, T_STRUCT);
|
425
445
|
obj_type = T_STRUCT;
|
@@ -435,7 +455,7 @@ read_obj(ParseInfo pi) {
|
|
435
455
|
if (Qundef == val && Qundef == (val = read_next(pi, 0))) {
|
436
456
|
raise_error("unexpected character", pi->str, pi->s);
|
437
457
|
}
|
438
|
-
if (Qundef == obj) {
|
458
|
+
if (Qundef == obj && 0 == odd) {
|
439
459
|
obj = rb_hash_new();
|
440
460
|
obj_type = T_HASH;
|
441
461
|
}
|
@@ -455,10 +475,25 @@ read_obj(ParseInfo pi) {
|
|
455
475
|
}
|
456
476
|
}
|
457
477
|
if (Qundef != key) {
|
458
|
-
if (
|
478
|
+
if (0 != odd) {
|
479
|
+
ID *idp;
|
480
|
+
|
481
|
+
for (idp = odd->attrs, vp = odd_args; 0 != *idp; idp++, vp++) {
|
482
|
+
if (0 == strcmp(rb_id2name(*idp), ks)) {
|
483
|
+
*vp = val;
|
484
|
+
break;
|
485
|
+
}
|
486
|
+
}
|
487
|
+
if (odd_args + MAX_ODD_ARGS <= vp) {
|
488
|
+
raise_error("invalid attribute", pi->str, pi->s);
|
489
|
+
}
|
490
|
+
} else if (T_OBJECT == obj_type) {
|
459
491
|
VALUE *slot;
|
460
492
|
ID var_id;
|
461
493
|
|
494
|
+
#ifdef SAFE_CACHE
|
495
|
+
pthread_mutex_lock(&oj_cache_mutex);
|
496
|
+
#endif
|
462
497
|
if (Qundef == (var_id = oj_cache_get(oj_attr_cache, ks, &slot))) {
|
463
498
|
char attr[1024];
|
464
499
|
|
@@ -472,6 +507,9 @@ read_obj(ParseInfo pi) {
|
|
472
507
|
var_id = rb_intern(attr);
|
473
508
|
*slot = var_id;
|
474
509
|
}
|
510
|
+
#ifdef SAFE_CACHE
|
511
|
+
pthread_mutex_unlock(&oj_cache_mutex);
|
512
|
+
#endif
|
475
513
|
rb_ivar_set(obj, var_id, val);
|
476
514
|
} else if (T_HASH == obj_type) {
|
477
515
|
if (Yes == pi->options->sym_key) {
|
@@ -501,7 +539,9 @@ read_obj(ParseInfo pi) {
|
|
501
539
|
raise_error("invalid format, expected , or } while in an object", pi->str, pi->s);
|
502
540
|
}
|
503
541
|
}
|
504
|
-
if (0 !=
|
542
|
+
if (0 != odd) {
|
543
|
+
obj = rb_funcall2(odd->create_obj, odd->create_op, odd->attr_cnt, odd_args);
|
544
|
+
} else if (0 != json_class_name) {
|
505
545
|
VALUE clas = classname2class(json_class_name, pi);
|
506
546
|
VALUE args[1];
|
507
547
|
|
@@ -625,7 +665,7 @@ read_str(ParseInfo pi, int hint) {
|
|
625
665
|
} else if (ObjectMode == pi->options->mode && '^' == *text && '\0' != text[2]) {
|
626
666
|
char c1 = text[1];
|
627
667
|
|
628
|
-
if ('r' == c1) {
|
668
|
+
if ('r' == c1 && 0 != pi->circ_array) {
|
629
669
|
obj = circ_array_get(pi->circ_array, read_ulong(text + 2, pi));
|
630
670
|
} else if ('i' == c1) {
|
631
671
|
obj = ULONG2NUM(read_ulong(text + 2, pi));
|
@@ -691,6 +731,9 @@ read_num(ParseInfo pi) {
|
|
691
731
|
for (; '0' <= *pi->s && *pi->s <= '9'; pi->s++) {
|
692
732
|
a = a * 10 + (*pi->s - '0');
|
693
733
|
div *= 10;
|
734
|
+
if (NUM_MAX <= div) {
|
735
|
+
big = 1;
|
736
|
+
}
|
694
737
|
}
|
695
738
|
}
|
696
739
|
if ('e' == *pi->s || 'E' == *pi->s) {
|
@@ -703,6 +746,9 @@ read_num(ParseInfo pi) {
|
|
703
746
|
}
|
704
747
|
for (; '0' <= *pi->s && *pi->s <= '9'; pi->s++) {
|
705
748
|
e = e * 10 + (*pi->s - '0');
|
749
|
+
if (NUM_MAX <= e) {
|
750
|
+
big = 1;
|
751
|
+
}
|
706
752
|
}
|
707
753
|
}
|
708
754
|
if (0 == e && 0 == a && 1 == div) {
|
@@ -721,22 +767,33 @@ read_num(ParseInfo pi) {
|
|
721
767
|
}
|
722
768
|
return LONG2NUM(n);
|
723
769
|
}
|
724
|
-
} else {
|
725
|
-
|
770
|
+
} else { // decimal
|
771
|
+
if (big) {
|
772
|
+
char c = *pi->s;
|
773
|
+
VALUE num;
|
774
|
+
|
775
|
+
*pi->s = '\0';
|
776
|
+
num = rb_funcall(oj_bigdecimal_class, oj_new_id, 1, rb_str_new2(start));
|
777
|
+
*pi->s = c;
|
726
778
|
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
if (
|
735
|
-
e
|
779
|
+
return num;
|
780
|
+
} else {
|
781
|
+
double d = (double)n + (double)a / (double)div;
|
782
|
+
|
783
|
+
if (neg) {
|
784
|
+
d = -d;
|
785
|
+
}
|
786
|
+
if (1 < big) {
|
787
|
+
e += big - 1;
|
788
|
+
}
|
789
|
+
if (0 != e) {
|
790
|
+
if (eneg) {
|
791
|
+
e = -e;
|
792
|
+
}
|
793
|
+
d *= pow(10.0, e);
|
736
794
|
}
|
737
|
-
|
795
|
+
return rb_float_new(d);
|
738
796
|
}
|
739
|
-
return rb_float_new(d);
|
740
797
|
}
|
741
798
|
}
|
742
799
|
|