oj 3.13.13 → 3.13.16

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6c59bab43c76d548574059f41aab7b1604fa74161b59bbc0e958a0919e1cdabe
4
- data.tar.gz: 8b60a10bb54b6a03f9a23b1db561a6402d1710c942f01d1f175582a08c566a9c
3
+ metadata.gz: d07b4081b5dda88146594adba591542d11106f1c1eadcf7c56e38358d0ee0af3
4
+ data.tar.gz: 6bdc82c3812f45a8ae9d72ec0b2f43ee223d95ac250399fc8dae8daf34cd3b49
5
5
  SHA512:
6
- metadata.gz: 70ea6740a38970443000f03b67a5222fd450529f6d5d8edbb613feb277ecbeb27350784de26204b962a7815b4bf9cae821cfc8753be6f23ca845d118dfa6465b
7
- data.tar.gz: 57d7f8b7f7f3d4e2ac37949e820d392840c0d3f36ff35be55c5ba0ba589a6656bf572de39c0f82482d23aa992bb3c8b9a634c106c753c077be8ef994c61c251f
6
+ metadata.gz: 4358aa15b7956a5b577163e43fbdc0512212a218124878ceedc2932483f27acabed2d2b92eb888c8e54601f4f4aaf3dce3b959a36effbea989e7e7ea8956d1c1
7
+ data.tar.gz: 1e1710bce62aadfbcc1196357d2e692892b75cc18c982fb6f53c2e35782d9bd2256cb3b6ab98951691430f23e8c2d8db26987a95dcba29f87b472729613b8d2d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 3.13.16 - 2022-07-06
4
+
5
+ - Added line and column as optional arguments to the Oj::Parser.saj parser.
6
+
7
+ ## 3.13.15 - 2022-07-03
8
+
9
+ - Fixed issue dumping NaN value in object mode.
10
+
11
+ ## 3.13.14 - 2022-06-03
12
+
13
+ - Double fclose() due to bad merger fixed by tonobo.
14
+
3
15
  ## 3.13.13 - 2022-05-20
4
16
 
5
17
  - Fixed flooding stdout with debug output when dumping.
data/ext/oj/compat.c CHANGED
@@ -54,7 +54,7 @@ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, c
54
54
  } else {
55
55
  rb_hash_aset(parent->val, rkey, rstr);
56
56
  }
57
- if (Yes == pi->options.trace) {
57
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
58
58
  oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rstr);
59
59
  }
60
60
  }
@@ -68,7 +68,7 @@ static VALUE start_hash(ParseInfo pi) {
68
68
  } else {
69
69
  h = rb_hash_new();
70
70
  }
71
- if (Yes == pi->options.trace) {
71
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
72
72
  oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
73
73
  }
74
74
  return h;
@@ -93,7 +93,7 @@ static void end_hash(struct _parseInfo *pi) {
93
93
  parent->classname = 0;
94
94
  }
95
95
  }
96
- if (Yes == pi->options.trace) {
96
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
97
97
  oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
98
98
  }
99
99
  }
@@ -110,14 +110,14 @@ static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig
110
110
  }
111
111
  }
112
112
  pi->stack.head->val = rstr;
113
- if (Yes == pi->options.trace) {
113
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
114
114
  oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, rstr);
115
115
  }
116
116
  }
117
117
 
118
118
  static void add_num(ParseInfo pi, NumInfo ni) {
119
119
  pi->stack.head->val = oj_num_as_value(ni);
120
- if (Yes == pi->options.trace) {
120
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
121
121
  oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, pi->stack.head->val);
122
122
  }
123
123
  }
@@ -138,7 +138,7 @@ static void hash_set_num(struct _parseInfo *pi, Val parent, NumInfo ni) {
138
138
  } else {
139
139
  rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), rval);
140
140
  }
141
- if (Yes == pi->options.trace) {
141
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
142
142
  oj_trace_parse_call("set_number", pi, __FILE__, __LINE__, rval);
143
143
  }
144
144
  }
@@ -157,7 +157,7 @@ static void hash_set_value(ParseInfo pi, Val parent, VALUE value) {
157
157
  } else {
158
158
  rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), value);
159
159
  }
