oj 3.4.0 → 3.5.0

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
- SHA1:
3
- metadata.gz: 9badf52195a57cbb014c118468e251a6410492be
4
- data.tar.gz: 8cf51afa4ee58bbb314625d6b4e4c91c69c1f816
2
+ SHA256:
3
+ metadata.gz: 30b24a6a60285c820a9e10671a976043a9163c2e98a3c07ba16af43ad88b8e6f
4
+ data.tar.gz: 90fc1a46d76296f2e226434a26b6acc0cbe16fa378173ea98700b2250ecf45ca
5
5
  SHA512:
6
- metadata.gz: 3366cc54755af4f3d8abbded2afac3b1235a4fe25315964d6d1225c69e849611eecedb2e7d893e14b72514bcc0115b1a2cce94bc007f0e8460230798d1531276
7
- data.tar.gz: 02d082acfd67708b44582a8fe69e10a5f639cc56ec57484c56c283be96ffc4d64b0a41b4c31bac2f707225388b2f5cd2551c9e6aba048c4c973e6c6461a462a8
6
+ metadata.gz: 71d7f8f0c32e3183a9f228764ffacdbd94cac6497e4af07e3ede247a676b2abd3815b3c51228992429a400a0ef879b8f54a8767cfa8b3a573a9931b46ec785e0
7
+ data.tar.gz: ce7fb5fa634fd8122173712faed5435bee5ec3477445d969f3a16f62ac6703dae9fee0f0476cbbfdc8852ba4a7243753d543e44f61eb286489b7a700e0e0dde5
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # [![{}j](http://www.ohler.com/dev/images/oj_comet_64.svg)](http://www.ohler.com/oj) gem
2
2
 
3
- [![Build Status](https://img.shields.io/travis/ohler55/oj/master.svg)](http://travis-ci.org/ohler55/oj?branch=master) [![AppVeyor](https://img.shields.io/appveyor/ci/ohler55/oj/master.svg)](https://ci.appveyor.com/project/ohler55/oj) ![Gem](https://img.shields.io/gem/v/oj.svg) ![Gem](https://img.shields.io/gem/dt/oj.svg) [![Gratipay](https://img.shields.io/gratipay/project/oj.svg)](https://gratipay.com/oj/)
3
+ [![Build Status](https://img.shields.io/travis/ohler55/oj/master.svg)](http://travis-ci.org/ohler55/oj?branch=master) [![AppVeyor](https://img.shields.io/appveyor/ci/ohler55/oj/master.svg)](https://ci.appveyor.com/project/ohler55/oj) ![Gem](https://img.shields.io/gem/v/oj.svg) ![Gem](https://img.shields.io/gem/dt/oj.svg)
4
4
 
5
5
  A *fast* JSON parser and Object marshaller as a Ruby gem.
6
6
 
@@ -11,6 +11,7 @@
11
11
  #include "resolve.h"
12
12
  #include "hash.h"
13
13
  #include "encode.h"
14
+ #include "trace.h"
14
15
 
15
16
  static void
16
17
  hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *orig) {
@@ -55,6 +56,9 @@ hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *o
55
56
  } else {
56
57
  rb_hash_aset(parent->val, rkey, rstr);
57
58
  }
59
+ if (Yes == pi->options.trace) {
60
+ oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rstr);
61
+ }
58
62
  }
59
63
  }
60
64
 
@@ -67,6 +71,9 @@ start_hash(ParseInfo pi) {
67
71
  } else {
68
72
  h = rb_hash_new();
69
73
  }
74
+ if (Yes == pi->options.trace) {
75
+ oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
76
+ }
70
77
  return h;
71
78
  }
72
79
 
@@ -90,6 +97,9 @@ end_hash(struct _ParseInfo *pi) {
90
97
  parent->classname = 0;
91
98
  }
92
99
  }
100
+ if (Yes == pi->options.trace) {
101
+ oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
102
+ }
93
103
  }
94
104
 
95
105
  static VALUE
@@ -120,23 +130,34 @@ add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
120
130
  }
121
131
  }
122
132
  pi->stack.head->val = rstr;
133
+ if (Yes == pi->options.trace) {
134
+ oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, rstr);
135
+ }
123
136
  }
124
137
 
125
138
  static void
