oj 3.13.23 → 3.14.2

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: 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
  }