160
- if (Yes == pi->options.trace) {
160
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
161
161
  oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
162
162
  }
163
163
  }
@@ -166,7 +166,7 @@ static VALUE start_array(ParseInfo pi) {
166
166
  if (Qnil != pi->options.array_class) {
167
167
  return rb_class_new_instance(0, NULL, pi->options.array_class);
168
168
  }
169
- if (Yes == pi->options.trace) {
169
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
170
170
  oj_trace_parse_in("start_array", pi, __FILE__, __LINE__);
171
171
  }
172
172
  return rb_ary_new();
@@ -184,7 +184,7 @@ static void array_append_num(ParseInfo pi, NumInfo ni) {
184
184
  } else {
185
185
  rb_ary_push(parent->val, rval);
186
186
  }
187
- if (Yes == pi->options.trace) {
187
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
188
188
  oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
189
189
  }
190
190
  }
@@ -201,7 +201,7 @@ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const c
201
201
  }
202
202
  }
203
203
  rb_ary_push(stack_peek(&pi->stack)->val, rstr);
204
- if (Yes == pi->options.trace) {
204
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
205
205
  oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rstr);
206
206
  }
207
207
  }
data/ext/oj/custom.c CHANGED
@@ -959,7 +959,7 @@ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, c
959
959
  break;
960
960
  default: break;
961
961
  }
962
- if (Yes == pi->options.trace) {
962
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
963
963
  oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rstr);
964
964
  }
965
965
  }
@@ -978,7 +978,7 @@ static void end_hash(struct _parseInfo *pi) {
978
978
  }
979
979
  parent->clas = Qundef;
980
980
  }
981
- if (Yes == pi->options.trace) {
981
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
982
982
  oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
983
983
  }
984
984
  }
@@ -1032,7 +1032,7 @@ static void hash_set_num(struct _parseInfo *pi, Val kval, NumInfo ni) {
1032
1032
  break;
1033
1033
  default: break;
1034
1034
  }
1035
- if (Yes == pi->options.trace) {
1035
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
1036
1036
  oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rval);
1037
1037
  }
1038
1038
  }
@@ -1045,7 +1045,7 @@ static void hash_set_value(ParseInfo pi, Val kval, VALUE value) {
1045
1045
  case T_HASH: rb_hash_aset(parent->val, oj_calc_hash_key(pi, kval), value); break;
1046
1046
  default: break;
1047
1047
  }
1048
- if (Yes == pi->options.trace) {
1048
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
1049
1049
  oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
1050
1050
  }
1051
1051
  }
@@ -1055,7 +1055,7 @@ static void array_append_num(ParseInfo pi, NumInfo ni) {
1055
1055
  volatile VALUE rval = oj_num_as_value(ni);
1056
1056
 
1057
1057
  rb_ary_push(parent->val, rval);
1058
- if (Yes == pi->options.trace) {
1058
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
1059
1059
  oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
1060
1060
  }
1061
1061
  }
@@ -1072,7 +1072,7 @@ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const c
1072
1072
  }
1073
1073
  }
1074
1074
  rb_ary_push(stack_peek(&pi->stack)->val, rstr);
1075
- if (Yes == pi->options.trace) {
1075
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
1076
1076
  oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rstr);
1077
1077
  }
1078
1078
  }
data/ext/oj/dump.c CHANGED
@@ -32,6 +32,7 @@ static const char nan_val[] = NAN_VAL;
32
32
  typedef unsigned long ulong;
33
33
 
34
34
  static size_t hibit_friendly_size(const uint8_t *str, size_t len);
35
+ static size_t slash_friendly_size(const uint8_t *str, size_t len);
35
36
  static size_t xss_friendly_size(const uint8_t *str, size_t len);
36
37
  static size_t ascii_friendly_size(const uint8_t *str, size_t len);
37
38
 
@@ -59,6 +60,17 @@ static char hibit_friendly_chars[256] = "\
59
60
  11111111111111111111111111111111\
60
61
  11111111111111111111111111111111";
61
62
 
63
+ // JSON standard but escape forward slashes `/`
64
+ static char slash_friendly_chars[256] = "\
65
+ 66666666222622666666666666666666\
66
+ 11211111111111121111111111111111\
67
+ 11111111111111111111111111112111\
68
+ 11111111111111111111111111111111\
69
+ 11111111111111111111111111111111\
70
+ 11111111111111111111111111111111\
71
+ 11111111111111111111111111111111\
72
+ 11111111111111111111111111111111";
73
+
62
74
  // High bit set characters are always encoded as unicode. Worse case is 3
63
75
  // bytes per character in the output. That makes this conservative.
64
76
  static char ascii_friendly_chars[256] = "\
@@ -143,6 +155,10 @@ inline static size_t hibit_friendly_size(const uint8_t *str, size_t len) {
143
155
  return calculate_string_size(str, len, hibit_friendly_chars);
144
156
  }
145
157
 
158
+ inline static size_t slash_friendly_size(const uint8_t *str, size_t len) {
159
+ return calculate_string_size(str, len, slash_friendly_chars);
160
+ }
161
+
146
162
  inline static size_t ascii_friendly_size(const uint8_t *str, size_t len) {
147
163
  return calculate_string_size(str, len, ascii_friendly_chars);
148
164
  }
@@ -365,7 +381,6 @@ void oj_dump_time(VALUE obj, Out out, int withZone) {
365
381
  long long sec;
366
382
  long long nsec;
367
383
 
368
- #ifdef HAVE_RB_TIME_TIMESPEC
369
384
  // rb_time_timespec as well as rb_time_timeeval have a bug that causes an
370
385
  // exception to be raised if a time is before 1970 on 32 bit systems so
371
386
  // check the timespec size and use the ruby calls if a 32 bit system.
@@ -378,10 +393,6 @@ void oj_dump_time(VALUE obj, Out out, int withZone) {
378
393
  sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
379
394
  nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
380
395
  }
381
- #else
382
- sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
383
- nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
384
- #endif
385
396
 
386
397
  *b-- = '\0';
387
398
  if (withZone) {
@@ -467,7 +478,6 @@ void oj_dump_xml_time(VALUE obj, Out out) {
467
478
  int tzhour, tzmin;
468
479
  char tzsign = '+';
469
480
 
470
- #ifdef HAVE_RB_TIME_TIMESPEC
471
481
  if (16 <= sizeof(struct timespec)) {
472
482
  struct timespec ts = rb_time_timespec(obj);
473
483
 
@@ -477,10 +487,6 @@ void oj_dump_xml_time(VALUE obj, Out out) {
477
487
  sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
478
488
  nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
479
489
  }
480
- #else
481
- sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
482
- nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
483
- #endif
484
490
 
485
491
  assure_size(out, 36);
486
492
  if (9 > out->opts->sec_prec) {
@@ -614,7 +620,6 @@ void oj_write_obj_to_file(VALUE obj, const char *path, Options copts) {
614
620
 
615
621
  oj_out_free(&out);
616
622
 
617
- fclose(f);
618
623
  if (!ok) {
619
624
  int err = ferror(f);
620
625
  fclose(f);
@@ -757,6 +762,11 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
757
762
  cmap = ascii_friendly_chars;
758
763
  size = ascii_friendly_size((uint8_t *)str, cnt);
759
764
  break;
765
+ case SlashEsc:
766
+ has_hi = true;
767
+ cmap = slash_friendly_chars;
768
+ size = slash_friendly_size((uint8_t *)str, cnt);
769
+ break;
760
770
  case XSSEsc:
761
771
  cmap = xss_friendly_chars;
762
772
  size = xss_friendly_size((uint8_t *)str, cnt);
@@ -1131,7 +1141,7 @@ void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
1131
1141
  } else if (isnan(d)) {
1132
1142
  if (ObjectMode == out->opts->mode) {
1133
1143
  strcpy(buf, nan_val);
1134
- cnt = sizeof(ninf_val) - 1;
1144
+ cnt = sizeof(nan_val) - 1;
1135
1145
  } else {
1136
1146
  NanDump nd = out->opts->dump_opts.nan_dump;
1137
1147
 
data/ext/oj/dump_compat.c CHANGED
@@ -444,7 +444,6 @@ time_alt(VALUE obj, int depth, Out out) {
444
444
  time_t sec;
445
445
  long long nsec;
446
446
 
447
- #ifdef HAVE_RB_TIME_TIMESPEC
448
447
  if (16 <= sizeof(struct timespec)) {
449
448
  struct timespec ts = rb_time_timespec(obj);
450
449
 
@@ -454,10 +453,6 @@ time_alt(VALUE obj, int depth, Out out) {
454
453
  sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
455
454
  nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
456
455
  }
457
- #else
458
- sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
459
- nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
460
- #endif
461
456
 
462
457
  attrs[0].num = sec;
463
458
  attrs[1].num = nsec;
data/ext/oj/dump_object.c CHANGED
@@ -315,7 +315,6 @@ static void dump_hash_class(VALUE obj, VALUE clas, int depth, Out out) {
315
315
  *out->cur = '\0';
316
316
  }
317
317
 
318
- #ifdef HAVE_RB_IVAR_FOREACH
319
318
  static int dump_attr_cb(ID key, VALUE value, VALUE ov) {
320
319
  Out out = (Out)ov;
321
320
  int depth = out->depth;
@@ -358,7 +357,6 @@ static int dump_attr_cb(ID key, VALUE value, VALUE ov) {
358
357
 
359
358
  return ST_CONTINUE;
360
359
  }
361
- #endif
362
360
 
363
361
  static void dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
364
362
  dump_hash_class(obj, rb_obj_class(obj), depth, out);
@@ -510,19 +508,8 @@ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out)
510
508
  default: break;
511
509
  }
512
510
  {
513
- int cnt;
514
- #ifdef HAVE_RB_IVAR_COUNT
515
- cnt = (int)rb_ivar_count(obj);
516
- #else
517
- volatile VALUE vars = rb_funcall2(obj, oj_instance_variables_id, 0, 0);
518
- VALUE * np = RARRAY_PTR(vars);
519
- ID vid;
520
- const char * attr;
521
- int i;
522
- int first = 1;
523
-
524
- cnt = (int)RARRAY_LEN(vars);
525
- #endif
511
+ int cnt = (int)rb_ivar_count(obj);
512
+
526
513
  if (Qundef != clas && 0 < cnt) {
527
514
  *out->cur++ = ',';
528
515
  }
@@ -535,52 +522,10 @@ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out)
535
522
  }
536
523
  }
537
524
  out->depth = depth + 1;
538
- #ifdef HAVE_RB_IVAR_FOREACH
539
525
  rb_ivar_foreach(obj, dump_attr_cb, (VALUE)out);
540
526
  if (',' == *(out->cur - 1)) {
541
527
  out->cur--; // backup to overwrite last comma
542
528
  }
543
- #else
544
- size = d2 * out->indent + 1;
545
- for (i = cnt; 0 < i; i--, np++) {
546
- VALUE value;
547
-
548
- vid = rb_to_id(*np);
549
- attr = rb_id2name(vid);
550
- if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
551
- continue;
552
- }
553
- value = rb_ivar_get(obj, vid);
554
-
555
- if (dump_ignore(out->opts, value)) {
556
- continue;
557
- }
558
- if (out->omit_nil && Qnil == value) {
559
- continue;
560
- }
561
- if (first) {
562
- first = 0;
563
- } else {
564
- *out->cur++ = ',';
565
- }
566
- assure_size(out, size);
567
- fill_indent(out, d2);
568
- if ('@' == *attr) {
569
- attr++;
570
- oj_dump_cstr(attr, strlen(attr), 0, 0, out);
571
- } else {
572
- char buf[32];
573
-
574
- *buf = '~';
575
- strncpy(buf + 1, attr, sizeof(buf) - 2);
576
- buf[sizeof(buf) - 1] = '\0';
577
- oj_dump_cstr(buf, strlen(attr) + 1, 0, 0, out);
578
- }
579
- *out->cur++ = ':';
580
- oj_dump_obj_val(value, d2, out);
581
- assure_size(out, 2);
582
- }
583
- #endif
584
529
  if (rb_obj_is_kind_of(obj, rb_eException)) {
585
530
  volatile VALUE rv;
586
531
 
data/ext/oj/extconf.rb CHANGED
@@ -23,14 +23,10 @@ dflags = {
23
23
  'RSTRUCT_LEN_RETURNS_INTEGER_OBJECT' => ('ruby' == type && '2' == version[0] && '4' == version[1] && '1' >= version[2]) ? 1 : 0,
24
24
  }
25
25
 
26
- have_func('rb_time_timespec')
27
- have_func('rb_ivar_count')
28
- have_func('rb_ivar_foreach')
29
26
  # Support for compaction.
30
27
  have_func('rb_gc_mark_movable')
31
28
  have_func('stpcpy')
32
29
  have_func('pthread_mutex_init')
33
- have_func('rb_enc_associate')
34
30
  have_func('rb_enc_interned_str')
35
31
  have_func('rb_ext_ractor_safe', 'ruby.h')
36
32
  # rb_hash_bulk_insert is deep down in a header not included in normal build and that seems to fool have_func.
@@ -38,6 +34,11 @@ have_func('rb_hash_bulk_insert', 'ruby.h') unless '2' == version[0] && '6' == ve
38
34
 
39
35
  dflags['OJ_DEBUG'] = true unless ENV['OJ_DEBUG'].nil?
40
36
 
37
+ if try_cflags('-msse4.2')
38
+ $CPPFLAGS += ' -msse4.2'
39
+ dflags['OJ_USE_SSE4_2'] = 1
40
+ end
41
+
41
42
  dflags.each do |k,v|
42
43
  if v.nil?
43
44
  $CPPFLAGS += " -D#{k}"
data/ext/oj/mimic_json.c CHANGED
@@ -388,6 +388,10 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
388
388
  VALUE active_hack[1];
389
389
 
390
390
  if (Qundef == state_class) {
391
+ rb_warn(
392
+ "Oj::Rails.mimic_JSON was called implicitly. "
393
+ "Call it explicitly beforehand if you want to remove this warning."
394
+ );
391
395
  oj_define_mimic_json(0, NULL, Qnil);
392
396
  }
393
397
  active_hack[0] = rb_funcall(state_class, oj_new_id, 0);
@@ -460,7 +464,7 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
460
464
  if (0 == argc) {
461
465
  rb_raise(rb_eArgError, "wrong number of arguments (0))");
462
466
  }
463
- if (1 == argc) {
467
+ if (1 == argc || Qnil == argv[1]) {
464
468
  h = rb_hash_new();
465
469
  } else {
466
470
  h = argv[1];
@@ -481,6 +485,10 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
481
485
  rb_hash_aset(h, oj_array_nl_sym, rb_str_new2("\n"));
482
486
  }
483
487
  if (Qundef == state_class) {
488
+ rb_warn(
489
+ "Oj::Rails.mimic_JSON was called implicitly. "
490
+ "Call it explicitly beforehand if you want to remove this warning."
491
+ );
484
492
  oj_define_mimic_json(0, NULL, Qnil);
485
493
  }
486
494
  rargs[1] = rb_funcall(state_class, oj_new_id, 1, h);
@@ -536,14 +544,6 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE info) {
536
544
  }
537
545
  } else if (oj_decimal_class_sym == k) {
538
546
  pi->options.compat_bigdec = (oj_bigdecimal_class == v);
539
- } else if (oj_max_nesting_sym == k) {
540
- if (Qtrue == v) {
541
- pi->max_depth = 100;
542
- } else if (Qfalse == v || Qnil == v) {
543
- pi->max_depth = 0;
544
- } else if (T_FIXNUM == rb_type(v)) {
545
- pi->max_depth = NUM2INT(v);
546
- }
547
547
  }
548
548
  return ST_CONTINUE;
549
549
  }
@@ -573,11 +573,21 @@ static VALUE mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
573
573
  pi.max_depth = 100;
574
574
 
575
575
  if (Qnil != ropts) {
576
+ VALUE v;
577
+
576
578
  if (T_HASH != rb_type(ropts)) {
577
579
  rb_raise(rb_eArgError, "options must be a hash.");
578
580
  }
579
581
 
580
582
  rb_hash_foreach(ropts, parse_options_cb, (VALUE)&pi);
583
+ v = rb_hash_lookup(ropts, oj_max_nesting_sym);
584
+ if (Qtrue == v) {
585
+ pi.max_depth = 100;
586
+ } else if (Qfalse == v || Qnil == v) {
587
+ pi.max_depth = 0;
588
+ } else if (T_FIXNUM == rb_type(v)) {
589
+ pi.max_depth = NUM2INT(v);
590
+ }
581
591
  oj_parse_opt_match_string(&pi.options.str_rx, ropts);
582
592
  if (Yes == pi.options.create_ok && Yes == pi.options.sym_key) {
583
593
  rb_raise(rb_eArgError, ":symbolize_names and :create_additions can not both be true.");
data/ext/oj/object.c CHANGED
@@ -445,7 +445,7 @@ WHICH_TYPE:
445
445
  rb_class2name(rb_obj_class(parent->val)));
446
446
  return;
447
447
  }
448
- if (Yes == pi->options.trace) {
448
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
449
449
  oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rval);
450
450
  }
451
451
  }
@@ -516,7 +516,7 @@ WHICH_TYPE:
516
516
  rb_class2name(rb_obj_class(parent->val)));
517
517
  return;
518
518
  }
519
- if (Yes == pi->options.trace) {
519
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
520
520
  oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, rval);
521
521
  }
