oj 1.3.7 → 1.4.0
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 +2 -8
- data/ext/oj/fast.c +6 -5
- data/ext/oj/oj.c +30 -27
- data/lib/oj.rb +1 -0
- data/lib/oj/error.rb +23 -0
- data/lib/oj/version.rb +1 -1
- metadata +3 -2
data/README.md
CHANGED
@@ -32,15 +32,9 @@ A fast JSON parser and Object marshaller as a Ruby gem.
|
|
32
32
|
|
33
33
|
## <a name="release">Release Notes</a>
|
34
34
|
|
35
|
-
### Release 1.
|
35
|
+
### Release 1.4.0
|
36
36
|
|
37
|
-
-
|
38
|
-
|
39
|
-
### Release 1.3.6
|
40
|
-
|
41
|
-
- Oj.load() now raises a SystemStackError if a JSON is too deeply nested. The loading is allowed to use on 75% of the stack.
|
42
|
-
|
43
|
-
- Oj::Doc.open() now raises a SystemStackError if a JSON is too deeply nested. The loading is allowed to use on 75% of the stack. Oj::Doc.open will allow much deeper nesting than Oj.load().
|
37
|
+
- Parse errors now raise an Exception that inherites form Oj::Error which inherits from StandardError. Some other Exceptions were changed as well to make it easier to rescue errors.
|
44
38
|
|
45
39
|
## <a name="description">Description</a>
|
46
40
|
|
data/ext/oj/fast.c
CHANGED
@@ -276,7 +276,7 @@ leaf_value(Doc doc, Leaf leaf) {
|
|
276
276
|
return leaf_hash_value(doc, leaf);
|
277
277
|
break;
|
278
278
|
default:
|
279
|
-
rb_raise(
|
279
|
+
rb_raise(rb_const_get_at(Oj, rb_intern("Error")), "Unexpected type %02x.", leaf->type);
|
280
280
|
break;
|
281
281
|
}
|
282
282
|
}
|
@@ -901,7 +901,7 @@ get_leaf(Leaf *stack, Leaf *lp, const char *path) {
|
|
901
901
|
Leaf leaf = *lp;
|
902
902
|
|
903
903
|
if (MAX_STACK <= lp - stack) {
|
904
|
-
rb_raise(
|
904
|
+
rb_raise(rb_const_get_at(Oj, rb_intern("DepthError")), "Path too deep. Limit is %d levels.", MAX_STACK);
|
905
905
|
}
|
906
906
|
if ('\0' != *path) {
|
907
907
|
if ('.' == *path && '.' == *(path + 1)) {
|
@@ -988,7 +988,7 @@ each_leaf(Doc doc, VALUE self) {
|
|
988
988
|
static int
|
989
989
|
move_step(Doc doc, const char *path, int loc) {
|
990
990
|
if (MAX_STACK <= doc->where - doc->where_path) {
|
991
|
-
rb_raise(
|
991
|
+
rb_raise(rb_const_get_at(Oj, rb_intern("DepthError")), "Path too deep. Limit is %d levels.", MAX_STACK);
|
992
992
|
}
|
993
993
|
if ('\0' == *path) {
|
994
994
|
loc = 0;
|
@@ -1167,7 +1167,7 @@ doc_open_file(VALUE clas, VALUE filename) {
|
|
1167
1167
|
Check_Type(filename, T_STRING);
|
1168
1168
|
path = StringValuePtr(filename);
|
1169
1169
|
if (0 == (f = fopen(path, "r"))) {
|
1170
|
-
rb_raise(rb_eIOError, "%s
|
1170
|
+
rb_raise(rb_eIOError, "%s", strerror(errno));
|
1171
1171
|
}
|
1172
1172
|
fseek(f, 0, SEEK_END);
|
1173
1173
|
len = ftell(f);
|
@@ -1180,7 +1180,8 @@ doc_open_file(VALUE clas, VALUE filename) {
|
|
1180
1180
|
fseek(f, 0, SEEK_SET);
|
1181
1181
|
if (len != fread(json, 1, len, f)) {
|
1182
1182
|
fclose(f);
|
1183
|
-
rb_raise(
|
1183
|
+
rb_raise(rb_const_get_at(Oj, rb_intern("LoadError")),
|
1184
|
+
"Failed to read %lu bytes from %s.", (unsigned long)len, path);
|
1184
1185
|
}
|
1185
1186
|
fclose(f);
|
1186
1187
|
json[len] = '\0';
|
data/ext/oj/oj.c
CHANGED
@@ -67,6 +67,7 @@ ID oj_utc_offset_id;
|
|
67
67
|
ID oj_write_id;
|
68
68
|
|
69
69
|
VALUE oj_bag_class;
|
70
|
+
VALUE oj_parse_error_class;
|
70
71
|
VALUE oj_bigdecimal_class;
|
71
72
|
VALUE oj_stringio_class;
|
72
73
|
VALUE oj_struct_class;
|
@@ -249,7 +250,7 @@ set_def_opts(VALUE self, VALUE opts) {
|
|
249
250
|
} else if (null_sym == v) {
|
250
251
|
oj_default_options.mode = NullMode;
|
251
252
|
} else {
|
252
|
-
rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, or :null
|
253
|
+
rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, or :null.");
|
253
254
|
}
|
254
255
|
|
255
256
|
v = rb_hash_lookup(opts, time_format_sym);
|
@@ -262,7 +263,7 @@ set_def_opts(VALUE self, VALUE opts) {
|
|
262
263
|
} else if (ruby_sym == v) {
|
263
264
|
oj_default_options.time_format = RubyTime;
|
264
265
|
} else {
|
265
|
-
rb_raise(rb_eArgError, ":time_format must be :unix, :xmlschema, or :ruby
|
266
|
+
rb_raise(rb_eArgError, ":time_format must be :unix, :xmlschema, or :ruby.");
|
266
267
|
}
|
267
268
|
|
268
269
|
if (Qtrue == rb_funcall(opts, rb_intern("has_key?"), 1, create_id_sym)) {
|
@@ -291,7 +292,7 @@ set_def_opts(VALUE self, VALUE opts) {
|
|
291
292
|
} else if (Qfalse == v) {
|
292
293
|
*o->attr = No;
|
293
294
|
} else {
|
294
|
-
rb_raise(rb_eArgError, "%s must be true, false, or nil
|
295
|
+
rb_raise(rb_eArgError, "%s must be true, false, or nil.", rb_id2name(SYM2ID(o->sym)));
|
295
296
|
}
|
296
297
|
}
|
297
298
|
}
|
@@ -314,7 +315,7 @@ parse_options(VALUE ropts, Options copts) {
|
|
314
315
|
|
315
316
|
if (Qnil != (v = rb_hash_lookup(ropts, indent_sym))) {
|
316
317
|
if (rb_cFixnum != rb_obj_class(v)) {
|
317
|
-
rb_raise(rb_eArgError, ":indent must be a Fixnum
|
318
|
+
rb_raise(rb_eArgError, ":indent must be a Fixnum.");
|
318
319
|
}
|
319
320
|
copts->indent = NUM2INT(v);
|
320
321
|
}
|
@@ -328,7 +329,7 @@ parse_options(VALUE ropts, Options copts) {
|
|
328
329
|
} else if (null_sym == v) {
|
329
330
|
copts->mode = NullMode;
|
330
331
|
} else {
|
331
|
-
rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, or :null
|
332
|
+
rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, or :null.");
|
332
333
|
}
|
333
334
|
}
|
334
335
|
if (Qnil != (v = rb_hash_lookup(ropts, time_format_sym))) {
|
@@ -339,7 +340,7 @@ parse_options(VALUE ropts, Options copts) {
|
|
339
340
|
} else if (ruby_sym == v) {
|
340
341
|
copts->time_format = RubyTime;
|
341
342
|
} else {
|
342
|
-
rb_raise(rb_eArgError, ":time_format must be :unix, :xmlschema, or :ruby
|
343
|
+
rb_raise(rb_eArgError, ":time_format must be :unix, :xmlschema, or :ruby.");
|
343
344
|
}
|
344
345
|
}
|
345
346
|
for (o = ynos; 0 != o->attr; o++) {
|
@@ -349,7 +350,7 @@ parse_options(VALUE ropts, Options copts) {
|
|
349
350
|
} else if (Qfalse == v) {
|
350
351
|
*o->attr = No;
|
351
352
|
} else {
|
352
|
-
rb_raise(rb_eArgError, "%s must be true or false
|
353
|
+
rb_raise(rb_eArgError, "%s must be true or false.", rb_id2name(SYM2ID(o->sym)));
|
353
354
|
}
|
354
355
|
}
|
355
356
|
}
|
@@ -398,7 +399,7 @@ load_with_opts(VALUE input, Options copts) {
|
|
398
399
|
json = ALLOCA_N(char, len + 1);
|
399
400
|
}
|
400
401
|
if (0 >= (cnt = read(fd, json, len)) || cnt != (ssize_t)len) {
|
401
|
-
rb_raise(rb_eIOError, "failed to read from IO Object
|
402
|
+
rb_raise(rb_eIOError, "failed to read from IO Object.");
|
402
403
|
}
|
403
404
|
json[len] = '\0';
|
404
405
|
#endif
|
@@ -412,7 +413,7 @@ load_with_opts(VALUE input, Options copts) {
|
|
412
413
|
}
|
413
414
|
strcpy(json, StringValuePtr(s));
|
414
415
|
} else {
|
415
|
-
rb_raise(rb_eArgError, "load() expected a String or IO Object
|
416
|
+
rb_raise(rb_eArgError, "load() expected a String or IO Object.");
|
416
417
|
}
|
417
418
|
}
|
418
419
|
obj = oj_parse(json, copts);
|
@@ -435,7 +436,7 @@ load(int argc, VALUE *argv, VALUE self) {
|
|
435
436
|
struct _Options options = oj_default_options;
|
436
437
|
|
437
438
|
if (1 > argc) {
|
438
|
-
rb_raise(rb_eArgError, "Wrong number of arguments to load()
|
439
|
+
rb_raise(rb_eArgError, "Wrong number of arguments to load().");
|
439
440
|
}
|
440
441
|
if (2 <= argc) {
|
441
442
|
parse_options(argv[1], &options);
|
@@ -466,7 +467,7 @@ load_file(int argc, VALUE *argv, VALUE self) {
|
|
466
467
|
Check_Type(*argv, T_STRING);
|
467
468
|
path = StringValuePtr(*argv);
|
468
469
|
if (0 == (f = fopen(path, "r"))) {
|
469
|
-
rb_raise(rb_eIOError, "%s
|
470
|
+
rb_raise(rb_eIOError, "%s", strerror(errno));
|
470
471
|
}
|
471
472
|
fseek(f, 0, SEEK_END);
|
472
473
|
len = ftell(f);
|
@@ -478,7 +479,7 @@ load_file(int argc, VALUE *argv, VALUE self) {
|
|
478
479
|
fseek(f, 0, SEEK_SET);
|
479
480
|
if (len != fread(json, 1, len, f)) {
|
480
481
|
fclose(f);
|
481
|
-
rb_raise(
|
482
|
+
rb_raise(rb_const_get_at(Oj, rb_intern("LoadError")), "Failed to read %ld bytes from %s.", len, path);
|
482
483
|
}
|
483
484
|
fclose(f);
|
484
485
|
json[len] = '\0';
|
@@ -508,7 +509,7 @@ dump(int argc, VALUE *argv, VALUE self) {
|
|
508
509
|
parse_options(argv[1], &copts);
|
509
510
|
}
|
510
511
|
if (0 == (json = oj_write_obj_to_str(*argv, &copts))) {
|
511
|
-
rb_raise(rb_eNoMemError, "Not enough memory
|
512
|
+
rb_raise(rb_eNoMemError, "Not enough memory.");
|
512
513
|
}
|
513
514
|
rstr = rb_str_new2(json);
|
514
515
|
#if HAS_ENCODING_SUPPORT
|
@@ -551,7 +552,7 @@ mimic_dump(int argc, VALUE *argv, VALUE self) {
|
|
551
552
|
VALUE rstr;
|
552
553
|
|
553
554
|
if (0 == (json = oj_write_obj_to_str(*argv, &copts))) {
|
554
|
-
rb_raise(rb_eNoMemError, "Not enough memory
|
555
|
+
rb_raise(rb_eNoMemError, "Not enough memory.");
|
555
556
|
}
|
556
557
|
rstr = rb_str_new2(json);
|
557
558
|
#if HAS_ENCODING_SUPPORT
|
@@ -601,7 +602,7 @@ mimic_walk(VALUE key, VALUE obj, VALUE proc) {
|
|
601
602
|
*args = obj;
|
602
603
|
rb_proc_call_with_block(proc, 1, args, Qnil);
|
603
604
|
#else
|
604
|
-
rb_raise(rb_eNotImpError, "Calling a Proc with a block not supported in this version. Use func() {|x| } syntax instead
|
605
|
+
rb_raise(rb_eNotImpError, "Calling a Proc with a block not supported in this version. Use func() {|x| } syntax instead.");
|
605
606
|
#endif
|
606
607
|
}
|
607
608
|
return ST_CONTINUE;
|
@@ -623,7 +624,7 @@ mimic_load(int argc, VALUE *argv, VALUE self) {
|
|
623
624
|
static VALUE
|
624
625
|
mimic_dump_load(int argc, VALUE *argv, VALUE self) {
|
625
626
|
if (1 > argc) {
|
626
|
-
rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)
|
627
|
+
rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
|
627
628
|
} else if (T_STRING == rb_type(*argv)) {
|
628
629
|
return mimic_load(argc, argv, self);
|
629
630
|
} else {
|
@@ -644,7 +645,7 @@ mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
|
644
645
|
|
645
646
|
memset(&dump_opts, 0, sizeof(dump_opts)); // may not be needed
|
646
647
|
if (T_HASH != rb_type(ropts)) {
|
647
|
-
rb_raise(rb_eArgError, "options must be a hash
|
648
|
+
rb_raise(rb_eArgError, "options must be a hash.");
|
648
649
|
}
|
649
650
|
if (Qnil != (v = rb_hash_lookup(ropts, indent_sym))) {
|
650
651
|
rb_check_type(v, T_STRING);
|
@@ -690,7 +691,7 @@ mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
|
690
691
|
// :max_nesting is always set to 100
|
691
692
|
}
|
692
693
|
if (0 == (json = oj_write_obj_to_str(*argv, copts))) {
|
693
|
-
rb_raise(rb_eNoMemError, "Not enough memory
|
694
|
+
rb_raise(rb_eNoMemError, "Not enough memory.");
|
694
695
|
}
|
695
696
|
rstr = rb_str_new2(json);
|
696
697
|
#if HAS_ENCODING_SUPPORT
|
@@ -733,14 +734,14 @@ mimic_parse(int argc, VALUE *argv, VALUE self) {
|
|
733
734
|
struct _Options options = oj_default_options;
|
734
735
|
|
735
736
|
if (1 > argc) {
|
736
|
-
rb_raise(rb_eArgError, "Wrong number of arguments to parse()
|
737
|
+
rb_raise(rb_eArgError, "Wrong number of arguments to parse().");
|
737
738
|
}
|
738
739
|
if (2 <= argc && Qnil != argv[1]) {
|
739
740
|
VALUE ropts = argv[1];
|
740
741
|
VALUE v;
|
741
742
|
|
742
743
|
if (T_HASH != rb_type(ropts)) {
|
743
|
-
rb_raise(rb_eArgError, "options must be a hash
|
744
|
+
rb_raise(rb_eArgError, "options must be a hash.");
|
744
745
|
}
|
745
746
|
if (Qnil != (v = rb_hash_lookup(ropts, symbolize_names_sym))) {
|
746
747
|
options.sym_key = (Qtrue == v) ? Yes : No;
|
@@ -804,7 +805,8 @@ define_mimic_json(VALUE self) {
|
|
804
805
|
VALUE dummy;
|
805
806
|
|
806
807
|
if (rb_const_defined_at(rb_cObject, rb_intern("JSON"))) {
|
807
|
-
rb_raise(
|
808
|
+
rb_raise(rb_const_get_at(Oj, rb_intern("MimicError")),
|
809
|
+
"JSON module already exists. Can not mimic. Do not require 'json' before calling mimic_JSON.");
|
808
810
|
}
|
809
811
|
mimic = rb_define_module("JSON");
|
810
812
|
ext = rb_define_module_under(mimic, "Ext");
|
@@ -884,6 +886,7 @@ void Init_oj() {
|
|
884
886
|
oj_write_id = rb_intern("write");
|
885
887
|
|
886
888
|
oj_bag_class = rb_const_get_at(Oj, rb_intern("Bag"));
|
889
|
+
oj_parse_error_class = rb_const_get_at(Oj, rb_intern("ParseError"));
|
887
890
|
oj_struct_class = rb_const_get(rb_cObject, rb_intern("Struct"));
|
888
891
|
oj_time_class = rb_const_get(rb_cObject, rb_intern("Time"));
|
889
892
|
oj_bigdecimal_class = rb_const_get(rb_cObject, rb_intern("BigDecimal"));
|
@@ -965,19 +968,19 @@ void Init_oj() {
|
|
965
968
|
}
|
966
969
|
|
967
970
|
void
|
968
|
-
_oj_raise_error(const char *msg, const char *
|
969
|
-
int
|
971
|
+
_oj_raise_error(const char *msg, const char *json, const char *current, const char* file, int line) {
|
972
|
+
int jline = 1;
|
970
973
|
int col = 1;
|
971
974
|
|
972
|
-
for (;
|
975
|
+
for (; json < current && '\n' != *current; current--) {
|
973
976
|
col++;
|
974
977
|
}
|
975
|
-
for (;
|
978
|
+
for (; json < current; current--) {
|
976
979
|
if ('\n' == *current) {
|
977
|
-
|
980
|
+
jline++;
|
978
981
|
}
|
979
982
|
}
|
980
|
-
rb_raise(
|
983
|
+
rb_raise(oj_parse_error_class, "%s at line %d, column %d [%s:%d]", msg, jline, col, file, line);
|
981
984
|
}
|
982
985
|
|
983
986
|
// mimic JSON documentation
|
data/lib/oj.rb
CHANGED
data/lib/oj/error.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
module Oj
|
3
|
+
|
4
|
+
class Error < StandardError
|
5
|
+
end # Error
|
6
|
+
|
7
|
+
# An Exception that is raised as a result of a parse error while parsing a JSON document.
|
8
|
+
class ParseError < Error
|
9
|
+
end # ParseError
|
10
|
+
|
11
|
+
# An Exception that is raised as a result of a path being too deep.
|
12
|
+
class DepthError < Error
|
13
|
+
end # DepthError
|
14
|
+
|
15
|
+
# An Exception that is raised if a file fails to load.
|
16
|
+
class LoadError < Error
|
17
|
+
end # LoadError
|
18
|
+
|
19
|
+
# An Exception that is raised if there is a conflict with mimicing JSON
|
20
|
+
class MimicError < Error
|
21
|
+
end # MimicError
|
22
|
+
|
23
|
+
end # Oj
|
data/lib/oj/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oj
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-10-
|
12
|
+
date: 2012-10-11 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: ! 'The fastest JSON parser and object serializer. '
|
15
15
|
email: peter@ohler.com
|
@@ -20,6 +20,7 @@ extra_rdoc_files:
|
|
20
20
|
- README.md
|
21
21
|
files:
|
22
22
|
- lib/oj/bag.rb
|
23
|
+
- lib/oj/error.rb
|
23
24
|
- lib/oj/mimic.rb
|
24
25
|
- lib/oj/version.rb
|
25
26
|
- lib/oj.rb
|