oj 3.11.5 → 3.16.5

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.
Files changed (168) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1421 -0
  3. data/README.md +19 -5
  4. data/RELEASE_NOTES.md +61 -0
  5. data/ext/oj/buf.h +20 -6
  6. data/ext/oj/cache.c +329 -0
  7. data/ext/oj/cache.h +22 -0
  8. data/ext/oj/cache8.c +10 -9
  9. data/ext/oj/circarray.c +8 -6
  10. data/ext/oj/circarray.h +2 -2
  11. data/ext/oj/code.c +19 -33
  12. data/ext/oj/code.h +2 -2
  13. data/ext/oj/compat.c +27 -77
  14. data/ext/oj/custom.c +86 -179
  15. data/ext/oj/debug.c +126 -0
  16. data/ext/oj/dump.c +256 -249
  17. data/ext/oj/dump.h +26 -12
  18. data/ext/oj/dump_compat.c +565 -642
  19. data/ext/oj/dump_leaf.c +17 -63
  20. data/ext/oj/dump_object.c +65 -187
  21. data/ext/oj/dump_strict.c +27 -51
  22. data/ext/oj/encoder.c +43 -0
  23. data/ext/oj/err.c +2 -13
  24. data/ext/oj/err.h +24 -8
  25. data/ext/oj/extconf.rb +21 -6
  26. data/ext/oj/fast.c +149 -149
  27. data/ext/oj/intern.c +313 -0
  28. data/ext/oj/intern.h +22 -0
  29. data/ext/oj/mem.c +318 -0
  30. data/ext/oj/mem.h +53 -0
  31. data/ext/oj/mimic_json.c +121 -106
  32. data/ext/oj/object.c +85 -162
  33. data/ext/oj/odd.c +89 -67
  34. data/ext/oj/odd.h +15 -15
  35. data/ext/oj/oj.c +542 -411
  36. data/ext/oj/oj.h +99 -73
  37. data/ext/oj/parse.c +175 -187
  38. data/ext/oj/parse.h +26 -24
  39. data/ext/oj/parser.c +1600 -0
  40. data/ext/oj/parser.h +101 -0
  41. data/ext/oj/rails.c +112 -159
  42. data/ext/oj/rails.h +1 -1
  43. data/ext/oj/reader.c +11 -14
  44. data/ext/oj/reader.h +4 -2
  45. data/ext/oj/resolve.c +5 -24
  46. data/ext/oj/rxclass.c +7 -6
  47. data/ext/oj/rxclass.h +1 -1
  48. data/ext/oj/saj.c +22 -33
  49. data/ext/oj/saj2.c +584 -0
  50. data/ext/oj/saj2.h +23 -0
  51. data/ext/oj/scp.c +5 -28
  52. data/ext/oj/sparse.c +28 -72
  53. data/ext/oj/stream_writer.c +50 -40
  54. data/ext/oj/strict.c +56 -61
  55. data/ext/oj/string_writer.c +72 -39
  56. data/ext/oj/trace.h +31 -4
  57. data/ext/oj/usual.c +1218 -0
  58. data/ext/oj/usual.h +69 -0
  59. data/ext/oj/util.h +1 -1
  60. data/ext/oj/val_stack.c +14 -3
  61. data/ext/oj/val_stack.h +8 -7
  62. data/ext/oj/validate.c +46 -0
  63. data/ext/oj/wab.c +63 -88
  64. data/lib/oj/active_support_helper.rb +1 -3
  65. data/lib/oj/bag.rb +7 -1
  66. data/lib/oj/easy_hash.rb +4 -5
  67. data/lib/oj/error.rb +1 -2
  68. data/lib/oj/json.rb +162 -150
  69. data/lib/oj/mimic.rb +9 -7
  70. data/lib/oj/saj.rb +20 -6
  71. data/lib/oj/schandler.rb +5 -4
  72. data/lib/oj/state.rb +12 -8
  73. data/lib/oj/version.rb +1 -2
  74. data/lib/oj.rb +2 -0
  75. data/pages/Compatibility.md +1 -1
  76. data/pages/InstallOptions.md +20 -0
  77. data/pages/JsonGem.md +15 -0
  78. data/pages/Modes.md +8 -3
  79. data/pages/Options.md +43 -5
  80. data/pages/Parser.md +309 -0
  81. data/pages/Rails.md +14 -2
  82. data/test/_test_active.rb +8 -9
  83. data/test/_test_active_mimic.rb +7 -8
  84. data/test/_test_mimic_rails.rb +17 -20
  85. data/test/activerecord/result_test.rb +5 -6
  86. data/test/activesupport6/encoding_test.rb +63 -28
  87. data/test/{activesupport5 → activesupport7}/abstract_unit.rb +16 -12
  88. data/test/{activesupport5 → activesupport7}/decoding_test.rb +2 -10
  89. data/test/{activesupport5 → activesupport7}/encoding_test.rb +86 -50
  90. data/test/{activesupport5 → activesupport7}/encoding_test_cases.rb +6 -0
  91. data/test/{activesupport5 → activesupport7}/time_zone_test_helpers.rb +8 -0
  92. data/test/files.rb +15 -15
  93. data/test/foo.rb +16 -45
  94. data/test/helper.rb +11 -8
  95. data/test/isolated/shared.rb +3 -2
  96. data/test/json_gem/json_addition_test.rb +2 -2
  97. data/test/json_gem/json_common_interface_test.rb +8 -6
  98. data/test/json_gem/json_encoding_test.rb +0 -0
  99. data/test/json_gem/json_ext_parser_test.rb +1 -0
  100. data/test/json_gem/json_fixtures_test.rb +3 -2
  101. data/test/json_gem/json_generator_test.rb +56 -38
  102. data/test/json_gem/json_generic_object_test.rb +11 -11
  103. data/test/json_gem/json_parser_test.rb +54 -47
  104. data/test/json_gem/json_string_matching_test.rb +9 -9
  105. data/test/json_gem/test_helper.rb +7 -3
  106. data/test/mem.rb +34 -0
  107. data/test/perf.rb +22 -27
  108. data/test/perf_compat.rb +31 -33
  109. data/test/perf_dump.rb +50 -0
  110. data/test/perf_fast.rb +80 -82
  111. data/test/perf_file.rb +27 -29
  112. data/test/perf_object.rb +65 -69
  113. data/test/perf_once.rb +59 -0
  114. data/test/perf_parser.rb +183 -0
  115. data/test/perf_saj.rb +46 -54
  116. data/test/perf_scp.rb +58 -69
  117. data/test/perf_simple.rb +41 -39
  118. data/test/perf_strict.rb +74 -82
  119. data/test/perf_wab.rb +67 -69
  120. data/test/prec.rb +5 -5
  121. data/test/sample/change.rb +0 -1
  122. data/test/sample/dir.rb +0 -1
  123. data/test/sample/doc.rb +0 -1
  124. data/test/sample/file.rb +0 -1
  125. data/test/sample/group.rb +0 -1
  126. data/test/sample/hasprops.rb +0 -1
  127. data/test/sample/layer.rb +0 -1
  128. data/test/sample/rect.rb +0 -1
  129. data/test/sample/shape.rb +0 -1
  130. data/test/sample/text.rb +0 -1
  131. data/test/sample.rb +16 -16
  132. data/test/sample_json.rb +8 -8
  133. data/test/test_compat.rb +95 -43
  134. data/test/test_custom.rb +73 -51
  135. data/test/test_debian.rb +7 -10
  136. data/test/test_fast.rb +135 -79
  137. data/test/test_file.rb +41 -30
  138. data/test/test_gc.rb +16 -5
  139. data/test/test_generate.rb +5 -5
  140. data/test/test_hash.rb +5 -5
  141. data/test/test_integer_range.rb +9 -9
  142. data/test/test_null.rb +20 -20
  143. data/test/test_object.rb +99 -96
  144. data/test/test_parser.rb +11 -0
  145. data/test/test_parser_debug.rb +27 -0
  146. data/test/test_parser_saj.rb +337 -0
  147. data/test/test_parser_usual.rb +251 -0
  148. data/test/test_rails.rb +2 -2
  149. data/test/test_saj.rb +10 -8
  150. data/test/test_scp.rb +37 -39
  151. data/test/test_strict.rb +40 -32
  152. data/test/test_various.rb +165 -84
  153. data/test/test_wab.rb +48 -44
  154. data/test/test_writer.rb +47 -47
  155. data/test/tests.rb +13 -5
  156. data/test/tests_mimic.rb +12 -3
  157. data/test/tests_mimic_addition.rb +12 -3
  158. metadata +74 -128
  159. data/ext/oj/hash.c +0 -131
  160. data/ext/oj/hash.h +0 -19
  161. data/ext/oj/hash_test.c +0 -491
  162. data/test/activesupport4/decoding_test.rb +0 -108
  163. data/test/activesupport4/encoding_test.rb +0 -531
  164. data/test/activesupport4/test_helper.rb +0 -41
  165. data/test/activesupport5/test_helper.rb +0 -72
  166. data/test/bar.rb +0 -35
  167. data/test/baz.rb +0 -16
  168. data/test/zoo.rb +0 -13