522
522
  }
@@ -602,13 +602,13 @@ WHICH_TYPE:
602
602
  rb_class2name(rb_obj_class(parent->val)));
603
603
  return;
604
604
  }
605
- if (Yes == pi->options.trace) {
605
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
606
606
  oj_trace_parse_call("add_value", pi, __FILE__, __LINE__, value);
607
607
  }
608
608
  }
609
609
 
610
610
  static VALUE start_hash(ParseInfo pi) {
611
- if (Yes == pi->options.trace) {
611
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
612
612
  oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
613
613
  }
614
614
  return Qnil;
@@ -626,7 +626,7 @@ static void end_hash(ParseInfo pi) {
626
626
  oj_odd_free(oa);
627
627
  parent->odd_args = NULL;
628
628
  }
629
- if (Yes == pi->options.trace) {
629
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
630
630
  oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
631
631
  }
632
632
  }
@@ -654,7 +654,7 @@ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const c
654
654
  }
655
655
  rval = str_to_value(pi, str, len, orig);
656
656
  rb_ary_push(stack_peek(&pi->stack)->val, rval);
657
- if (Yes == pi->options.trace) {
657
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
658
658
  oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rval);
659
659
  }
660
660
  }
@@ -663,21 +663,21 @@ static void array_append_num(ParseInfo pi, NumInfo ni) {
663
663
  volatile VALUE rval = oj_num_as_value(ni);
664
664
 
665
665
  rb_ary_push(stack_peek(&pi->stack)->val, rval);
666
- if (Yes == pi->options.trace) {
666
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
667
667
  oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
668
668
  }
669
669
  }
670
670
 
671
671
  static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
672
672
  pi->stack.head->val = str_to_value(pi, str, len, orig);
673
- if (Yes == pi->options.trace) {
673
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
674
674
  oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, pi->stack.head->val);
675
675
  }
676
676
  }
677
677
 
678
678
  static void add_num(ParseInfo pi, NumInfo ni) {
679
679
  pi->stack.head->val = oj_num_as_value(ni);
680
- if (Yes == pi->options.trace) {
680
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
681
681
  oj_trace_parse_call("add_num", pi, __FILE__, __LINE__, pi->stack.head->val);
682
682
  }
683
683
  }
data/ext/oj/oj.c CHANGED
@@ -45,7 +45,6 @@ ID oj_hash_key_id;
45
45
  ID oj_hash_set_id;
46
46
  ID oj_hash_start_id;
47
47
  ID oj_iconv_id;
48
- ID oj_instance_variables_id;
49
48
  ID oj_json_create_id;
50
49
  ID oj_length_id;
51
50
  ID oj_new_id;
@@ -137,6 +136,7 @@ static VALUE rails_sym;
137
136
  static VALUE raise_sym;
138
137
  static VALUE ruby_sym;
139
138
  static VALUE sec_prec_sym;
139
+ static VALUE slash_sym;
140
140
  static VALUE strict_sym;
141
141
  static VALUE symbol_keys_sym;
142
142
  static VALUE time_format_sym;
@@ -405,6 +405,7 @@ static VALUE get_def_opts(VALUE self) {
405
405
  switch (oj_default_options.escape_mode) {
406
406
  case NLEsc: rb_hash_aset(opts, escape_mode_sym, newline_sym); break;
407
407
  case JSONEsc: rb_hash_aset(opts, escape_mode_sym, json_sym); break;
408
+ case SlashEsc: rb_hash_aset(opts, escape_mode_sym, slash_sym); break;
408
409
  case XSSEsc: rb_hash_aset(opts, escape_mode_sym, xss_safe_sym); break;
409
410
  case ASCIIEsc: rb_hash_aset(opts, escape_mode_sym, ascii_sym); break;
410
411
  case JXEsc: rb_hash_aset(opts, escape_mode_sym, unicode_xss_sym); break;
@@ -734,6 +735,8 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
734
735
  copts->escape_mode = NLEsc;
735
736
  } else if (json_sym == v) {
736
737
  copts->escape_mode = JSONEsc;
738
+ } else if (slash_sym == v) {
739
+ copts->escape_mode = SlashEsc;
737
740
  } else if (xss_safe_sym == v) {
738
741
  copts->escape_mode = XSSEsc;
739
742
  } else if (ascii_sym == v) {
@@ -1148,7 +1151,17 @@ static VALUE load_file(int argc, VALUE *argv, VALUE self) {
1148
1151
  }
1149
1152
  }
1150
1153
  path = StringValuePtr(*argv);
1151
- if (0 == (fd = open(path, O_RDONLY))) {
1154
+ #ifdef _WIN32
1155
+ {
1156
+ WCHAR *wide_path;
1157
+ wide_path = rb_w32_mbstr_to_wstr(CP_UTF8, path, -1, NULL);
1158
+ fd = rb_w32_wopen(wide_path, O_RDONLY);
1159
+ free(wide_path);
1160
+ }
1161
+ #else
1162
+ fd = open(path, O_RDONLY);
1163
+ #endif
1164
+ if (0 == fd) {
1152
1165
  rb_raise(rb_eIOError, "%s", strerror(errno));
1153
1166
  }
1154
1167
  switch (mode) {
@@ -1814,7 +1827,6 @@ void Init_oj(void) {
1814
1827
  oj_hash_set_id = rb_intern("hash_set");
1815
1828
  oj_hash_start_id = rb_intern("hash_start");
1816
1829
  oj_iconv_id = rb_intern("iconv");
1817
- oj_instance_variables_id = rb_intern("instance_variables");
1818
1830
  oj_json_create_id = rb_intern("json_create");
1819
1831
  oj_length_id = rb_intern("length");
1820
1832
  oj_new_id = rb_intern("new");
@@ -1977,6 +1989,8 @@ void Init_oj(void) {
1977
1989
  rb_gc_register_address(&ruby_sym);
1978
1990
  sec_prec_sym = ID2SYM(rb_intern("second_precision"));
1979
1991
  rb_gc_register_address(&sec_prec_sym);
1992
+ slash_sym = ID2SYM(rb_intern("slash"));
1993
+ rb_gc_register_address(&slash_sym);
1980
1994
  strict_sym = ID2SYM(rb_intern("strict"));
1981
1995
  rb_gc_register_address(&strict_sym);
1982
1996
  symbol_keys_sym = ID2SYM(rb_intern("symbol_keys"));
data/ext/oj/oj.h CHANGED
@@ -66,6 +66,7 @@ typedef enum { UnixTime = 'u', UnixZTime = 'z', XmlTime = 'x', RubyTime = 'r' }
66
66
  typedef enum {
67
67
  NLEsc = 'n',
68
68
  JSONEsc = 'j',
69
+ SlashEsc = 's',
69
70
  XSSEsc = 'x',
70
71
  ASCIIEsc = 'a',
71
72
  JXEsc = 'g', // json gem
@@ -346,7 +347,6 @@ extern ID oj_hash_key_id;
346
347
  extern ID oj_hash_set_id;
347
348
  extern ID oj_hash_start_id;
348
349
  extern ID oj_iconv_id;
349
- extern ID oj_instance_variables_id;
350
350
  extern ID oj_json_create_id;
351
351
  extern ID oj_length_id;
352
352
  extern ID oj_new_id;