oj 3.13.15 → 3.13.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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