data/ext/oj/code.c CHANGED
@@ -18,8 +18,8 @@ inline static VALUE resolve_classname(VALUE mod, const char *classname) {
18
18
  static VALUE path2class(const char *name) {
19
19
  char class_name[1024];
20
20
  VALUE clas;
21
- char * end = class_name + sizeof(class_name) - 1;
22
- char * s;
21
+ char *end = class_name + sizeof(class_name) - 1;
22
+ char *s;
23
23
  const char *n = name;
24
24
 
25
25
  clas = rb_cObject;
@@ -140,21 +140,17 @@ void oj_code_attrs(VALUE obj, Attr attrs, int depth, Out out, bool with_class) {
140
140
  if (with_class) {
141
141
  fill_indent(out, d2);
142
142
  *out->cur++ = '"';
143
- memcpy(out->cur, out->opts->create_id, out->opts->create_id_len);
144
- out->cur += out->opts->create_id_len;
143
+ APPEND_CHARS(out->cur, out->opts->create_id, out->opts->create_id_len);
145
144
  *out->cur++ = '"';
146
145
  if (0 < out->opts->dump_opts.before_size) {
147
- strcpy(out->cur, out->opts->dump_opts.before_sep);
148
- out->cur += out->opts->dump_opts.before_size;
146
+ APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
149
147
  }
150
148
  *out->cur++ = ':';
151
149
  if (0 < out->opts->dump_opts.after_size) {
152
- strcpy(out->cur, out->opts->dump_opts.after_sep);
153
- out->cur += out->opts->dump_opts.after_size;
150
+ APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
154
151
  }
155
152
  *out->cur++ = '"';
156
- memcpy(out->cur, classname, len);
157
- out->cur += len;
153
+ APPEND_CHARS(out->cur, classname, len);
158
154
  *out->cur++ = '"';
159
155
  no_comma = false;
160
156
  }
@@ -168,17 +164,14 @@ void oj_code_attrs(VALUE obj, Attr attrs, int depth, Out out, bool with_class) {
168
164
  }
169
165
  fill_indent(out, d2);
170
166
  *out->cur++ = '"';
171
- memcpy(out->cur, attrs->name, attrs->len);
172
- out->cur += attrs->len;
167
+ APPEND_CHARS(out->cur, attrs->name, attrs->len);
173
168
  *out->cur++ = '"';
174
169
  if (0 < out->opts->dump_opts.before_size) {
175
- strcpy(out->cur, out->opts->dump_opts.before_sep);
176
- out->cur += out->opts->dump_opts.before_size;
170
+ APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
177
171
  }
178
172
  *out->cur++ = ':';
179
173
  if (0 < out->opts->dump_opts.after_size) {
180
- strcpy(out->cur, out->opts->dump_opts.after_sep);
181
- out->cur += out->opts->dump_opts.after_size;
174
+ APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
182
175
  }
183
176
  if (Qundef == attrs->value) {
184
177
  if (Qundef != attrs->time) {
@@ -190,32 +183,25 @@ void oj_code_attrs(VALUE obj, Attr attrs, int depth, Out out, bool with_class) {
190
183
  default: oj_dump_time(attrs->time, out, false); break;
191
184
  }
192
185
  } else {
193
- char buf[32];
194
- char *b = buf + sizeof(buf) - 1;
195
- int neg = 0;
196
- long num = attrs->num;
186
+ char buf[32];
187
+ char *b = buf + sizeof(buf) - 1;
188
+ bool neg = false;
189
+ long num = attrs->num;
190
+ size_t cnt = 0;
197
191
 
198
192
  if (0 > num) {
199
- neg = 1;
193
+ neg = true;
200
194
  num = -num;
201
195
  }
202
196
  *b-- = '\0';
203
197
  if (0 < num) {
204
- for (; 0 < num; num /= 10, b--) {
205
- *b = (num % 10) + '0';
206
- }
207
- if (neg) {
208
- *b = '-';
209
- } else {
210
- b++;
211
- }
198
+ b = oj_longlong_to_string(num, neg, b);
212
199
  } else {
213
200
  *b = '0';
214
201
  }
215
- assure_size(out, (sizeof(buf) - (b - buf)));
216
- for (; '\0' != *b; b++) {
217
- *out->cur++ = *b;
218
- }
202
+ cnt = sizeof(buf) - (b - buf) - 1;
203
+ assure_size(out, cnt);
204
+ APPEND_CHARS(out->cur, b, cnt);
219
205
  }
220
206
  } else {
221
207
  oj_dump_compat_val(attrs->value, d3, out, true);
data/ext/oj/code.h CHANGED
@@ -17,7 +17,7 @@ typedef struct _code {
17
17
  EncodeFunc encode;
18
18
  DecodeFunc decode;
19
19
  bool active; // For compat mode.
20
- } * Code;
20
+ } *Code;
21
21
 
22
22
  // Used by encode functions.
23
23
  typedef struct _attr {
@@ -26,7 +26,7 @@ typedef struct _attr {
26
26
  VALUE value;
27
27
  long num;
28
28
  VALUE time;
29
- } * Attr;
29
+ } *Attr;
30
30
 
31
31
  extern bool oj_code_dump(Code codes, VALUE obj, int depth, Out out);
32
32
  extern VALUE oj_code_load(Code codes, VALUE clas, VALUE args);
data/ext/oj/compat.c CHANGED
@@ -5,34 +5,27 @@
5
5
 
6
6
  #include "encode.h"
7
7
  #include "err.h"
8
- #include "hash.h"
8
+ #include "intern.h"
9
+ #include "mem.h"
9
10
  #include "oj.h"
10
11
  #include "parse.h"
11
12
  #include "resolve.h"
12
13
  #include "trace.h"
13
14
 
14
15
  static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *orig) {
15
- const char * key = kval->key;
16
- int klen = kval->klen;
17
- Val parent = stack_peek(&pi->stack);
18
- volatile VALUE rkey = kval->key_val;
16
+ const char *key = kval->key;
17
+ int klen = kval->klen;
18
+ Val parent = stack_peek(&pi->stack);
19
19
 
20
- if (Qundef == rkey && Yes == pi->options.create_ok && NULL != pi->options.create_id &&
20
+ if (Qundef == kval->key_val && Yes == pi->options.create_ok && NULL != pi->options.create_id &&
21
21
  *pi->options.create_id == *key && (int)pi->options.create_id_len == klen &&
22
22
  0 == strncmp(pi->options.create_id, key, klen)) {
23
23
  parent->classname = oj_strndup(str, len);
24
24
  parent->clen = len;
25
25
  } else {
26
- volatile VALUE rstr = rb_str_new(str, len);
27
-
28
- if (Qundef == rkey) {
29
- rkey = rb_str_new(key, klen);
30
- rstr = oj_encode(rstr);
31
- rkey = oj_encode(rkey);
32
- if (Yes == pi->options.sym_key) {
33
- rkey = rb_str_intern(rkey);
34
- }
35
- }
26
+ volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
27
+ volatile VALUE rkey = oj_calc_hash_key(pi, kval);
28
+
36
29
  if (Yes == pi->options.create_ok && NULL != pi->options.str_rx.head) {
37
30
  VALUE clas = oj_rxclass_match(&pi->options.str_rx, str, (int)len);
38
31
 
@@ -49,9 +42,7 @@ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, c
49
42
  } else {
50
43
  rb_hash_aset(parent->val, rkey, rstr);
51
44
  }
52
- if (Yes == pi->options.trace) {
53
- oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rstr);
54
- }
45
+ TRACE_PARSE_CALL(pi->options.trace, "set_string", pi, rstr);
55
46
  }
56
47
  }
57
48
 
@@ -63,9 +54,7 @@ static VALUE start_hash(ParseInfo pi) {
63
54
  } else {
64
55
  h = rb_hash_new();
65
56
  }
66
- if (Yes == pi->options.trace) {
67
- oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
68
- }
57
+ TRACE_PARSE_IN(pi->options.trace, "start_hash", pi);
69
58
  return h;
70
59
  }
71
60
 
@@ -84,32 +73,16 @@ static void end_hash(struct _parseInfo *pi) {
84
73
  }
85
74
  }
86
75
  if (0 != parent->classname) {
87
- xfree((char *)parent->classname);
76
+ OJ_R_FREE((char *)parent->classname);
88
77
  parent->classname = 0;
89
78
  }
90
79
  }
91
- if (Yes == pi->options.trace) {
92
- oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
93
- }
94
- }
95
-
96
- static VALUE calc_hash_key(ParseInfo pi, Val parent) {
97
- volatile VALUE rkey = parent->key_val;
98
-
99
- if (Qundef == rkey) {
100
- rkey = rb_str_new(parent->key, parent->klen);
101
- }
102
- rkey = oj_encode(rkey);
103
- if (Yes == pi->options.sym_key) {
104
- rkey = rb_str_intern(rkey);
105
- }
106
- return rkey;
80
+ TRACE_PARSE_HASH_END(pi->options.trace, pi);
107
81
  }
108
82
 
109
83
  static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
110
- volatile VALUE rstr = rb_str_new(str, len);
84
+ volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
111
85
 
112
- rstr = oj_encode(rstr);
113
86
  if (Yes == pi->options.create_ok && NULL != pi->options.str_rx.head) {
114
87
  VALUE clas = oj_rxclass_match(&pi->options.str_rx, str, (int)len);
115
88
 
@@ -119,37 +92,27 @@ static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig
119
92
  }
120
93
  }
121
94
  pi->stack.head->val = rstr;
122
- if (Yes == pi->options.trace) {
123
- oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, rstr);
124
- }
95
+ TRACE_PARSE_CALL(pi->options.trace, "add_string", pi, rstr);
125
96
  }
126
97
 
127
98
  static void add_num(ParseInfo pi, NumInfo ni) {
128
99
  pi->stack.head->val = oj_num_as_value(ni);
129
- if (Yes == pi->options.trace) {
130
- oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, pi->stack.head->val);
131
- }
100
+ TRACE_PARSE_CALL(pi->options.trace, "add_number", pi, pi->stack.head->val);
132
101
  }
133
102
 
134
103
  static void hash_set_num(struct _parseInfo *pi, Val parent, NumInfo ni) {
135
104
  volatile VALUE rval = oj_num_as_value(ni);
136
105
 
137
- if (!oj_use_hash_alt && rb_cHash != rb_obj_class(parent->val)) {
106
+ if (rb_cHash != rb_obj_class(parent->val)) {
138
107
  // The rb_hash_set would still work but the unit tests for the
139
108
  // json gem require the less efficient []= method be called to set
140
109
  // values. Even using the store method to set the values will fail
141
110
  // the unit tests.
142
- rb_funcall(stack_peek(&pi->stack)->val,
143
- rb_intern("[]="),
144
- 2,
145
- calc_hash_key(pi, parent),
146
- rval);
111
+ rb_funcall(stack_peek(&pi->stack)->val, rb_intern("[]="), 2, oj_calc_hash_key(pi, parent), rval);
147
112
  } else {
148
- rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), rval);
149
- }
150
- if (Yes == pi->options.trace) {
151
- oj_trace_parse_call("set_number", pi, __FILE__, __LINE__, rval);
113
+ rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), rval);
152
114
  }
115
+ TRACE_PARSE_CALL(pi->options.trace, "set_number", pi, rval);
153
116
  }
154
117
 
155
118
  static void hash_set_value(ParseInfo pi, Val parent, VALUE value) {
@@ -158,26 +121,18 @@ static void hash_set_value(ParseInfo pi, Val parent, VALUE value) {
158
121
  // json gem require the less efficient []= method be called to set
159
122
  // values. Even using the store method to set the values will fail
160
123
  // the unit tests.
161
- rb_funcall(stack_peek(&pi->stack)->val,
162
- rb_intern("[]="),
163
- 2,
164
- calc_hash_key(pi, parent),
165
- value);
124
+ rb_funcall(stack_peek(&pi->stack)->val, rb_intern("[]="), 2, oj_calc_hash_key(pi, parent), value);
166
125
  } else {
167
- rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), value);
168
- }
169
- if (Yes == pi->options.trace) {
170
- oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
126
+ rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), value);
171
127
  }
128
+ TRACE_PARSE_CALL(pi->options.trace, "set_value", pi, value);
172
129
  }
173
130
 
174
131
  static VALUE start_array(ParseInfo pi) {
175
132
  if (Qnil != pi->options.array_class) {
176
133
  return rb_class_new_instance(0, NULL, pi->options.array_class);
177
134
  }
178
- if (Yes == pi->options.trace) {
179
- oj_trace_parse_in("start_array", pi, __FILE__, __LINE__);
180
- }
135
+ TRACE_PARSE_IN(pi->options.trace, "start_array", pi);
181
136
  return rb_ary_new();
182
137
  }
183
138
 
@@ -193,15 +148,12 @@ static void array_append_num(ParseInfo pi, NumInfo ni) {
193
148
  } else {
194
149
  rb_ary_push(parent->val, rval);
195
150
  }
196
- if (Yes == pi->options.trace) {
197
- oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
198
- }
151
+ TRACE_PARSE_CALL(pi->options.trace, "append_number", pi, rval);
199
152
  }
200
153
 
201
154
  static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
202
- volatile VALUE rstr = rb_str_new(str, len);
155
+ volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
203
156
 
204
- rstr = oj_encode(rstr);
205
157
  if (Yes == pi->options.create_ok && NULL != pi->options.str_rx.head) {
206
158
  VALUE clas = oj_rxclass_match(&pi->options.str_rx, str, (int)len);
207
159
 
@@ -211,9 +163,7 @@ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const c
211
163
  }
212
164
  }
213
165
  rb_ary_push(stack_peek(&pi->stack)->val, rstr);
214
- if (Yes == pi->options.trace) {
215
- oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rstr);
216
- }
166
+ TRACE_PARSE_CALL(pi->options.trace, "append_string", pi, rstr);
217
167
  }
218
168
 
219
169
  void oj_set_compat_callbacks(ParseInfo pi) {