oj 3.13.15 → 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: 2dd6fd9c107efe5095ca235c398e2fb7cc4fb9cdd9feffb4f27fef1ed1e3faa3
4
- data.tar.gz: 072e3744f4cbb880f1e5296ad1abba448341d9934173fa101ba1d65efe20de64
3
+ metadata.gz: d07b4081b5dda88146594adba591542d11106f1c1eadcf7c56e38358d0ee0af3
4
+ data.tar.gz: 6bdc82c3812f45a8ae9d72ec0b2f43ee223d95ac250399fc8dae8daf34cd3b49
5
5
  SHA512:
6
- metadata.gz: 76fbaa3e575553ffbf37e45447429b58da392d58e59afa82491363a17ee3ab7cacf5283986db7242f1cf8b0340449d8a1d97a6f54c288076110a2fdc5ccebf30
7
- data.tar.gz: 116f07d7db9124f62007eff33a2583f4de5a1338009fec59eca267a483be229285a7ec66c6fbb1feb92f05284afe76ae39629aca2e8f2a7ff20caa27adddc0c4
6
+ metadata.gz: 4358aa15b7956a5b577163e43fbdc0512212a218124878ceedc2932483f27acabed2d2b92eb888c8e54601f4f4aaf3dce3b959a36effbea989e7e7ea8956d1c1
7
+ data.tar.gz: 1e1710bce62aadfbcc1196357d2e692892b75cc18c982fb6f53c2e35782d9bd2256cb3b6ab98951691430f23e8c2d8db26987a95dcba29f87b472729613b8d2d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
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
+
3
7
  ## 3.13.15 - 2022-07-03
4
8
 
5
9
  - Fixed issue dumping NaN value in object mode.
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/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/parser.c CHANGED
@@ -533,6 +533,7 @@ static void calc_num(ojParser p) {
533
533
  // nothing to do
534
534
  break;
535
535
  }
536
+ p->type = OJ_NONE;
536
537
  }
537
538
 
