oj 3.13.23 → 3.14.2

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: 3d2f8a01b7a59da7cd25ed3551065dddd9e31e5184989804d172c2e39cc769d6
4
- data.tar.gz: 7211a96856ec44173fa9dcc7245e3cb2f6b7c2e22a746ef35f168126873f4c88
3
+ metadata.gz: 35277d429b423f078c9c259bc2f7d8fd5714f55bb67def193b2b58c1352f3d11
4
+ data.tar.gz: 337ca936375237d94a5e6a6ece01abd28ce367119fbb72b53dc41c3248c9e136
5
5
  SHA512:
6
- metadata.gz: ee3ad5cac6cac48bcf7fdf682e69770dfee08b502735cc75b84ae1635196fdcdaf2fde021e32e6d897bdc6935e111882ddc48fa5a274fe0d98ad45c2fdf68917
7
- data.tar.gz: 3e05212fa84a2bf05954ec870ac27da7c845335b411507aa0bf5e45497403cccf4c40990f0ee8cee6d21f19163f33116bb240836795482737eaa744bc5ff6d94
6
+ metadata.gz: e41c8ef241150e82943a92becc0ca0ec501d3ea9f9a2729abcb2529f2f5ac4360bb0a7684d46fd2357c0edb81d9347b5a6228129536c24157df5b0a788a4fc22
7
+ data.tar.gz: 6b69fcd20fe9956826865a8fafbca921ae0d9d39f43fbb3aa713b8411381852bcbfa16f7b3a3557e0c24e0545fb0a82c120c93c24bcd81ea8616b89fb6db2b47
data/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 3.14.2 - 2023-02-10
4
+
5
+ - Fixed check for \0 in strings.
6
+
7
+ ## 3.14.1 - 2023-02-01
8
+
9
+ - Fixed issue with uninitialized handler for Oj::Parser::Saj.
10
+
11
+ - Fixed hang on unterminated string with a \0 byte in parse.c.
12
+
13
+ ## 3.14.0 - 2023-01-30
14
+
15
+ - Tracing is now a compile time option giving a 15 to 20% performance boost.
16
+
17
+ - Some cleanup in teh fast parser.
18
+
3
19
  ## 3.13.23 - 2022-11-06
4
20
 
5
21
  - Fixed issue with Oj::Parser extension regarding GC timeing.
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/github/workflow/status/ohler55/oj/CI?logo=github)](https://github.com/ohler55/oj/actions/workflows/CI.yml)
3
+ [![CI](https://github.com/ohler55/oj/actions/workflows/CI.yml/badge.svg)](https://github.com/ohler55/oj/actions/workflows/CI.yml)
4
4
  ![Gem](https://img.shields.io/gem/v/oj.svg)
5
5
  ![Gem](https://img.shields.io/gem/dt/oj.svg)
6
6
  [![SemVer compatibility](https://api.dependabot.com/badges/compatibility_score?dependency-name=oj&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=oj&package-manager=bundler&version-scheme=semver)
@@ -70,6 +70,7 @@ links.
70
70
  - [{file:Compatibility.md}](pages/Compatibility.md) lists current compatibility with Rubys and Rails.
71
71
  - [{file:Advanced.md}](pages/Advanced.md) for fast parser and marshalling features.
72
72
  - [{file:Security.md}](pages/Security.md) for security considerations.
73
+ - [{file:InstallOptions.md}](pages/InstallOptions.md) for install option.
73
74
 
74
75
  ## Releases
75
76
 
data/ext/oj/buf.h CHANGED
@@ -5,6 +5,7 @@
5
5
  #define OJ_BUF_H
6
6
 
7
7
  #include "ruby.h"
8
+ #include "mem.h"
8
9
 
9
10
  typedef struct _buf {
10
11
  char *head;
@@ -25,7 +26,7 @@ inline static void buf_reset(Buf buf) {
25
26
 
26
27
  inline static void buf_cleanup(Buf buf) {
27
28
  if (buf->base != buf->head) {
28
- xfree(buf->head);
29
+ OJ_R_FREE(buf->head);
29
30
  }
30
31
  }
31
32
 
@@ -49,10 +50,10 @@ inline static void buf_append_string(Buf buf, const char *s, size_t slen) {
49
50
  size_t new_len = len + slen + len / 2;
50
51
 
51
52
  if (buf->base == buf->head) {
52
- buf->head = ALLOC_N(char, new_len);
53
+ buf->head = OJ_R_ALLOC_N(char, new_len);
53
54
  memcpy(buf->head, buf->base, len);
54
55
  } else {
55
- REALLOC_N(buf->head, char, new_len);
56
+ OJ_R_REALLOC_N(buf->head, char, new_len);
56
57
  }
57
58
  buf->tail = buf->head + toff;
58
59
  buf->end = buf->head + new_len - 1;
@@ -68,10 +69,10 @@ inline static void buf_append(Buf buf, char c) {
68
69
  size_t new_len = len + len / 2;
69
70
 
70
71
  if (buf->base == buf->head) {
71
- buf->head = ALLOC_N(char, new_len);
72
+ buf->head = OJ_R_ALLOC_N(char, new_len);
72
73
  memcpy(buf->head, buf->base, len);
73
74
  } else {
74
- REALLOC_N(buf->head, char, new_len);
75
+ OJ_R_REALLOC_N(buf->head, char, new_len);
75
76
  }
76
77
  buf->tail = buf->head + toff;
77
78
  buf->end = buf->head + new_len - 1;
data/ext/oj/cache.c CHANGED
@@ -6,6 +6,7 @@
6
6
  #endif
7
7
  #include <stdlib.h>
8
8
 
9
+ #include "mem.h"
9
10
  #include "cache.h"
10
11
 
11
12
  // The stdlib calloc, realloc, and free are used instead of the Ruby ALLOC,
@@ -100,7 +101,7 @@ static void rehash(Cache c) {
100
101
  osize = c->size;
101
102
  c->size = osize * 4;
102
103
  c->mask = c->size - 1;
103
- c->slots = realloc((void *)c->slots, sizeof(Slot) * c->size);
104
+ c->slots = OJ_REALLOC((void *)c->slots, sizeof(Slot) * c->size);
104
105
  memset((Slot *)c->slots + osize, 0, sizeof(Slot) * osize * 3);
105
106
  end = (Slot *)c->slots + osize;
106
107
  for (sp = (Slot *)c->slots; sp < end; sp++) {
@@ -128,7 +129,7 @@ static VALUE lockless_intern(Cache c, const char *key, size_t len) {
128
129
  while (REUSE_MAX < c->rcnt) {
129
130
  if (NULL != (b = c->reuse)) {
130
131
  c->reuse = b->next;
131
- free(b);
132
+ OJ_FREE(b);
132
133
  c->rcnt--;
133
134
  } else {
134
135
  // An accounting error occured somewhere so correct it.
@@ -143,7 +144,7 @@ static VALUE lockless_intern(Cache c, const char *key, size_t len) {
143
144
  }
144
145
  rkey = c->form(key, len);
145
146
  if (NULL == (b = c->reuse)) {
146
- b = calloc(1, sizeof(struct _slot));
147
+ b = OJ_CALLOC(1, sizeof(struct _slot));
147
148
  } else {
148
149
  c->reuse = b->next;
149
150
  c->rcnt--;
@@ -174,7 +175,7 @@ static VALUE locking_intern(Cache c, const char *key, size_t len) {
174
175
  while (REUSE_MAX < c->rcnt) {
175
176
  if (NULL != (b = c->reuse)) {
176
177
  c->reuse = b->next;
177
- free(b);
178
+ OJ_FREE(b);
178
179
  c->rcnt--;
179
180
  } else {
180
181
  // An accounting error occured somewhere so correct it.
@@ -200,7 +201,7 @@ static VALUE locking_intern(Cache c, const char *key, size_t len) {
200
201
  }
201
202
  CACHE_UNLOCK(c);
202
203
  if (NULL == b) {
203
- b = calloc(1, sizeof(struct _slot));
204
+ b = OJ_CALLOC(1, sizeof(struct _slot));
204
205
  }
205
206
  rkey = c->form(key, len);
206
207
  b->hash = h;
@@ -228,7 +229,7 @@ static VALUE locking_intern(Cache c, const char *key, size_t len) {
228
229
  }
229
230
 
230
231
  Cache cache_create(size_t size, VALUE (*form)(const char *str, size_t len), bool mark, bool locking) {
231
- Cache c = calloc(1, sizeof(struct _cache));
232
+ Cache c = OJ_CALLOC(1, sizeof(struct _cache));
232
233
  int shift = 0;
233
234
 
234
235
  for (; REHASH_LIMIT < size; size /= 2, shift++) {
@@ -243,7 +244,7 @@ Cache cache_create(size_t size, VALUE (*form)(const char *str, size_t len), bool
243
244
  #endif
244
245
  c->size = 1 << shift;
245
246
  c->mask = c->size - 1;
246
- c->slots = calloc(c->size, sizeof(Slot));
247
+ c->slots = OJ_CALLOC(c->size, sizeof(Slot));
247
248
  c->form = form;
248
249
  c->xrate = 1; // low
249
250
  c->mark = mark;
@@ -268,11 +269,11 @@ void cache_free(Cache c) {
268
269
 
269
270
  for (s = c->slots[i]; NULL != s; s = next) {
270
271
  next = s->next;
271
- free(s);
272
+ OJ_FREE(s);
272
273
  }
273
274
  }
274
- free((void *)c->slots);
275
- free(c);
275
+ OJ_FREE((void *)c->slots);
276
+ OJ_FREE(c);
276
277
  }
277
278
 
278
279
  void cache_mark(Cache c) {
data/ext/oj/cache8.c CHANGED
@@ -9,6 +9,7 @@
9
9
  #include <stdlib.h>
10
10
  #include <string.h>
11
11
 
12
+ #include "mem.h"
12
13
  #include "ruby.h"
13
14
 
14
15
  #define BITS 4
@@ -32,7 +33,7 @@ void oj_cache8_new(Cache8 *cache) {
32
33
  Bucket *b;
33
34
  int i;
34
35
 
35
- *cache = ALLOC(struct _cache8);
36
+ *cache = OJ_R_ALLOC(struct _cache8);
36
37
  for (i = SLOT_CNT, b = (*cache)->buckets; 0 < i; i--, b++) {
37
38
  b->value = 0;
38
39
  }
@@ -51,7 +52,7 @@ static void cache8_delete(Cache8 cache, int depth) {
51
52
  }
52
53
  }
53
54
  }
54
- xfree(cache);
55
+ OJ_R_FREE(cache);
55
56
  }
56
57
 
57
58
  slot_t oj_cache8_get(Cache8 cache, sid_t key, slot_t **slot) {
data/ext/oj/circarray.c CHANGED
@@ -1,12 +1,13 @@
1
1
  // Copyright (c) 2012 Peter Ohler. All rights reserved.
2
2
  // Licensed under the MIT License. See LICENSE file in the project root for license details.
3
3
 
4
+ #include "mem.h"
4
5
  #include "circarray.h"
5
6
 
6
7
  CircArray oj_circ_array_new(void) {
7
8
  CircArray ca;
8
9
 
9
- if (0 == (ca = ALLOC(struct _circArray))) {
10
+ if (0 == (ca = OJ_R_ALLOC(struct _circArray))) {
10
11
  rb_raise(rb_eNoMemError, "not enough memory\n");
11
12
  }
12
13
  ca->objs = ca->obj_array;
@@ -18,9 +19,9 @@ CircArray oj_circ_array_new(void) {
18
19
 
19
20
  void oj_circ_array_free(CircArray ca) {
20
21
  if (ca->objs != ca->obj_array) {
21
- xfree(ca->objs);
22
+ OJ_R_FREE(ca->objs);
22
23
  }
23
- xfree(ca);
24
+ OJ_R_FREE(ca);
24
25
  }
25
26
 
26
27
  void oj_circ_array_set(CircArray ca, VALUE obj, unsigned long id) {
@@ -31,12 +32,12 @@ void oj_circ_array_set(CircArray ca, VALUE obj, unsigned long id) {
31
32
  unsigned long cnt = id + 512;
32
33
 
33
34
  if (ca->objs == ca->obj_array) {
34
- if (0 == (ca->objs = ALLOC_N(VALUE, cnt))) {
35
+ if (0 == (ca->objs = OJ_R_ALLOC_N(VALUE, cnt))) {
35
36
  rb_raise(rb_eNoMemError, "not enough memory\n");
36
37
  }
37
38
  memcpy(ca->objs, ca->obj_array, sizeof(VALUE) * ca->cnt);
38
39
  } else {
39
- REALLOC_N(ca->objs, VALUE, cnt);
40
+ OJ_R_REALLOC_N(ca->objs, VALUE, cnt);
40
41
  }
41
42
  ca->size = cnt;
42
43
  }
data/ext/oj/compat.c CHANGED
@@ -3,6 +3,7 @@
3
3
 
4
4
  #include <stdio.h>
5
5
 
6
+ #include "mem.h"
6
7
  #include "encode.h"
7
8
  #include "err.h"
8
9
  #include "intern.h"
@@ -54,9 +55,7 @@ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, c
54
55
  } else {
55
56
  rb_hash_aset(parent->val, rkey, rstr);
56
57
  }
57
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
58
- oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rstr);
59
- }
58
+ TRACE_PARSE_CALL(pi->options.trace, "set_string", pi, rstr);
60
59
  }
61
60
  }
62
61
 
@@ -68,9 +67,7 @@ static VALUE start_hash(ParseInfo pi) {
68
67
  } else {
69
68
  h = rb_hash_new();
70
69
  }
71
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
72
- oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
73
- }
70
+ TRACE_PARSE_IN(pi->options.trace, "start_hash", pi);
74
71
  return h;
75
72
  }
76
73
 
@@ -89,13 +86,11 @@ static void end_hash(struct _parseInfo *pi) {
89
86
  }
90
87
  }
91
88
  if (0 != parent->classname) {
92
- xfree((char *)parent->classname);
89
+ OJ_R_FREE((char *)parent->classname);
93
90
  parent->classname = 0;
94
91
  }
95
92
  }
96
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
97
- oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
98
- }
93
+ TRACE_PARSE_HASH_END(pi->options.trace, pi);
99
94
  }
100
95
 
101
96
  static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
@@ -110,16 +105,12 @@ static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig
110
105
  }
111
106
  }
112
107
  pi->stack.head->val = rstr;
113
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
114
- oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, rstr);
115
- }
108
+ TRACE_PARSE_CALL(pi->options.trace, "add_string", pi, rstr);
116
109
  }
117
110
 
118
111
  static void add_num(ParseInfo pi, NumInfo ni) {
119
112
  pi->stack.head->val = oj_num_as_value(ni);
120
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
121
- oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, pi->stack.head->val);
122
- }
113
+ TRACE_PARSE_CALL(pi->options.trace, "add_number", pi, pi->stack.head->val);
123
114
  }
124
115
 
125
116
  static void hash_set_num(struct _parseInfo *pi, Val parent, NumInfo ni) {
@@ -138,9 +129,7 @@ static void hash_set_num(struct _parseInfo *pi, Val parent, NumInfo ni) {
138
129
  } else {
139
130
  rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), rval);
140
131
  }
141
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
142
- oj_trace_parse_call("set_number", pi, __FILE__, __LINE__, rval);
143
- }
132
+ TRACE_PARSE_CALL(pi->options.trace, "set_number", pi, rval);
144
133
  }
145
134
 
146
135
  static void hash_set_value(ParseInfo pi, Val parent, VALUE value) {
@@ -157,18 +146,14 @@ static void hash_set_value(ParseInfo pi, Val parent, VALUE value) {
157
146
  } else {
158
147
  rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), value);
159
148
  }
160
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
161
- oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
162
- }
149
+ TRACE_PARSE_CALL(pi->options.trace, "set_value", pi, value);
163
150
  }
164
151
 
165
152
  static VALUE start_array(ParseInfo pi) {
166
153
  if (Qnil != pi->options.array_class) {
167
154
  return rb_class_new_instance(0, NULL, pi->options.array_class);
168
155
  }
169
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
170
- oj_trace_parse_in("start_array", pi, __FILE__, __LINE__);
171
- }
156
+ TRACE_PARSE_IN(pi->options.trace, "start_array", pi);
172
157
  return rb_ary_new();
173
158
  }
174
159
 
@@ -184,9 +169,7 @@ static void array_append_num(ParseInfo pi, NumInfo ni) {
184
169
  } else {
185
170
  rb_ary_push(parent->val, rval);
186
171
  }
187
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
188
- oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
189
- }
172
+ TRACE_PARSE_CALL(pi->options.trace, "append_number", pi, rval);
190
173
  }
191
174
 
192
175
  static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
@@ -201,9 +184,7 @@ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const c
201
184
  }
202
185
  }
203
186
  rb_ary_push(stack_peek(&pi->stack)->val, rstr);
204
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
205
- oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rstr);
206
- }
187
+ TRACE_PARSE_CALL(pi->options.trace, "append_string", pi, rstr);
207
188
  }
208
189
 
209
190
  void oj_set_compat_callbacks(ParseInfo pi) {
data/ext/oj/custom.c CHANGED
@@ -4,6 +4,7 @@
4
4
  #include <stdint.h>
5
5
  #include <stdio.h>
6
6
 
7
+ #include "mem.h"
7
8
  #include "code.h"
8
9
  #include "dump.h"
9
10
  #include "encode.h"
@@ -24,20 +25,20 @@ static void dump_obj_str(VALUE obj, int depth, Out out) {
24
25
  {"s", 1, Qnil},
25
26
  {NULL, 0, Qnil},
26
27
  };
27
- attrs->value = rb_funcall(obj, oj_to_s_id, 0);
28
+ attrs->value = oj_safe_string_convert(obj);
28
29
 
29
30
  oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
30
31
  }
31
32
 
32
33
  static void dump_obj_as_str(VALUE obj, int depth, Out out) {
33
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
34
+ volatile VALUE rstr = oj_safe_string_convert(obj);
34
35
  const char *str = RSTRING_PTR(rstr);
35
36
 
36
37
  oj_dump_cstr(str, RSTRING_LEN(rstr), 0, 0, out);
37
38
  }
38
39
 
39
40
  static void bigdecimal_dump(VALUE obj, int depth, Out out) {
40
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
41
+ volatile VALUE rstr = oj_safe_string_convert(obj);
41
42
  const char *str = RSTRING_PTR(rstr);
42
43
  int len = (int)RSTRING_LEN(rstr);
43
44
 
@@ -305,7 +306,7 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
305
306
  switch (rb_type(key)) {
306
307
  case T_STRING: oj_dump_str(key, 0, out, false); break;
307
308
  case T_SYMBOL: oj_dump_sym(key, 0, out, false); break;
308
- default: oj_dump_str(rb_funcall(key, oj_to_s_id, 0), 0, out, false); break;
309
+ default: oj_dump_str(oj_safe_string_convert(key), 0, out, false); break;
309
310
  }
310
311
  if (!out->opts->dump_opts.use) {
311
312
  *out->cur++ = ':';
@@ -437,7 +438,7 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
437
438
  ID i;
438
439
 
439
440
  if (sizeof(nbuf) <= nlen) {
440
- if (NULL == (n2 = strdup(name))) {
441
+ if (NULL == (n2 = OJ_STRDUP(name))) {
441
442
  rb_raise(rb_eNoMemError, "for attribute name.");
442
443
  }
443
444
  } else {
@@ -454,7 +455,7 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
454
455
  i = rb_intern(n);
455
456
  v = rb_funcall(v, i, 0);
456
457
  if (nbuf != n2) {
457
- free(n2);
458
+ OJ_FREE(n2);
458
459
  }
459
460
  }
460
461
  fill_indent(out, d2);
@@ -479,17 +480,13 @@ static VALUE dump_common(VALUE obj, int depth, Out out) {
479
480
  const char *s;
480
481
  int len;
481
482
 
482
- if (RB_UNLIKELY(Yes == out->opts->trace)) {
483
- oj_trace("to_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyIn);
484
- }
483
+ TRACE(out->opts->trace, "to_json", obj, depth + 1, TraceRubyIn);
485
484
  if (0 == rb_obj_method_arity(obj, oj_to_json_id)) {
486
485
  rs = rb_funcall(obj, oj_to_json_id, 0);
487
486
  } else {
488
487
  rs = rb_funcall2(obj, oj_to_json_id, out->argc, out->argv);
489
488
  }
490
- if (RB_UNLIKELY(Yes == out->opts->trace)) {
491
- oj_trace("to_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyOut);
492
- }
489
+ TRACE(out->opts->trace, "to_json", obj, depth + 1, TraceRubyOut);
493
490
  s = RSTRING_PTR(rs);
494
491
  len = (int)RSTRING_LEN(rs);
495
492
 
@@ -499,9 +496,7 @@ static VALUE dump_common(VALUE obj, int depth, Out out) {
499
496
  } else if (Yes == out->opts->as_json && rb_respond_to(obj, oj_as_json_id)) {
500
497
  volatile VALUE aj;
501
498
 
502
- if (RB_UNLIKELY(Yes == out->opts->trace)) {
503
- oj_trace("as_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyIn);
504
- }
499
+ TRACE(out->opts->trace, "as_json", obj, depth + 1, TraceRubyIn);
505
500
  // Some classes elect to not take an options argument so check the arity
506
501
  // of as_json.
507
502
  if (0 == rb_obj_method_arity(obj, oj_as_json_id)) {
@@ -509,12 +504,10 @@ static VALUE dump_common(VALUE obj, int depth, Out out) {
509
504
  } else {
510
505
  aj = rb_funcall2(obj, oj_as_json_id, out->argc, out->argv);
511
506
  }
512
- if (RB_UNLIKELY(Yes == out->opts->trace)) {
513
- oj_trace("as_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyOut);
514
- }
507
+ TRACE(out->opts->trace, "as_json", obj, depth + 1, TraceRubyOut);
515
508
  // Catch the obvious brain damaged recursive dumping.
516
509
  if (aj == obj) {
517
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
510
+ volatile VALUE rstr = oj_safe_string_convert(obj);
518
511
 
519
512
  oj_dump_cstr(RSTRING_PTR(rstr), (int)RSTRING_LEN(rstr), false, false, out);
520
513
  } else {
@@ -876,9 +869,7 @@ static DumpFunc custom_funcs[] = {
876
869
  void oj_dump_custom_val(VALUE obj, int depth, Out out, bool as_ok) {
877
870
  int type = rb_type(obj);
878
871
 
879
- if (RB_UNLIKELY(Yes == out->opts->trace)) {
880
- oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
881
- }
872
+ TRACE(out->opts->trace, "dump", obj, depth, TraceIn);
882
873
  if (MAX_DEPTH < depth) {
883
874
  rb_raise(rb_eNoMemError, "Too deeply nested.\n");
884
875
  }
@@ -887,16 +878,12 @@ void oj_dump_custom_val(VALUE obj, int depth, Out out, bool as_ok) {
887
878
 
888
879
  if (NULL != f) {
889
880
  f(obj, depth, out, true);
890
- if (RB_UNLIKELY(Yes == out->opts->trace)) {
891
- oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
892
- }
881
+ TRACE(out->opts->trace, "dump", obj, depth, TraceOut);
893
882
  return;
894
883
  }
895
884
  }
896
885
  oj_dump_nil(Qnil, depth, out, false);
897
- if (RB_UNLIKELY(Yes == out->opts->trace)) {
898
- oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
899
- }
886
+ TRACE(out->opts->trace, "dump", Qnil, depth, TraceOut);
900
887
  }
901
888
 
902
889
  ///// load functions /////
@@ -969,9 +956,7 @@ static void end_hash(struct _parseInfo *pi) {
969
956
  }
970
957
  parent->clas = Qundef;
971
958
  }
972
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
973
- oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
974
- }
959
+ TRACE_PARSE_HASH_END(pi->options.trace, pi);
975
960
  }
976
961
 
977
962
  static void hash_set_num(struct _parseInfo *pi, Val kval, NumInfo ni) {
data/ext/oj/dump.c CHANGED
@@ -14,6 +14,7 @@
14
14
  #include <poll.h>
15
15
  #endif
16
16
 
17
+ #include "mem.h"
17
18
  #include "cache8.h"
18
19
  #include "odd.h"
19
20
  #include "oj.h"
@@ -463,7 +464,7 @@ void oj_dump_time(VALUE obj, Out out, int withZone) {
463
464
  }
464
465
 
465
466
  void oj_dump_ruby_time(VALUE obj, Out out) {
466
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
467
+ volatile VALUE rstr = oj_safe_string_convert(obj);
467
468
 
468
469
  oj_dump_cstr(RSTRING_PTR(rstr), (int)RSTRING_LEN(rstr), 0, 0, out);
469
470
  }
@@ -736,13 +737,9 @@ void oj_dump_raw_json(VALUE obj, int depth, Out out) {
736
737
  } else {
737
738
  volatile VALUE jv;
738
739
 
739
- if (RB_UNLIKELY(Yes == out->opts->trace)) {
740
- oj_trace("raw_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyIn);
741
- }
740
+ TRACE(out->opts->trace, "raw_json", obj, depth + 1, TraceRubyIn);
742
741
  jv = rb_funcall(obj, oj_raw_json_id, 2, RB_INT2NUM(depth), RB_INT2NUM(out->indent));
743
- if (RB_UNLIKELY(Yes == out->opts->trace)) {
744
- oj_trace("raw_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyOut);
745
- }
742
+ TRACE(out->opts->trace, "raw_json", obj, depth + 1, TraceRubyOut);
746
743
  oj_dump_raw(RSTRING_PTR(jv), (size_t)RSTRING_LEN(jv), out);
747
744
  }
748
745
  }
@@ -932,7 +929,7 @@ void oj_dump_class(VALUE obj, int depth, Out out, bool as_ok) {
932
929
  }
933
930
 
934
931
  void oj_dump_obj_to_s(VALUE obj, Out out) {
935
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
932
+ volatile VALUE rstr = oj_safe_string_convert(obj);
936
933
 
937
934
  oj_dump_cstr(RSTRING_PTR(rstr), (int)RSTRING_LEN(rstr), 0, 0, out);
938
935
  }
@@ -952,7 +949,7 @@ void oj_out_init(Out out) {
952
949
 
953
950
  void oj_out_free(Out out) {
954
951
  if (out->allocated) {
955
- xfree(out->buf); // TBD
952
+ OJ_R_FREE(out->buf); // TBD
956
953
  }
957
954
  }
958
955
 
@@ -966,9 +963,9 @@ void oj_grow_out(Out out, size_t len) {
966
963
  size += len;
967
964
  }
968
965
  if (out->allocated) {
969
- REALLOC_N(buf, char, (size + BUFFER_EXTRA));
966
+ OJ_R_REALLOC_N(buf, char, (size + BUFFER_EXTRA));
970
967
  } else {
971
- buf = ALLOC_N(char, (size + BUFFER_EXTRA));
968
+ buf = OJ_R_ALLOC_N(char, (size + BUFFER_EXTRA));
972
969
  out->allocated = true;
973
970
  memcpy(buf, out->buf, out->end - out->buf + BUFFER_EXTRA);
974
971
  }
@@ -1173,7 +1170,7 @@ void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
1173
1170
  } else if (d == (double)(long long int)d) {
1174
1171
  cnt = snprintf(buf, sizeof(buf), "%.1f", d);
1175
1172
  } else if (0 == out->opts->float_prec) {
1176
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
1173
+ volatile VALUE rstr = oj_safe_string_convert(obj);
1177
1174
 
1178
1175
  cnt = (int)RSTRING_LEN(rstr);
1179
1176
  if ((int)sizeof(buf) <= cnt) {
@@ -1195,7 +1192,7 @@ int oj_dump_float_printf(char *buf, size_t blen, VALUE obj, double d, const char
1195
1192
  // Round off issues at 16 significant digits so check for obvious ones of
1196
1193
  // 0001 and 9999.
1197
1194
  if (17 <= cnt && (0 == strcmp("0001", buf + cnt - 4) || 0 == strcmp("9999", buf + cnt - 4))) {
1198
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
1195
+ volatile VALUE rstr = oj_safe_string_convert(obj);
1199
1196
 
1200
1197
  strcpy(buf, RSTRING_PTR(rstr));
1201
1198
  cnt = (int)RSTRING_LEN(rstr);
data/ext/oj/dump_compat.c CHANGED
@@ -109,17 +109,13 @@ dump_to_json(VALUE obj, Out out) {
109
109
  const char *s;
110
110
  int len;
111
111
 
112
- if (RB_UNLIKELY(Yes == out->opts->trace)) {
113
- oj_trace("to_json", obj, __FILE__, __LINE__, 0, TraceRubyIn);
114
- }
112
+ TRACE(out->opts->trace, "to_json", obj, 0, TraceRubyIn);
115
113
  if (0 == rb_obj_method_arity(obj, oj_to_json_id)) {
116
114
  rs = rb_funcall(obj, oj_to_json_id, 0);
117
115
  } else {
118
116
  rs = rb_funcall2(obj, oj_to_json_id, out->argc, out->argv);
119
117
  }
120
- if (RB_UNLIKELY(Yes == out->opts->trace)) {
121
- oj_trace("to_json", obj, __FILE__, __LINE__, 0, TraceRubyOut);
122
- }
118
+ TRACE(out->opts->trace, "to_json", obj, 0, TraceRubyOut);
123
119
 
124
120
  s = RSTRING_PTR(rs);
125
121
  len = (int)RSTRING_LEN(rs);
@@ -299,7 +295,7 @@ datetime_alt(VALUE obj, int depth, Out out) {
299
295
  attrs[3].value = rb_funcall(obj, hour_id, 0);
300
296
  attrs[4].value = rb_funcall(obj, min_id, 0);
301
297
  attrs[5].value = rb_funcall(obj, sec_id, 0);
302
- attrs[6].value = rb_funcall(rb_funcall(obj, offset_id, 0), oj_to_s_id, 0);
298
+ attrs[6].value = oj_safe_string_convert(rb_funcall(obj, offset_id, 0));
303
299
  attrs[7].value = rb_funcall(obj, start_id, 0);
304
300
 
305
301
  oj_code_attrs(obj, attrs, depth, out, true);
@@ -606,7 +602,7 @@ dump_float(VALUE obj, int depth, Out out, bool as_ok) {
606
602
  } else if (oj_rails_float_opt) {
607
603
  cnt = oj_dump_float_printf(buf, sizeof(buf), obj, d, "%0.16g");
608
604
  } else {
609
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
605
+ volatile VALUE rstr = oj_safe_string_convert(obj);
610
606
 
611
607
  strcpy(buf, RSTRING_PTR(rstr));
612
608
  cnt = (int)RSTRING_LEN(rstr);
@@ -648,7 +644,7 @@ hash_cb(VALUE key, VALUE value, VALUE ov) {
648
644
  break;
649
645
  default:
650
646
  /*rb_raise(rb_eTypeError, "In :compat mode all Hash keys must be Strings or Symbols, not %s.\n", rb_class2name(rb_obj_class(key)));*/
651
- oj_dump_str(rb_funcall(key, oj_to_s_id, 0), 0, out, false);
647
+ oj_dump_str(oj_safe_string_convert(key), 0, out, false);
652
648
  break;
653
649
  }
654
650
  if (!out->opts->dump_opts.use) {
@@ -833,7 +829,7 @@ dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
833
829
  if (use_bignum_alt) {
834
830
  rs = rb_big2str(obj, 10);
835
831
  } else {
836
- rs = rb_funcall(obj, oj_to_s_id, 0);
832
+ rs = oj_safe_string_convert(obj);
837
833
  }
838
834
  rb_check_type(rs, T_STRING);
839
835
  cnt = (int)RSTRING_LEN(rs);
@@ -893,9 +889,7 @@ void
893
889
  oj_dump_compat_val(VALUE obj, int depth, Out out, bool as_ok) {
894
890
  int type = rb_type(obj);
895
891
 
896
- if (RB_UNLIKELY(Yes == out->opts->trace)) {
897
- oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
898
- }
892
+ TRACE(out->opts->trace, "dump", obj, depth, TraceIn);
899
893
  if (out->opts->dump_opts.max_depth <= depth) {
900
894
  // When JSON.dump is called then an ArgumentError is expected and the
901
895
  // limit is the depth inclusive. If JSON.generate is called then a
@@ -918,14 +912,10 @@ oj_dump_compat_val(VALUE obj, int depth, Out out, bool as_ok) {
918
912
 
919
913
  if (NULL != f) {
920
914
  f(obj, depth, out, as_ok);
921
- if (RB_UNLIKELY(Yes == out->opts->trace)) {
922
- oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
923
- }
915
+ TRACE(out->opts->trace, "dump", obj, depth, TraceOut);
924
916
  return;
925
917
  }
926
918
  }
927
919
  oj_dump_nil(Qnil, depth, out, false);
928
- if (RB_UNLIKELY(Yes == out->opts->trace)) {
929
- oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
930
- }
920
+ TRACE(out->opts->trace, "dump", Qnil, depth, TraceOut);
931
921
  }