126
139
  add_num(ParseInfo pi, NumInfo ni) {
127
140
  pi->stack.head->val = oj_num_as_value(ni);
141
+ if (Yes == pi->options.trace) {
142
+ oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, pi->stack.head->val);
143
+ }
128
144
  }
129
145
 
130
146
  static void
131
147
  hash_set_num(struct _ParseInfo *pi, Val parent, NumInfo ni) {
148
+ volatile VALUE rval = oj_num_as_value(ni);
149
+
132
150
  if (!oj_use_hash_alt && rb_cHash != rb_obj_class(parent->val)) {
133
151
  // The rb_hash_set would still work but the unit tests for the
134
152
  // json gem require the less efficient []= method be called to set
135
153
  // values. Even using the store method to set the values will fail
136
154
  // the unit tests.
137
- rb_funcall(stack_peek(&pi->stack)->val, rb_intern("[]="), 2, calc_hash_key(pi, parent), oj_num_as_value(ni));
155
+ rb_funcall(stack_peek(&pi->stack)->val, rb_intern("[]="), 2, calc_hash_key(pi, parent), rval);
138
156
  } else {
139
- rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), oj_num_as_value(ni));
157
+ rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), rval);
158
+ }
159
+ if (Yes == pi->options.trace) {
160
+ oj_trace_parse_call("set_number", pi, __FILE__, __LINE__, rval);
140
161
  }
141
162
  }
142
163
 
@@ -151,6 +172,9 @@ hash_set_value(ParseInfo pi, Val parent, VALUE value) {
151
172
  } else {
152
173
  rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), value);
153
174
  }
175
+ if (Yes == pi->options.trace) {
176
+ oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
177
+ }
154
178
  }
155
179
 
156
180
  static VALUE
@@ -158,20 +182,27 @@ start_array(ParseInfo pi) {
158
182
  if (Qnil != pi->options.array_class) {
159
183
  return rb_class_new_instance(0, NULL, pi->options.array_class);
160
184
  }
185
+ if (Yes == pi->options.trace) {
186
+ oj_trace_parse_in("start_array", pi, __FILE__, __LINE__);
187
+ }
161
188
  return rb_ary_new();
162
189
  }
163
190
 
164
191
  static void
165
192
  array_append_num(ParseInfo pi, NumInfo ni) {
166
- Val parent = stack_peek(&pi->stack);
193
+ Val parent = stack_peek(&pi->stack);
194
+ volatile VALUE rval = oj_num_as_value(ni);
167
195
 
168
196
  if (!oj_use_array_alt && rb_cArray != rb_obj_class(parent->val)) {
169
197
  // The rb_ary_push would still work but the unit tests for the json
170
198
  // gem require the less efficient << method be called to push the
171
199
  // values.
172
- rb_funcall(parent->val, rb_intern("<<"), 1, oj_num_as_value(ni));
200
+ rb_funcall(parent->val, rb_intern("<<"), 1, rval);
173
201
  } else {
174
- rb_ary_push(parent->val, oj_num_as_value(ni));
202
+ rb_ary_push(parent->val, rval);
203
+ }
204
+ if (Yes == pi->options.trace) {
205
+ oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
175
206
  }
176
207
  }
177
208
 
@@ -189,6 +220,9 @@ array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
189
220
  }
190
221
  }
191
222
  rb_ary_push(stack_peek(&pi->stack)->val, rstr);
223
+ if (Yes == pi->options.trace) {
224
+ oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rstr);
225
+ }
192
226
  }
193
227
 
194
228
  void
@@ -14,6 +14,7 @@
14
14
  #include "oj.h"
15
15
  #include "parse.h"
16
16
  #include "resolve.h"
17
+ #include "trace.h"
17
18
 
18
19
  extern void oj_set_obj_ivar(Val parent, Val kval, VALUE value);
19
20
  extern VALUE oj_parse_xml_time(const char *str, int len); // from object.c
@@ -874,6 +875,9 @@ void
874
875
  oj_dump_custom_val(VALUE obj, int depth, Out out, bool as_ok) {
875
876
  int type = rb_type(obj);
876
877
 
878
+ if (Yes == out->opts->trace) {
879
+ oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
880
+ }
877
881
  if (MAX_DEPTH < depth) {
878
882
  rb_raise(rb_eNoMemError, "Too deeply nested.\n");
879
883
  }
@@ -882,10 +886,16 @@ oj_dump_custom_val(VALUE obj, int depth, Out out, bool as_ok) {
882
886
 
883
887
  if (NULL != f) {
884
888
  f(obj, depth, out, true);
889
+ if (Yes == out->opts->trace) {
890
+ oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
891
+ }
885
892
  return;
886
893
  }
887
894
  }
888
895
  oj_dump_nil(Qnil, depth, out, false);
896
+ if (Yes == out->opts->trace) {
897
+ oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
898
+ }
889
899
  }
890
900
 
891
901
  ///// load functions /////
@@ -946,6 +956,9 @@ hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *o
946
956
  default:
947
957
  break;
948
958
  }
959
+ if (Yes == pi->options.trace) {
960
+ oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rstr);
961
+ }
949
962
  }
950
963
  }
951
964
 
@@ -963,6 +976,9 @@ end_hash(struct _ParseInfo *pi) {
963
976
  }
964
977
  parent->clas = Qundef;
965
978
  }
979
+ if (Yes == pi->options.trace) {
980
+ oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
981
+ }
966
982
  }
967
983
 
968
984
  static VALUE
@@ -981,11 +997,12 @@ calc_hash_key(ParseInfo pi, Val parent) {
981
997
 
982
998
  static void
983
999
  hash_set_num(struct _ParseInfo *pi, Val kval, NumInfo ni) {
984
- Val parent = stack_peek(&pi->stack);
1000
+ Val parent = stack_peek(&pi->stack);
1001
+ volatile VALUE rval = oj_num_as_value(ni);
985
1002
 
986
1003
  switch (rb_type(parent->val)) {
987
1004
  case T_OBJECT:
988
- oj_set_obj_ivar(parent, kval, oj_num_as_value(ni));
1005
+ oj_set_obj_ivar(parent, kval, rval);
989
1006
  break;
990
1007
  case T_HASH:
991
1008
  if (4 == parent->klen && NULL != parent->key && rb_cTime == parent->clas && 0 == strncmp("time", parent->key, 4)) {
@@ -1001,7 +1018,7 @@ hash_set_num(struct _ParseInfo *pi, Val kval, NumInfo ni) {
1001
1018
  if (86400 == ni->exp) { // UTC time
1002
1019
  parent->val = rb_time_nano_new(ni->i, (long)nsec);
1003
1020
  // Since the ruby C routines alway create local time, the
1004
- // offset and then a convertion to UTC keeps makes the time
1021
+ // offset and then a conversion to UTC keeps makes the time
1005
1022
  // match the expected value.
1006
1023
  parent->val = rb_funcall2(parent->val, oj_utc_id, 0, 0);
1007
1024
  } else if (ni->hasExp) {
@@ -1020,13 +1037,17 @@ hash_set_num(struct _ParseInfo *pi, Val kval, NumInfo ni) {
1020
1037
  } else {
1021
1038
  parent->val = rb_time_nano_new(ni->i, (long)nsec);
1022
1039
  }
1040
+ rval = parent->val;
1023
1041
  } else {
1024
- rb_hash_aset(parent->val, calc_hash_key(pi, kval), oj_num_as_value(ni));
1042
+ rb_hash_aset(parent->val, calc_hash_key(pi, kval), rval);
1025
1043
  }
1026
1044
  break;
1027
1045
  default:
1028
1046
  break;
1029
1047
  }
1048
+ if (Yes == pi->options.trace) {
1049
+ oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rval);
1050
+ }
1030
1051
  }
1031
1052
 
1032
1053
  static void
@@ -1043,13 +1064,20 @@ hash_set_value(ParseInfo pi, Val kval, VALUE value) {
1043
1064
  default:
1044
1065
  break;
1045
1066
  }
1067
+ if (Yes == pi->options.trace) {
1068
+ oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
1069
+ }
1046
1070
  }
1047
1071
 
1048
1072
  static void
1049
1073
  array_append_num(ParseInfo pi, NumInfo ni) {
1050
- Val parent = stack_peek(&pi->stack);
1074
+ Val parent = stack_peek(&pi->stack);
1075
+ volatile VALUE rval = oj_num_as_value(ni);
1051
1076
 
1052
- rb_ary_push(parent->val, oj_num_as_value(ni));
1077
+ rb_ary_push(parent->val, rval);
1078
+ if (Yes == pi->options.trace) {
1079
+ oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
1080
+ }
1053
1081
  }
1054
1082
 
1055
1083
  static void
@@ -1066,6 +1094,9 @@ array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
1066
1094
  }
1067
1095
  }
1068
1096
  rb_ary_push(stack_peek(&pi->stack)->val, rstr);
1097
+ if (Yes == pi->options.trace) {
1098
+ oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rstr);
1099
+ }
1069
1100
  }
1070
1101
 
1071
1102
  void
@@ -6,6 +6,7 @@
6
6
  #include "code.h"
7
7
  #include "dump.h"
8
8
  #include "rails.h"
9
+ #include "trace.h"
9
10
 
10
11
  // Workaround in case INFINITY is not defined in math.h or if the OS is CentOS
11
12
  #define OJ_INFINITY (1.0/0.0)
@@ -901,7 +902,10 @@ set_state_depth(VALUE state, int depth) {
901
902
  void
902
903
  oj_dump_compat_val(VALUE obj, int depth, Out out, bool as_ok) {
903
904
  int type = rb_type(obj);
904
-
905
+
906
+ if (Yes == out->opts->trace) {
907
+ oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
908
+ }
905
909
  if (out->opts->dump_opts.max_depth <= depth) {
906
910
  // When JSON.dump is called then an ArgumentError is expected and the
907
911
  // limit is the depth inclusive. If JSON.generate is called then a
@@ -924,8 +928,14 @@ oj_dump_compat_val(VALUE obj, int depth, Out out, bool as_ok) {
924
928
 
925
929
  if (NULL != f) {
926
930
  f(obj, depth, out, as_ok);
931
+ if (Yes == out->opts->trace) {
932
+ oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
933
+ }
927
934
  return;
928
935
  }
929
936
  }
930
937
  oj_dump_nil(Qnil, depth, out, false);
938
+ if (Yes == out->opts->trace) {
939
+ oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
940
+ }
931
941
  }
@@ -5,6 +5,7 @@
5
5
 
6
6
  #include "dump.h"
7
7
  #include "odd.h"
8
+ #include "trace.h"
8
9
 
9
10
  static const char hex_chars[17] = "0123456789abcdef";
10
11
 
@@ -816,6 +817,9 @@ void
816
817
  oj_dump_obj_val(VALUE obj, int depth, Out out) {
817
818
  int type = rb_type(obj);
818
819
 
820
+ if (Yes == out->opts->trace) {
821
+ oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
822
+ }
819
823
  if (MAX_DEPTH < depth) {
820
824
  rb_raise(rb_eNoMemError, "Too deeply nested.\n");
821
825
  }
@@ -824,8 +828,14 @@ oj_dump_obj_val(VALUE obj, int depth, Out out) {
824
828
 
825
829
  if (NULL != f) {
826
830
  f(obj, depth, out, false);
831
+ if (Yes == out->opts->trace) {
832
+ oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
833
+ }
827
834
  return;
828
835
  }
829
836
  }
830
837
  oj_dump_nil(Qnil, depth, out, false);
838
+ if (Yes == out->opts->trace) {
839
+ oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
840
+ }
831
841
  }
@@ -12,6 +12,7 @@
12
12
  #include <errno.h>
13
13
 
14
14
  #include "dump.h"
15
+ #include "trace.h"
15
16
 
16
17
  #if !HAS_ENCODING_SUPPORT || defined(RUBINIUS_RUBY)
17
18
  #define rb_eEncodingError rb_eException
@@ -366,6 +367,9 @@ void
366
367
  oj_dump_strict_val(VALUE obj, int depth, Out out) {
367
368
  int type = rb_type(obj);
368
369
 
370
+ if (Yes == out->opts->trace) {
371
+ oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
372
+ }
369
373
  if (MAX_DEPTH < depth) {
370
374
  rb_raise(rb_eNoMemError, "Too deeply nested.\n");
371
375
  }
@@ -374,6 +378,9 @@ oj_dump_strict_val(VALUE obj, int depth, Out out) {
374
378
 
375
379
  if (NULL != f) {
376
380
  f(obj, depth, out, false);
381
+ if (Yes == out->opts->trace) {
382
+ oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
383
+ }
377
384
  return;
378
385
  }
379
386
  }
@@ -409,6 +416,9 @@ void
409
416
  oj_dump_null_val(VALUE obj, int depth, Out out) {
410
417
  int type = rb_type(obj);
411
418
 
419
+ if (Yes == out->opts->trace) {
420
+ oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
421
+ }
412
422
  if (MAX_DEPTH < depth) {
413
423
  rb_raise(rb_eNoMemError, "Too deeply nested.\n");
414
424
  }
@@ -417,8 +427,14 @@ oj_dump_null_val(VALUE obj, int depth, Out out) {
417
427
 
418
428
  if (NULL != f) {
419
429
  f(obj, depth, out, false);
430
+ if (Yes == out->opts->trace) {
431
+ oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
432
+ }
420
433
  return;
421
434
  }
422
435
  }
423
436
  oj_dump_nil(Qnil, depth, out, false);
437
+ if (Yes == out->opts->trace) {
438
+ oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
439
+ }
424
440
  }
@@ -44,13 +44,13 @@ static VALUE state_class;
44
44
  /* Document-method: parser=
45
45
  * call-seq: parser=(parser)
46
46
  *
47
- * Does nothing other than provide compatibiltiy.
47
+ * Does nothing other than provide compatibility.
48
48
  * - *parser* [_Object_] ignored
49
49
  */
50
50
  /* Document-method: generator=
51
51
  * call-seq: generator=(generator)
52
52
  *
53
- * Does nothing other than provide compatibiltiy.
53
+ * Does nothing other than provide compatibility.
54
54
  * - *generator* [_Object_] ignored
55
55
  */
56
56
 
@@ -606,7 +606,7 @@ mimic_parse_bang(int argc, VALUE *argv, VALUE self) {
606
606
  /* Document-method: recurse_proc
607
607
  * call-seq: recurse_proc(obj, &proc)
608
608
  *
609
- * Yields to the proc for every element in the obj recursivly.
609
+ * Yields to the proc for every element in the obj recursively.
610
610
  *
611
611
  * - *obj* [_Hash_|Array] object to walk
612
612
  * - *proc* [_Proc_] to yield to on each element
@@ -684,6 +684,7 @@ static struct _Options mimic_object_to_json_options = {
684
684
  No, // allow_invalid
685
685
  No, // create_ok
686
686
  No, // allow_nan
687
+ No, // trace
687
688
  oj_json_class,// create_id
688
689
  10, // create_id_len
689
690
  3, // sec_prec
@@ -13,6 +13,7 @@
13
13
  #include "hash.h"
14
14
  #include "odd.h"
15
15
  #include "encode.h"
16
+ #include "trace.h"
16
17
 
17
18
  inline static long
18
19
  read_long(const char *str, size_t len) {
@@ -286,7 +287,7 @@ hat_num(ParseInfo pi, Val parent, Val kval, NumInfo ni) {
286
287
  if (86400 == ni->exp) { // UTC time
287
288
  parent->val = rb_time_nano_new(ni->i, (long)nsec);
288
289
  // Since the ruby C routines alway create local time, the
289
- // offset and then a convertion to UTC keeps makes the time
290
+ // offset and then a conversion to UTC keeps makes the time
290
291
  // match the expected value.
291
292
  parent->val = rb_funcall2(parent->val, oj_utc_id, 0, 0);
292
293
  } else if (ni->hasExp) {
@@ -482,9 +483,10 @@ oj_set_obj_ivar(Val parent, Val kval, VALUE value) {
482
483
 
483
484
  static void
484
485
  hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *orig) {
485
- const char *key = kval->key;
486
- int klen = kval->klen;
487
- Val parent = stack_peek(&pi->stack);
486
+ const char *key = kval->key;
487
+ int klen = kval->klen;
488
+ Val parent = stack_peek(&pi->stack);
489
+ volatile VALUE rval = Qnil;
488
490
 
489
491
  WHICH_TYPE:
490
492
  switch (rb_type(parent->val)) {
@@ -499,41 +501,50 @@ hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *o
499
501
  rb_hash_aset(parent->val, calc_hash_key(pi, kval, parent->k1), str_to_value(pi, str, len, orig));
500
502
  break;
501
503
  case T_STRING:
504
+ rval = str_to_value(pi, str, len, orig);
502
505
  if (4 == klen && 's' == *key && 'e' == key[1] && 'l' == key[2] && 'f' == key[3]) {
503
- rb_funcall(parent->val, oj_replace_id, 1, str_to_value(pi, str, len, orig));
506
+ rb_funcall(parent->val, oj_replace_id, 1, rval);
504
507
  } else {
505
- oj_set_obj_ivar(parent, kval, str_to_value(pi, str, len, orig));
508
+ oj_set_obj_ivar(parent, kval, rval);
506
509
  }
507
510
  break;
508
511
  case T_OBJECT:
509
- oj_set_obj_ivar(parent, kval, str_to_value(pi, str, len, orig));
512
+ rval = str_to_value(pi, str, len, orig);
513
+ oj_set_obj_ivar(parent, kval, rval);
510
514
  break;
511
515
  case T_CLASS:
512
516
  if (0 == parent->odd_args) {
513
517
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "%s is not an odd class", rb_class2name(rb_obj_class(parent->val)));
514
518
  return;
515
- } else if (0 != oj_odd_set_arg(parent->odd_args, kval->key, kval->klen, str_to_value(pi, str, len, orig))) {
516
- char buf[256];
519
+ } else {
520
+ rval = str_to_value(pi, str, len, orig);
521
+ if (0 != oj_odd_set_arg(parent->odd_args, kval->key, kval->klen, rval)) {
522
+ char buf[256];
517
523
 
518
- if ((int)sizeof(buf) - 1 <= klen) {
519
- klen = sizeof(buf) - 2;
524
+ if ((int)sizeof(buf) - 1 <= klen) {
525
+ klen = sizeof(buf) - 2;
526
+ }
527
+ memcpy(buf, key, klen);
528
+ buf[klen] = '\0';
529
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "%s is not an attribute of %s", buf, rb_class2name(rb_obj_class(parent->val)));
520
530
  }
521
- memcpy(buf, key, klen);
522
- buf[klen] = '\0';
523
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "%s is not an attribute of %s", buf, rb_class2name(rb_obj_class(parent->val)));
524
531
  }
525
532
  break;
526
533
  default:
527
534
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "can not add attributes to a %s", rb_class2name(rb_obj_class(parent->val)));
528
535
  return;
529
536
  }
537
+ if (Yes == pi->options.trace) {
538
+ oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rval);
539
+ }
530
540
  }
531
541
 
532
542
  static void
533
543
  hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
534
- const char *key = kval->key;
535
- int klen = kval->klen;
536
- Val parent = stack_peek(&pi->stack);
544
+ const char *key = kval->key;
545
+ int klen = kval->klen;
546
+ Val parent = stack_peek(&pi->stack);
547
+ volatile VALUE rval = Qnil;
537
548
 
538
549
  WHICH_TYPE:
539
550
  switch (rb_type(parent->val)) {
@@ -545,35 +556,43 @@ hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
545
556
  }
546
557
  break;
547
558
  case T_HASH:
548
- rb_hash_aset(parent->val, calc_hash_key(pi, kval, parent->k1), oj_num_as_value(ni));
559
+ rval = oj_num_as_value(ni);
560
+ rb_hash_aset(parent->val, calc_hash_key(pi, kval, parent->k1), rval);
549
561
  break;
550
562
  case T_OBJECT:
551
563
  if (2 == klen && '^' == *key && 'i' == key[1] &&
552
564
  !ni->infinity && !ni->neg && 1 == ni->div && 0 == ni->exp && 0 != pi->circ_array) { // fixnum
553
565
  oj_circ_array_set(pi->circ_array, parent->val, ni->i);
554
566
  } else {
555
- oj_set_obj_ivar(parent, kval, oj_num_as_value(ni));
567
+ rval = oj_num_as_value(ni);
568
+ oj_set_obj_ivar(parent, kval, rval);
556
569
  }
557
570
  break;
558
571
  case T_CLASS:
559
572
  if (0 == parent->odd_args) {
560
573
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "%s is not an odd class", rb_class2name(rb_obj_class(parent->val)));
561
574
  return;
562
- } else if (0 != oj_odd_set_arg(parent->odd_args, key, klen, oj_num_as_value(ni))) {
563
- char buf[256];
575
+ } else {
576
+ rval = oj_num_as_value(ni);
577
+ if (0 != oj_odd_set_arg(parent->odd_args, key, klen, rval)) {
578
+ char buf[256];
564
579
 
565
- if ((int)sizeof(buf) - 1 <= klen) {
566
- klen = sizeof(buf) - 2;
580
+ if ((int)sizeof(buf) - 1 <= klen) {
581
+ klen = sizeof(buf) - 2;
582
+ }
583
+ memcpy(buf, key, klen);
584
+ buf[klen] = '\0';
585
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "%s is not an attribute of %s", buf, rb_class2name(rb_obj_class(parent->val)));
567
586
  }
568
- memcpy(buf, key, klen);
569
- buf[klen] = '\0';
570
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "%s is not an attribute of %s", buf, rb_class2name(rb_obj_class(parent->val)));
571
587
  }
572
588
  break;
573
589
  default:
574
590
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "can not add attributes to a %s", rb_class2name(rb_obj_class(parent->val)));
575
591
  return;
576
592
  }
593
+ if (Yes == pi->options.trace) {
594
+ oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, rval);
595
+ }
577
596
  }
578
597
 
579
598
  static void
@@ -644,10 +663,16 @@ hash_set_value(ParseInfo pi, Val kval, VALUE value) {
644
663
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "can not add attributes to a %s", rb_class2name(rb_obj_class(parent->val)));
645
664
  return;
646
665
  }
666
+ if (Yes == pi->options.trace) {
667
+ oj_trace_parse_call("add_value", pi, __FILE__, __LINE__, value);
668
+ }
647
669
  }
648
670
 
649
671
  static VALUE
650
672
  start_hash(ParseInfo pi) {
673
+ if (Yes == pi->options.trace) {
674
+ oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
675
+ }
651
676
  return Qnil;
652
677
  }
653
678
 
@@ -664,10 +689,15 @@ end_hash(struct _ParseInfo *pi) {
664
689
  oj_odd_free(oa);
665
690
  parent->odd_args = 0;
666
691
  }
692
+ if (Yes == pi->options.trace) {
693
+ oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
694
+ }
667
695
  }
668
696
 
669
697
  static void
670
698
  array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
699
+ volatile VALUE rval = Qnil;
700
+
671
701
  if (3 <= len && 0 != pi->circ_array) {
672
702
  if ('i' == str[1]) {
673
703
  long i = read_long(str + 2, len - 2);
@@ -686,22 +716,37 @@ array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
686
716
 
687
717
  }
688
718
  }
689
- rb_ary_push(stack_peek(&pi->stack)->val, str_to_value(pi, str, len, orig));
719
+ rval = str_to_value(pi, str, len, orig);
720
+ rb_ary_push(stack_peek(&pi->stack)->val, rval);
721
+ if (Yes == pi->options.trace) {
722
+ oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rval);
723
+ }
690
724
  }
691
725
 
692
726
  static void
693
727
  array_append_num(ParseInfo pi, NumInfo ni) {
694
- rb_ary_push(stack_peek(&pi->stack)->val, oj_num_as_value(ni));
728
+ volatile VALUE rval = oj_num_as_value(ni);
729
+
730
+ rb_ary_push(stack_peek(&pi->stack)->val, rval);
731
+ if (Yes == pi->options.trace) {
732
+ oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
733
+ }
695
734
  }
696
735
 
697
736
  static void
698
737
  add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
699
738
  pi->stack.head->val = str_to_value(pi, str, len, orig);
739
+ if (Yes == pi->options.trace) {
740
+ oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, pi->stack.head->val);
741
+ }
700
742
  }
701
743
 
702
744
  static void
703
745
  add_num(ParseInfo pi, NumInfo ni) {
704
746
  pi->stack.head->val = oj_num_as_value(ni);
747
+ if (Yes == pi->options.trace) {
748
+ oj_trace_parse_call("add_num", pi, __FILE__, __LINE__, pi->stack.head->val);
749
+ }
705
750
  }
706
751
 
707
752
  void