538
539
  static void big_change(ojParser p) {
@@ -598,6 +599,8 @@ static void parse(ojParser p, const byte *json) {
598
599
  const byte *b = json;
599
600
  int i;
600
601
 
602
+ p->line = 1;
603
+ p->col = -1;
601
604
  #if DEBUG
602
605
  printf("*** parse - mode: %c %s\n", p->map[256], (const char *)json);
603
606
  #endif
@@ -652,6 +655,7 @@ static void parse(ojParser p, const byte *json) {
652
655
  }
653
656
  buf_append_string(&p->buf, (const char *)start, b - start);
654
657
  if ('"' == *b) {
658
+ p->cur = b - json;
655
659
  p->funcs[p->stack[p->depth]].add_str(p);
656
660
  p->map = (0 == p->depth) ? value_map : after_map;
657
661
  break;
@@ -661,12 +665,14 @@ static void parse(ojParser p, const byte *json) {
661
665
  p->next_map = (0 == p->depth) ? value_map : after_map;
662
666
  break;
663
667
  case OPEN_OBJECT:
668
+ p->cur = b - json;
664
669
  p->funcs[p->stack[p->depth]].open_object(p);
665
670
  p->depth++;
666
671
  p->stack[p->depth] = OBJECT_FUN;
667
672
  p->map = key1_map;
668
673
  break;
669
674
  case NUM_CLOSE_OBJECT:
675
+ p->cur = b - json;
670
676
  calc_num(p);
671
677
  // flow through
672
678
  case CLOSE_OBJECT:
@@ -677,15 +683,18 @@ static void parse(ojParser p, const byte *json) {
677
683
  return;
678
684
  }
679
685
  p->depth--;
686
+ p->cur = b - json;
680
687
  p->funcs[p->stack[p->depth]].close_object(p);
681
688
  break;
682
689
  case OPEN_ARRAY:
690
+ p->cur = b - json;
683
691
  p->funcs[p->stack[p->depth]].open_array(p);
684
692
  p->depth++;
685
693
  p->stack[p->depth] = ARRAY_FUN;
686
694
  p->map = value_map;
687
695
  break;
688
696
  case NUM_CLOSE_ARRAY:
697
+ p->cur = b - json;
689
698
  calc_num(p);
690
699
  // flow through
691
700
  case CLOSE_ARRAY:
@@ -696,9 +705,11 @@ static void parse(ojParser p, const byte *json) {
696
705
  return;
697
706
  }
698
707
  p->depth--;
708
+ p->cur = b - json;
699
709
  p->funcs[p->stack[p->depth]].close_array(p);
700
710
  break;
701
711
  case NUM_COMMA:
712
+ p->cur = b - json;
702
713
  calc_num(p);
703
714
  if (0 < p->depth && OBJECT_FUN == p->stack[p->depth]) {
704
715
  p->map = key_map;
@@ -860,8 +871,14 @@ static void parse(ojParser p, const byte *json) {
860
871
  b--;
861
872
  p->map = big_exp_map;
862
873
  break;
863
- case NUM_SPC: calc_num(p); break;
864
- case NUM_NEWLINE: calc_num(p); b++;
874
+ case NUM_SPC:
875
+ p->cur = b - json;
876
+ calc_num(p);
877
+ break;
878
+ case NUM_NEWLINE:
879
+ p->cur = b - json;
880
+ calc_num(p);
881
+ b++;
865
882
  #ifdef SPACE_JUMP
866
883
  // for (uint32_t *sj = (uint32_t*)b; 0x20202020 == *sj; sj++) { b += 4; }
867
884
  for (uint16_t *sj = (uint16_t *)b; 0x2020 == *sj; sj++) {
@@ -882,6 +899,7 @@ static void parse(ojParser p, const byte *json) {
882
899
  buf_append_string(&p->buf, (const char *)start, b - start);
883
900
  }
884
901
  if ('"' == *b) {
902
+ p->cur = b - json;
885
903
  p->funcs[p->stack[p->depth]].add_str(p);
886
904
  p->map = p->next_map;
887
905
  break;
@@ -890,6 +908,7 @@ static void parse(ojParser p, const byte *json) {
890
908
  break;
891
909
  case STR_SLASH: p->map = esc_map; break;
892
910
  case STR_QUOTE:
911
+ p->cur = b - json;
893
912
  p->funcs[p->stack[p->depth]].add_str(p);
894
913
  p->map = p->next_map;
895
914
  break;
@@ -967,6 +986,7 @@ static void parse(ojParser p, const byte *json) {
967
986
  case VAL_NULL:
968
987
  if ('u' == b[1] && 'l' == b[2] && 'l' == b[3]) {
969
988
  b += 3;
989
+ p->cur = b - json;
970
990
  p->funcs[p->stack[p->depth]].add_null(p);
971
991
  p->map = (0 == p->depth) ? value_map : after_map;
972
992
  break;
@@ -992,6 +1012,7 @@ static void parse(ojParser p, const byte *json) {
992
1012
  case VAL_TRUE:
993
1013
  if ('r' == b[1] && 'u' == b[2] && 'e' == b[3]) {
994
1014
  b += 3;
1015
+ p->cur = b - json;
995
1016
  p->funcs[p->stack[p->depth]].add_true(p);
996
1017
  p->map = (0 == p->depth) ? value_map : after_map;
997
1018
  break;
@@ -1017,6 +1038,7 @@ static void parse(ojParser p, const byte *json) {
1017
1038
  case VAL_FALSE:
1018
1039
  if ('a' == b[1] && 'l' == b[2] && 's' == b[3] && 'e' == b[4]) {
1019
1040
  b += 4;
1041
+ p->cur = b - json;
1020
1042
  p->funcs[p->stack[p->depth]].add_false(p);
1021
1043
  p->map = (0 == p->depth) ? value_map : after_map;
1022
1044
  break;
@@ -1050,6 +1072,7 @@ static void parse(ojParser p, const byte *json) {
1050
1072
  parse_error(p, "expected null");
1051
1073
  return;
1052
1074
  }
1075
+ p->cur = b - json;
1053
1076
  p->funcs[p->stack[p->depth]].add_null(p);
1054
1077
  p->map = (0 == p->depth) ? value_map : after_map;
1055
1078
  }
@@ -1061,6 +1084,7 @@ static void parse(ojParser p, const byte *json) {
1061
1084
  parse_error(p, "expected false");
1062
1085
  return;
1063
1086
  }
1087
+ p->cur = b - json;
1064
1088
  p->funcs[p->stack[p->depth]].add_false(p);
1065
1089
  p->map = (0 == p->depth) ? value_map : after_map;
1066
1090
  }
@@ -1072,6 +1096,7 @@ static void parse(ojParser p, const byte *json) {
1072
1096
  parse_error(p, "expected true");
1073
1097
  return;
1074
1098
  }
1099
+ p->cur = b - json;
1075
1100
  p->funcs[p->stack[p->depth]].add_true(p);
1076
1101
  p->map = (0 == p->depth) ? value_map : after_map;
1077
1102
  }
@@ -1099,7 +1124,10 @@ static void parse(ojParser p, const byte *json) {
1099
1124
  case 'D':
1100
1125
  case 'g':
1101
1126
  case 'B':
1102
- case 'Y': calc_num(p); break;
1127
+ case 'Y':
1128
+ p->cur = b - json;
1129
+ calc_num(p);
1130
+ break;
1103
1131
  }
1104
1132
  }
1105
1133
  return;
@@ -1456,7 +1484,7 @@ static VALUE saj_parser = Qundef;
1456
1484
  /* Document-method: saj
1457
1485
  * call-seq: saj
1458
1486
  *
1459
- * Returns the default saj parser. Note the default SAJ parser can not be used
1487
+ * Returns the default SAJ parser. Note the default SAJ parser can not be used
1460
1488
  * concurrently in more than one thread.
1461
1489
  */
1462
1490
  static VALUE parser_saj(VALUE self) {
data/ext/oj/parser.h CHANGED
@@ -80,6 +80,7 @@ typedef struct _ojParser {
80
80
 
81
81
  char token[8];
82
82
  long line;
83
+ long cur; // only set before call to a function
83
84
  long col;
84
85
  int ri;
85
86
  uint32_t ucode;
data/ext/oj/saj2.c CHANGED
@@ -6,8 +6,8 @@
6
6
 
7
7
  typedef struct _delegate {
8
8
  VALUE handler;
9
- VALUE * keys;
10
- VALUE * tail;
9
+ VALUE *keys;
10
+ VALUE *tail;
11
11
  size_t klen;
12
12
  struct _cache *str_cache;
13
13
  uint8_t cache_str;
@@ -17,7 +17,7 @@ typedef struct _delegate {
17
17
 
18
18
  static VALUE get_key(ojParser p) {
19
19
  Delegate d = (Delegate)p->ctx;
20
- const char * key = buf_str(&p->key);
20
+ const char *key = buf_str(&p->key);
21
21
  size_t len = buf_len(&p->key);
22
22
  volatile VALUE rkey;
23
23
 
@@ -48,6 +48,10 @@ static void open_object(ojParser p) {
48
48
  rb_funcall(((Delegate)p->ctx)->handler, oj_hash_start_id, 1, Qnil);
49
49
  }
50
50
 
51
+ static void open_object_loc(ojParser p) {
52
+ rb_funcall(((Delegate)p->ctx)->handler, oj_hash_start_id, 3, Qnil, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
53
+ }
54
+
51
55
  static void open_object_key(ojParser p) {
52
56
  Delegate d = (Delegate)p->ctx;
53
57
  volatile VALUE key = get_key(p);
@@ -56,10 +60,22 @@ static void open_object_key(ojParser p) {
56
60
  rb_funcall(d->handler, oj_hash_start_id, 1, key);
57
61
  }
58
62
 
63
+ static void open_object_loc_key(ojParser p) {
64
+ Delegate d = (Delegate)p->ctx;
65
+ volatile VALUE key = get_key(p);
66
+
67
+ push_key(d, key);
68
+ rb_funcall(d->handler, oj_hash_start_id, 3, key, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
69
+ }
70
+
59
71
  static void open_array(ojParser p) {
60
72
  rb_funcall(((Delegate)p->ctx)->handler, oj_array_start_id, 1, Qnil);
61
73
  }
62
74
 
75
+ static void open_array_loc(ojParser p) {
76
+ rb_funcall(((Delegate)p->ctx)->handler, oj_array_start_id, 3, Qnil, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
77
+ }
78
+
63
79
  static void open_array_key(ojParser p) {
64
80
  Delegate d = (Delegate)p->ctx;
65
81
  volatile VALUE key = get_key(p);
@@ -68,6 +84,14 @@ static void open_array_key(ojParser p) {
68
84
  rb_funcall(d->handler, oj_array_start_id, 1, key);
69
85
  }
70
86
 
87
+ static void open_array_loc_key(ojParser p) {
88
+ Delegate d = (Delegate)p->ctx;
89
+ volatile VALUE key = get_key(p);
90
+
91
+ push_key(d, key);
92
+ rb_funcall(d->handler, oj_array_start_id, 3, key, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
93
+ }
94
+
71
95
  static void close_object(ojParser p) {
72
96
  Delegate d = (Delegate)p->ctx;
73
97
  VALUE key = Qnil;
@@ -82,6 +106,20 @@ static void close_object(ojParser p) {
82
106
  rb_funcall(d->handler, oj_hash_end_id, 1, key);
83
107
  }
84
108
 
109
+ static void close_object_loc(ojParser p) {
110
+ Delegate d = (Delegate)p->ctx;
111
+ VALUE key = Qnil;
112
+
113
+ if (OBJECT_FUN == p->stack[p->depth]) {
114
+ d->tail--;
115
+ if (d->tail < d->keys) {
116
+ rb_raise(rb_eIndexError, "accessing key stack");
117
+ }
118
+ key = *d->tail;
119
+ }
120
+ rb_funcall(d->handler, oj_hash_end_id, 3, key, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
121
+ }
122
+
85
123
  static void close_array(ojParser p) {
86
124
  Delegate d = (Delegate)p->ctx;
87
125
  VALUE key = Qnil;
@@ -96,46 +134,160 @@ static void close_array(ojParser p) {
96
134
  rb_funcall(d->handler, oj_array_end_id, 1, key);
97
135
  }
98
136
 
137
+ static void close_array_loc(ojParser p) {
138
+ Delegate d = (Delegate)p->ctx;
139
+ VALUE key = Qnil;
140
+
141
+ if (OBJECT_FUN == p->stack[p->depth]) {
142
+ d->tail--;
143
+ if (d->tail < d->keys) {
144
+ rb_raise(rb_eIndexError, "accessing key stack");
145
+ }
146
+ key = *d->tail;
147
+ }
148
+ rb_funcall(d->handler, oj_array_end_id, 3, key, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
149
+ }
150
+
99
151
  static void add_null(ojParser p) {
100
152
  rb_funcall(((Delegate)p->ctx)->handler, oj_add_value_id, 2, Qnil, Qnil);
101
153
  }
102
154
 
155
+ static void add_null_loc(ojParser p) {
156
+ rb_funcall(((Delegate)p->ctx)->handler,
157
+ oj_add_value_id,
158
+ 4,
159
+ Qnil,
160
+ Qnil,
161
+ LONG2FIX(p->line),
162
+ LONG2FIX(p->cur - p->col));
163
+ }
164
+
103
165
  static void add_null_key(ojParser p) {
104
166
  rb_funcall(((Delegate)p->ctx)->handler, oj_add_value_id, 2, Qnil, get_key(p));
105
167
  }
106
168
 
169
+ static void add_null_key_loc(ojParser p) {
170
+ rb_funcall(((Delegate)p->ctx)->handler,
171
+ oj_add_value_id,
172
+ 4,
173
+ Qnil,
174
+ get_key(p),
175
+ LONG2FIX(p->line),
176
+ LONG2FIX(p->cur - p->col));
177
+ }
178
+
107
179
  static void add_true(ojParser p) {
108
180
  rb_funcall(((Delegate)p->ctx)->handler, oj_add_value_id, 2, Qtrue, Qnil);
109
181
  }
110
182
 
183
+ static void add_true_loc(ojParser p) {
184
+ rb_funcall(((Delegate)p->ctx)->handler,
185
+ oj_add_value_id,
186
+ 4,
187
+ Qtrue,
188
+ Qnil,
189
+ LONG2FIX(p->line),
190
+ LONG2FIX(p->cur - p->col));
191
+ }
192
+
111
193
  static void add_true_key(ojParser p) {
112
194
  rb_funcall(((Delegate)p->ctx)->handler, oj_add_value_id, 2, Qtrue, get_key(p));
113
195
  }
114
196
 
197
+ static void add_true_key_loc(ojParser p) {
198
+ rb_funcall(((Delegate)p->ctx)->handler,
199
+ oj_add_value_id,
200
+ 4,
201
+ Qtrue,
202
+ get_key(p),
203
+ LONG2FIX(p->line),
204
+ LONG2FIX(p->cur - p->col));
205
+ }
206
+
115
207
  static void add_false(ojParser p) {
116
208
  rb_funcall(((Delegate)p->ctx)->handler, oj_add_value_id, 2, Qfalse, Qnil);
117
209
  }
118
210
 
211
+ static void add_false_loc(ojParser p) {
212
+ rb_funcall(((Delegate)p->ctx)->handler,
213
+ oj_add_value_id,
214
+ 4,
215
+ Qfalse,
216
+ Qnil,
217
+ LONG2FIX(p->line),
218
+ LONG2FIX(p->cur - p->col));
219
+ }
220
+
119
221
  static void add_false_key(ojParser p) {
120
222
  rb_funcall(((Delegate)p->ctx)->handler, oj_add_value_id, 2, Qfalse, get_key(p));
121
223
  }
122
224
 
225
+ static void add_false_key_loc(ojParser p) {
226
+ rb_funcall(((Delegate)p->ctx)->handler,
227
+ oj_add_value_id,
228
+ 4,
229
+ Qfalse,
230
+ get_key(p),
231
+ LONG2FIX(p->line),
232
+ LONG2FIX(p->cur - p->col));
233
+ }
234
+
123
235
  static void add_int(ojParser p) {
124
236
  rb_funcall(((Delegate)p->ctx)->handler, oj_add_value_id, 2, LONG2NUM(p->num.fixnum), Qnil);
125
237
  }
126
238
 
239
+ static void add_int_loc(ojParser p) {
240
+ rb_funcall(((Delegate)p->ctx)->handler,
241
+ oj_add_value_id,
242
+ 4,
243
+ LONG2NUM(p->num.fixnum),
244
+ Qnil,
245
+ LONG2FIX(p->line),
246
+ LONG2FIX(p->cur - p->col));
247
+ }
248
+
127
249
  static void add_int_key(ojParser p) {
128
250
  rb_funcall(((Delegate)p->ctx)->handler, oj_add_value_id, 2, LONG2NUM(p->num.fixnum), get_key(p));
129
251
  }
130
252
 
253
+ static void add_int_key_loc(ojParser p) {
254
+ rb_funcall(((Delegate)p->ctx)->handler,
255
+ oj_add_value_id,
256
+ 4,
257
+ LONG2NUM(p->num.fixnum),
258
+ get_key(p),
259
+ LONG2FIX(p->line),
260
+ LONG2FIX(p->cur - p->col));
261
+ }
262
+
131
263
  static void add_float(ojParser p) {
132
264
  rb_funcall(((Delegate)p->ctx)->handler, oj_add_value_id, 2, rb_float_new(p->num.dub), Qnil);
133
265
  }
134
266
 
267
+ static void add_float_loc(ojParser p) {
268
+ rb_funcall(((Delegate)p->ctx)->handler,
269
+ oj_add_value_id,
270
+ 4,
271
+ rb_float_new(p->num.dub),
272
+ Qnil,
273
+ LONG2FIX(p->line),
274
+ LONG2FIX(p->cur - p->col));
275
+ }
276
+
135
277
  static void add_float_key(ojParser p) {
136
278
  rb_funcall(((Delegate)p->ctx)->handler, oj_add_value_id, 2, rb_float_new(p->num.dub), get_key(p));
137
279
  }
138
280
 
281
+ static void add_float_key_loc(ojParser p) {
282
+ rb_funcall(((Delegate)p->ctx)->handler,
283
+ oj_add_value_id,
284
+ 4,
285
+ rb_float_new(p->num.dub),
286
+ get_key(p),
287
+ LONG2FIX(p->line),
288
+ LONG2FIX(p->cur - p->col));
289
+ }
290
+
139
291
  static void add_big(ojParser p) {
140
292
  rb_funcall((VALUE)p->ctx,
141
293
  oj_add_value_id,
@@ -144,6 +296,16 @@ static void add_big(ojParser p) {
144
296
  Qnil);
145
297
  }
146
298
 
299
+ static void add_big_loc(ojParser p) {
300
+ rb_funcall((VALUE)p->ctx,
301
+ oj_add_value_id,
302
+ 4,
303
+ rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new(buf_str(&p->buf), buf_len(&p->buf))),
304
+ Qnil,
305
+ LONG2FIX(p->line),
306
+ LONG2FIX(p->cur - p->col));
307
+ }
308
+
147
309
  static void add_big_key(ojParser p) {
148
310
  rb_funcall((VALUE)p->ctx,
149
311
  oj_add_value_id,
@@ -152,10 +314,20 @@ static void add_big_key(ojParser p) {
152
314
  get_key(p));
153
315
  }
154
316
 
317
+ static void add_big_key_loc(ojParser p) {
318
+ rb_funcall((VALUE)p->ctx,
319
+ oj_add_value_id,
320
+ 4,
321
+ rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new(buf_str(&p->buf), buf_len(&p->buf))),
322
+ get_key(p),
323
+ LONG2FIX(p->line),
324
+ LONG2FIX(p->cur - p->col));
325
+ }
326
+
155
327
  static void add_str(ojParser p) {
156
328
  Delegate d = (Delegate)p->ctx;
157
329
  volatile VALUE rstr;
158
- const char * str = buf_str(&p->buf);
330
+ const char *str = buf_str(&p->buf);
159
331
  size_t len = buf_len(&p->buf);
160
332
 
161
333
  if (d->cache_str < len) {
@@ -166,10 +338,24 @@ static void add_str(ojParser p) {
166
338
  rb_funcall(d->handler, oj_add_value_id, 2, rstr, Qnil);
167
339
  }
168
340
 
341
+ static void add_str_loc(ojParser p) {
342
+ Delegate d = (Delegate)p->ctx;
343
+ volatile VALUE rstr;
344
+ const char *str = buf_str(&p->buf);
345
+ size_t len = buf_len(&p->buf);
346
+
347
+ if (d->cache_str < len) {
348
+ rstr = cache_intern(d->str_cache, str, len);
349
+ } else {
350
+ rstr = rb_utf8_str_new(str, len);
351
+ }
352
+ rb_funcall(d->handler, oj_add_value_id, 4, rstr, Qnil, LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
353
+ }
354
+
169
355
  static void add_str_key(ojParser p) {
170
356
  Delegate d = (Delegate)p->ctx;
171
357
  volatile VALUE rstr;
172
- const char * str = buf_str(&p->buf);
358
+ const char *str = buf_str(&p->buf);
173
359
  size_t len = buf_len(&p->buf);
174
360
 
175
361
  if (d->cache_str < len) {
@@ -180,6 +366,20 @@ static void add_str_key(ojParser p) {
180
366
  rb_funcall(d->handler, oj_add_value_id, 2, rstr, get_key(p));
181
367
  }
182
368
 
369
+ static void add_str_key_loc(ojParser p) {
370
+ Delegate d = (Delegate)p->ctx;
371
+ volatile VALUE rstr;
372
+ const char *str = buf_str(&p->buf);
373
+ size_t len = buf_len(&p->buf);
374
+
375
+ if (d->cache_str < len) {
376
+ rstr = cache_intern(d->str_cache, str, len);
377
+ } else {
378
+ rstr = rb_utf8_str_new(str, len);
379
+ }
380
+ rb_funcall(d->handler, oj_add_value_id, 4, rstr, get_key(p), LONG2FIX(p->line), LONG2FIX(p->cur - p->col));
381
+ }
382
+
183
383
  static void reset(ojParser p) {
184
384
  Funcs end = p->funcs + 3;
185
385
  Funcs f;
@@ -210,53 +410,107 @@ static VALUE option(ojParser p, const char *key, VALUE value) {
210
410
  d->handler = value;
211
411
  reset(p);
212
412
  if (rb_respond_to(value, oj_hash_start_id)) {
213
- p->funcs[TOP_FUN].open_object = open_object;
214
- p->funcs[ARRAY_FUN].open_object = open_object;
215
- p->funcs[OBJECT_FUN].open_object = open_object_key;
413
+ if (1 == rb_obj_method_arity(value, oj_hash_start_id)) {
414
+ p->funcs[TOP_FUN].open_object = open_object;
415
+ p->funcs[ARRAY_FUN].open_object = open_object;
416
+ p->funcs[OBJECT_FUN].open_object = open_object_key;
417
+ } else {
418
+ p->funcs[TOP_FUN].open_object = open_object_loc;
419
+ p->funcs[ARRAY_FUN].open_object = open_object_loc;
420
+ p->funcs[OBJECT_FUN].open_object = open_object_loc_key;
421
+ }
216
422
  }
217
423
  if (rb_respond_to(value, oj_array_start_id)) {
218
- p->funcs[TOP_FUN].open_array = open_array;
219
- p->funcs[ARRAY_FUN].open_array = open_array;
220
- p->funcs[OBJECT_FUN].open_array = open_array_key;
424
+ if (1 == rb_obj_method_arity(value, oj_array_start_id)) {
425
+ p->funcs[TOP_FUN].open_array = open_array;
426
+ p->funcs[ARRAY_FUN].open_array = open_array;
427
+ p->funcs[OBJECT_FUN].open_array = open_array_key;
428
+ } else {
429
+ p->funcs[TOP_FUN].open_array = open_array_loc;
430
+ p->funcs[ARRAY_FUN].open_array = open_array_loc;
431
+ p->funcs[OBJECT_FUN].open_array = open_array_loc_key;
432
+ }
221
433
  }
222
434
  if (rb_respond_to(value, oj_hash_end_id)) {
223
- p->funcs[TOP_FUN].close_object = close_object;
224
- p->funcs[ARRAY_FUN].close_object = close_object;
225
- p->funcs[OBJECT_FUN].close_object = close_object;
435
+ if (1 == rb_obj_method_arity(value, oj_hash_end_id)) {
436
+ p->funcs[TOP_FUN].close_object = close_object;
437
+ p->funcs[ARRAY_FUN].close_object = close_object;
438
+ p->funcs[OBJECT_FUN].close_object = close_object;
439
+ } else {
440
+ p->funcs[TOP_FUN].close_object = close_object_loc;
441
+ p->funcs[ARRAY_FUN].close_object = close_object_loc;
442
+ p->funcs[OBJECT_FUN].close_object = close_object_loc;
443
+ }
226
444
  }
227
445
  if (rb_respond_to(value, oj_array_end_id)) {
228
- p->funcs[TOP_FUN].close_array = close_array;
229
- p->funcs[ARRAY_FUN].close_array = close_array;
230
- p->funcs[OBJECT_FUN].close_array = close_array;
446
+ if (1 == rb_obj_method_arity(value, oj_array_end_id)) {
447
+ p->funcs[TOP_FUN].close_array = close_array;
448
+ p->funcs[ARRAY_FUN].close_array = close_array;
449
+ p->funcs[OBJECT_FUN].close_array = close_array;
450
+ } else {
451
+ p->funcs[TOP_FUN].close_array = close_array_loc;
452
+ p->funcs[ARRAY_FUN].close_array = close_array_loc;
453
+ p->funcs[OBJECT_FUN].close_array = close_array_loc;
454
+ }
231
455
  }
232
456
  if (rb_respond_to(value, oj_add_value_id)) {
233
- p->funcs[TOP_FUN].add_null = add_null;
234
- p->funcs[ARRAY_FUN].add_null = add_null;
235
- p->funcs[OBJECT_FUN].add_null = add_null_key;
236
-
237
- p->funcs[TOP_FUN].add_true = add_true;
238
- p->funcs[ARRAY_FUN].add_true = add_true;
239
- p->funcs[OBJECT_FUN].add_true = add_true_key;
240
-
241
- p->funcs[TOP_FUN].add_false = add_false;
242
- p->funcs[ARRAY_FUN].add_false = add_false;
243
- p->funcs[OBJECT_FUN].add_false = add_false_key;
244
-
245
- p->funcs[TOP_FUN].add_int = add_int;
246
- p->funcs[ARRAY_FUN].add_int = add_int;
247
- p->funcs[OBJECT_FUN].add_int = add_int_key;
248
-
249
- p->funcs[TOP_FUN].add_float = add_float;
250
- p->funcs[ARRAY_FUN].add_float = add_float;
251
- p->funcs[OBJECT_FUN].add_float = add_float_key;
252
-
253
- p->funcs[TOP_FUN].add_big = add_big;
254
- p->funcs[ARRAY_FUN].add_big = add_big;
255
- p->funcs[OBJECT_FUN].add_big = add_big_key;
256
-
257
- p->funcs[TOP_FUN].add_str = add_str;
258
- p->funcs[ARRAY_FUN].add_str = add_str;
259
- p->funcs[OBJECT_FUN].add_str = add_str_key;
457
+ if (2 == rb_obj_method_arity(value, oj_add_value_id)) {
458
+ p->funcs[TOP_FUN].add_null = add_null;
459
+ p->funcs[ARRAY_FUN].add_null = add_null;
460
+ p->funcs[OBJECT_FUN].add_null = add_null_key;
461
+
462
+ p->funcs[TOP_FUN].add_true = add_true;
463
+ p->funcs[ARRAY_FUN].add_true = add_true;
464
+ p->funcs[OBJECT_FUN].add_true = add_true_key;
465
+
466
+ p->funcs[TOP_FUN].add_false = add_false;
467
+ p->funcs[ARRAY_FUN].add_false = add_false;
468
+ p->funcs[OBJECT_FUN].add_false = add_false_key;
469
+
470
+ p->funcs[TOP_FUN].add_int = add_int;
471
+ p->funcs[ARRAY_FUN].add_int = add_int;
472
+ p->funcs[OBJECT_FUN].add_int = add_int_key;
473
+
474
+ p->funcs[TOP_FUN].add_float = add_float;
475
+ p->funcs[ARRAY_FUN].add_float = add_float;
476
+ p->funcs[OBJECT_FUN].add_float = add_float_key;
477
+
478
+ p->funcs[TOP_FUN].add_big = add_big;
479
+ p->funcs[ARRAY_FUN].add_big = add_big;
480
+ p->funcs[OBJECT_FUN].add_big = add_big_key;
481
+
482
+ p->funcs[TOP_FUN].add_str = add_str;
483
+ p->funcs[ARRAY_FUN].add_str = add_str;
484
+ p->funcs[OBJECT_FUN].add_str = add_str_key;
485
+ } else {
486
+ p->funcs[TOP_FUN].add_null = add_null_loc;
487
+ p->funcs[ARRAY_FUN].add_null = add_null_loc;
488
+ p->funcs[OBJECT_FUN].add_null = add_null_key_loc;
489
+
490
+ p->funcs[TOP_FUN].add_true = add_true_loc;
491
+ p->funcs[ARRAY_FUN].add_true = add_true_loc;
492
+ p->funcs[OBJECT_FUN].add_true = add_true_key_loc;
493
+
494
+ p->funcs[TOP_FUN].add_false = add_false_loc;
495
+ p->funcs[ARRAY_FUN].add_false = add_false_loc;
496
+ p->funcs[OBJECT_FUN].add_false = add_false_key_loc;
497
+
498
+ p->funcs[TOP_FUN].add_int = add_int_loc;
499
+ p->funcs[ARRAY_FUN].add_int = add_int_loc;
500
+ p->funcs[OBJECT_FUN].add_int = add_int_key_loc;
501
+
502
+ p->funcs[TOP_FUN].add_float = add_float_loc;
503
+ p->funcs[ARRAY_FUN].add_float = add_float_loc;
504
+ p->funcs[OBJECT_FUN].add_float = add_float_key_loc;
505
+
506
+ p->funcs[TOP_FUN].add_big = add_big_loc;
507
+ p->funcs[ARRAY_FUN].add_big = add_big_loc;
508
+ p->funcs[OBJECT_FUN].add_big = add_big_key_loc;
509
+
510
+ p->funcs[TOP_FUN].add_str = add_str_loc;
511
+ p->funcs[ARRAY_FUN].add_str = add_str_loc;
512
+ p->funcs[OBJECT_FUN].add_str = add_str_key_loc;
513
+ }
260
514
  }
261
515
  return Qnil;
262
516
  }
@@ -313,7 +567,7 @@ static void mark(ojParser p) {
313
567
  return;
314
568
  }
315
569
  Delegate d = (Delegate)p->ctx;
316
- VALUE *kp;
570
+ VALUE *kp;
317
571
 
318
572
  cache_mark(d->str_cache);
319
573
  if (Qnil != d->handler) {
data/ext/oj/strict.c CHANGED
@@ -50,13 +50,13 @@ VALUE oj_calc_hash_key(ParseInfo pi, Val parent) {
50
50
  }
51
51
 
52
52
  static void hash_end(ParseInfo pi) {
53
- if (Yes == pi->options.trace) {
53
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
54
54
  oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
55
55
  }
56
56
  }
57
57
 
58
58
  static void array_end(ParseInfo pi) {
59
- if (Yes == pi->options.trace) {
59
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
60
60
  oj_trace_parse_array_end(pi, __FILE__, __LINE__);
61
61
  }
62
62
  }
@@ -66,7 +66,7 @@ static VALUE noop_hash_key(ParseInfo pi, const char *key, size_t klen) {
66
66
  }
67
67
 
68
68
  static void add_value(ParseInfo pi, VALUE val) {
69
- if (Yes == pi->options.trace) {
69
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
70
70
  oj_trace_parse_call("add_value", pi, __FILE__, __LINE__, val);
71
71
  }
72
72
  pi->stack.head->val = val;
@@ -76,7 +76,7 @@ static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig
76
76
  volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
77
77
 
78
78
  pi->stack.head->val = rstr;
79
- if (Yes == pi->options.trace) {
79
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
80
80
  oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, rstr);
81
81
  }
82
82
  }
@@ -86,7 +86,7 @@ static void add_num(ParseInfo pi, NumInfo ni) {
86
86
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
87
87
  }
88
88
  pi->stack.head->val = oj_num_as_value(ni);
89
- if (Yes == pi->options.trace) {
89
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
90
90
  oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, pi->stack.head->val);
91
91
  }
92
92
  }
@@ -95,7 +95,7 @@ static VALUE start_hash(ParseInfo pi) {
95
95
  if (Qnil != pi->options.hash_class) {
96
96
  return rb_class_new_instance(0, NULL, pi->options.hash_class);
97
97
  }
98
- if (Yes == pi->options.trace) {
98
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
99
99
  oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
100
100
  }
101
101
  return rb_hash_new();
@@ -107,7 +107,7 @@ static void hash_set_cstr(ParseInfo pi, Val parent, const char *str, size_t len,
107
107
  rb_hash_aset(stack_peek(&pi->stack)->val,
108
108
  oj_calc_hash_key(pi, parent),
109
109
  rstr);
110
- if (Yes == pi->options.trace) {
110
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
111
111
  oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rstr);
112
112
  }
113
113
  }
@@ -122,7 +122,7 @@ static void hash_set_num(ParseInfo pi, Val parent, NumInfo ni) {
122
122
  rb_hash_aset(stack_peek(&pi->stack)->val,
123
123
  oj_calc_hash_key(pi, parent),
124
124
  v);
125
- if (Yes == pi->options.trace) {
125
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
126
126
  oj_trace_parse_call("set_number", pi, __FILE__, __LINE__, v);
127
127
  }
128
128
  }
@@ -131,13 +131,13 @@ static void hash_set_value(ParseInfo pi, Val parent, VALUE value) {
131
131
  rb_hash_aset(stack_peek(&pi->stack)->val,
132
132
  oj_calc_hash_key(pi, parent),
133
133
  value);
134
- if (Yes == pi->options.trace) {
134
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
135
135
  oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
136
136
  }
137
137
  }
138
138
 
139
139
  static VALUE start_array(ParseInfo pi) {
140
- if (Yes == pi->options.trace) {
140
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
141
141
  oj_trace_parse_in("start_array", pi, __FILE__, __LINE__);
142
142
  }
143
143
  return rb_ary_new();
@@ -147,7 +147,7 @@ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const c
147
147
  volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
148
148
 
149
149
  rb_ary_push(stack_peek(&pi->stack)->val, rstr);
150
- if (Yes == pi->options.trace) {
150
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
151
151
  oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rstr);
152
152
  }
153
153
  }
@@ -160,14 +160,14 @@ static void array_append_num(ParseInfo pi, NumInfo ni) {
160
160
  }
161
161
  v = oj_num_as_value(ni);
162
162
  rb_ary_push(stack_peek(&pi->stack)->val, v);
163
- if (Yes == pi->options.trace) {
163
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
164
164
  oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, v);
165
165
  }
166
166
  }
167
167
 
168
168
  static void array_append_value(ParseInfo pi, VALUE value) {
169
169
  rb_ary_push(stack_peek(&pi->stack)->val, value);
170
- if (Yes == pi->options.trace) {
170
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
171
171
  oj_trace_parse_call("append_value", pi, __FILE__, __LINE__, value);
172
172
  }
173
173
  }
data/ext/oj/wab.c CHANGED
@@ -312,13 +312,13 @@ static VALUE calc_hash_key(ParseInfo pi, Val parent) {
312
312
  }
313
313
 
314
314
  static void hash_end(ParseInfo pi) {
315
- if (Yes == pi->options.trace) {
315
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
316
316
  oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
317
317
  }
318
318
  }
319
319
 
320
320
  static void array_end(ParseInfo pi) {
321
- if (Yes == pi->options.trace) {
321
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
322
322
  oj_trace_parse_array_end(pi, __FILE__, __LINE__);
323
323
  }
324
324
  }
@@ -328,7 +328,7 @@ static VALUE noop_hash_key(ParseInfo pi, const char *key, size_t klen) {
328
328
  }
329
329
 
330
330
  static void add_value(ParseInfo pi, VALUE val) {
331
- if (Yes == pi->options.trace) {
331
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
332
332
  oj_trace_parse_call("add_value", pi, __FILE__, __LINE__, val);
333
333
  }
334
334
  pi->stack.head->val = val;
@@ -478,7 +478,7 @@ static VALUE cstr_to_rstr(ParseInfo pi, const char *str, size_t len) {
478
478
 
479
479
  static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
480
480
  pi->stack.head->val = cstr_to_rstr(pi, str, len);
481
- if (Yes == pi->options.trace) {
481
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
482
482
  oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, pi->stack.head->val);
483
483
  }
484
484
  }
@@ -488,13 +488,13 @@ static void add_num(ParseInfo pi, NumInfo ni) {
488
488
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
489
489
  }
490
490
  pi->stack.head->val = oj_num_as_value(ni);
491
- if (Yes == pi->options.trace) {
491
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
492
492
  oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, pi->stack.head->val);
493
493
  }
494
494
  }
495
495
 
496
496
  static VALUE start_hash(ParseInfo pi) {
497
- if (Yes == pi->options.trace) {
497
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
498
498
  oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
499
499
  }
500
500
  if (Qnil != pi->options.hash_class) {
@@ -507,7 +507,7 @@ static void hash_set_cstr(ParseInfo pi, Val parent, const char *str, size_t len,
507
507
  volatile VALUE rval = cstr_to_rstr(pi, str, len);
508
508
 
509
509
  rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), rval);
510
- if (Yes == pi->options.trace) {
510
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
511
511
  oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rval);
512
512
  }
513
513
  }
@@ -520,20 +520,20 @@ static void hash_set_num(ParseInfo pi, Val parent, NumInfo ni) {
520
520
  }
521
521
  rval = oj_num_as_value(ni);
522
522
  rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), rval);
523
- if (Yes == pi->options.trace) {
523
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
524
524
  oj_trace_parse_call("set_number", pi, __FILE__, __LINE__, rval);
525
525
  }
526
526
  }
527
527
 
528
528
  static void hash_set_value(ParseInfo pi, Val parent, VALUE value) {
529
529
  rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), value);
530
- if (Yes == pi->options.trace) {
530
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
531
531
  oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
532
532
  }
533
533
  }
534
534
 
535
535
  static VALUE start_array(ParseInfo pi) {
536
- if (Yes == pi->options.trace) {
536
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
537
537
  oj_trace_parse_in("start_array", pi, __FILE__, __LINE__);
538
538
  }
539
539
  return rb_ary_new();
@@ -543,7 +543,7 @@ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const c
543
543
  volatile VALUE rval = cstr_to_rstr(pi, str, len);
544
544
 
545
545
  rb_ary_push(stack_peek(&pi->stack)->val, rval);
546
- if (Yes == pi->options.trace) {
546
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
547
547
  oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, rval);
548
548
  }
549
549
  }
@@ -556,14 +556,14 @@ static void array_append_num(ParseInfo pi, NumInfo ni) {
556
556
  }
557
557
  rval = oj_num_as_value(ni);
558
558
  rb_ary_push(stack_peek(&pi->stack)->val, rval);
559
- if (Yes == pi->options.trace) {
559
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
560
560
  oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
561
561
  }
562
562
  }
563
563
 
564
564
  static void array_append_value(ParseInfo pi, VALUE value) {
565
565
  rb_ary_push(stack_peek(&pi->stack)->val, value);
566
- if (Yes == pi->options.trace) {
566
+ if (RB_UNLIKELY(Yes == pi->options.trace)) {
567
567
  oj_trace_parse_call("append_value", pi, __FILE__, __LINE__, value);
568
568
  }
569
569
  }
data/lib/oj/saj.rb CHANGED
@@ -1,11 +1,17 @@
1
1
  module Oj
2
- # A SAX style parse handler for JSON hence the acronym SAJ for Simple API for
3
- # JSON. The Oj::Saj handler class should be subclassed and then used with the
4
- # Oj::Saj key_parse() method. The Saj methods will then be called as the file
5
- # is parsed.
2
+ # A SAX style parse handler for JSON hence the acronym SAJ for Simple API
3
+ # for JSON. The Oj::Saj handler class can be subclassed and then used with
4
+ # the Oj::Saj key_parse() method or with the more resent
5
+ # Oj::Parser.new(:saj). The Saj methods will then be called as the file is
6
+ # parsed.
7
+ #
8
+ # With Oj::Parser.new(:saj) each method can also include a line and column
9
+ # argument so hash_start(key) could also be hash_start(key, line,
10
+ # column). The error() method is no used with Oj::Parser.new(:saj) so it
11
+ # will never be called.
6
12
  #
7
13
  # @example
8
- #
14
+ #
9
15
  # require 'oj'
10
16
  #
11
17
  # class MySaj < ::Oj::Saj
@@ -23,6 +29,14 @@ module Oj
23
29
  # Oj.saj_parse(cnt, f)
24
30
  # end
25
31
  #
32
+ # or
33
+ #
34
+ # p = Oj::Parser.new(:saj)
35
+ # p.handler = MySaj.new()
36
+ # File.open('any.json', 'r') do |f|
37
+ # p.parse(f.read)
38
+ # end
39
+ #
26
40
  # To make the desired methods active while parsing the desired method should
27
41
  # be made public in the subclasses. If the methods remain private they will
28
42
  # not be called during parsing.
@@ -61,6 +75,6 @@ module Oj
61
75
 
62
76
  def error(message, line, column)
63
77
  end
64
-
78
+
65
79
  end # Saj
66
80
  end # Oj
data/lib/oj/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Oj
3
3
  # Current version of the module.
4
- VERSION = '3.13.15'
4
+ VERSION = '3.13.16'
5
5
  end
@@ -5,7 +5,7 @@ $: << File.dirname(__FILE__)
5
5
 
6
6
  require 'helper'
7
7
 
8
- $json = %{{
8
+ $json = %|{
9
9
  "array": [
10
10
  {
11
11
  "num" : 3,
@@ -18,7 +18,7 @@ $json = %{{
18
18
  }
19
19
  ],
20
20
  "boolean" : true
21
- }}
21
+ }|
22
22
 
23
23
  class AllSaj < Oj::Saj
24
24
  attr_accessor :calls
@@ -53,6 +53,35 @@ class AllSaj < Oj::Saj
53
53
 
54
54
  end # AllSaj
55
55
 
56
+ class LocSaj
57
+ attr_accessor :calls
58
+
59
+ def initialize()
60
+ @calls = []
61
+ end
62
+
63
+ def hash_start(key, line, column)
64
+ @calls << [:hash_start, key, line, column]
65
+ end
66
+
67
+ def hash_end(key, line, column)
68
+ @calls << [:hash_end, key, line, column]
69
+ end
70
+
71
+ def array_start(key, line, column)
72
+ @calls << [:array_start, key, line, column]
73
+ end
74
+
75
+ def array_end(key, line, column)
76
+ @calls << [:array_end, key, line, column]
77
+ end
78
+
79
+ def add_value(value, key, line, column)
80
+ @calls << [:add_value, value, key, line, column]
81
+ end
82
+
83
+ end # LocSaj
84
+
56
85
  class SajTest < Minitest::Test
57
86
 
58
87
  def test_nil
@@ -242,4 +271,28 @@ class SajTest < Minitest::Test
242
271
  ], handler.calls)
243
272
  end
244
273
 
274
+ def test_loc
275
+ handler = LocSaj.new()
276
+ Oj::Parser.saj.handler = handler
277
+ Oj::Parser.saj.parse($json)
278
+ assert_equal([[:hash_start, nil, 1, 1],
279
+ [:array_start, 'array', 2, 12],
280
+ [:hash_start, nil, 3, 5],
281
+ [:add_value, 3, 'num', 4, 18],
282
+ [:add_value, 'message', 'string', 5, 25],
283
+ [:hash_start, 'hash', 6, 17],
284
+ [:hash_start, 'h2', 7, 17],
285
+ [:array_start, 'a', 8, 17],
286
+ [:add_value, 1, nil, 8, 20],
287
+ [:add_value, 2, nil, 8, 23],
288
+ [:add_value, 3, nil, 8, 26],
289
+ [:array_end, 'a', 8, 27],
290
+ [:hash_end, 'h2', 9, 9],
291
+ [:hash_end, 'hash', 10, 7],
292
+ [:hash_end, nil, 11, 5],
293
+ [:array_end, 'array', 12, 3],
294
+ [:add_value, true, 'boolean', 13, 18],
295
+ [:hash_end, nil, 14, 1]], handler.calls)
296
+ end
297
+
245
298
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oj
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.13.15
4
+ version: 3.13.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Ohler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-07-03 00:00:00.000000000 Z
11
+ date: 2022-07-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler