oj 3.13.9 → 3.13.12

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.
data/ext/oj/intern.h CHANGED
@@ -9,7 +9,7 @@
9
9
 
10
10
  struct _parseInfo;
11
11
 
12
- extern void oj_hash_init();
12
+ extern void oj_hash_init(void);
13
13
 
14
14
  extern VALUE oj_str_intern(const char *key, size_t len);
15
15
  extern VALUE oj_sym_intern(const char *key, size_t len);
data/ext/oj/mimic_json.c CHANGED
@@ -198,7 +198,6 @@ static int mimic_limit_arg(VALUE a) {
198
198
  * Returns [_String_] a JSON string.
199
199
  */
200
200
  static VALUE mimic_dump(int argc, VALUE *argv, VALUE self) {
201
- char buf[4096];
202
201
  struct _out out;
203
202
  struct _options copts = oj_default_options;
204
203
  VALUE rstr;
@@ -206,9 +205,9 @@ static VALUE mimic_dump(int argc, VALUE *argv, VALUE self) {
206
205
 
207
206
  copts.str_rx.head = NULL;
208
207
  copts.str_rx.tail = NULL;
209
- out.buf = buf;
210
- out.end = buf + sizeof(buf) - 10;
211
- out.allocated = false;
208
+
209
+ oj_out_init(&out);
210
+
212
211
  out.caller = CALLER_DUMP;
213
212
  copts.escape_mode = JXEsc;
214
213
  copts.mode = CompatMode;
@@ -257,9 +256,9 @@ static VALUE mimic_dump(int argc, VALUE *argv, VALUE self) {
257
256
  rb_funcall2(io, oj_write_id, 1, args);
258
257
  rstr = io;
259
258
  }
260
- if (out.allocated) {
261
- xfree(out.buf);
262
- }
259
+
260
+ oj_out_free(&out);
261
+
263
262
  return rstr;
264
263
  }
265
264
 
@@ -272,7 +271,7 @@ static int mimic_walk(VALUE key, VALUE obj, VALUE proc) {
272
271
  size_t i;
273
272
 
274
273
  for (i = 0; i < cnt; i++) {
275
- mimic_walk(Qnil, rb_ary_entry(obj, i), proc);
274
+ mimic_walk(Qnil, RARRAY_AREF(obj, i), proc);
276
275
  }
277
276
  break;
278
277
  }
@@ -358,15 +357,16 @@ static VALUE mimic_dump_load(int argc, VALUE *argv, VALUE self) {
358
357
  }
359
358
 
360
359
  static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
361
- char buf[4096];
362
360
  struct _out out;
363
361
  VALUE rstr;
364
362
 
365
- memset(buf, 0, sizeof(buf));
363
+ if (0 == argc) {
364
+ rb_raise(rb_eArgError, "wrong number of arguments (0))");
365
+ }
366
+ memset(out.stack_buffer, 0, sizeof(out.stack_buffer));
367
+
368
+ oj_out_init(&out);
366
369
 
367
- out.buf = buf;
368
- out.end = buf + sizeof(buf) - 10;
369
- out.allocated = false;
370
370
  out.omit_nil = copts->dump_opts.omit_nil;
371
371
  out.caller = CALLER_GENERATE;
372
372
  // For obj.to_json or generate nan is not allowed but if called from dump
@@ -398,9 +398,9 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
398
398
  }
399
399
  rstr = rb_str_new2(out.buf);
400
400
  rstr = oj_encode(rstr);
401
- if (out.allocated) {
402
- xfree(out.buf);
403
- }
401
+
402
+ oj_out_free(&out);
403
+
404
404
  return rstr;
405
405
  }
406
406
 
@@ -457,9 +457,12 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
457
457
  // a Hash. I haven't dug deep enough to find out why but using a State
458
458
  // instance and not a Hash gives the desired behavior.
459
459
  *rargs = *argv;
460
+ if (0 == argc) {
461
+ rb_raise(rb_eArgError, "wrong number of arguments (0))");
462
+ }
460
463
  if (1 == argc) {
461
464
  h = rb_hash_new();
462
- } else {
465
+ } else {
463
466
  h = argv[1];
464
467
  }
465
468
  if (!oj_hash_has_key(h, oj_indent_sym)) {
@@ -499,6 +502,52 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
499
502
  return mimic_generate_core(2, rargs, &copts);
500
503
  }
501
504
 
505
+ static int parse_options_cb(VALUE k, VALUE v, VALUE info) {
506
+ struct _parseInfo *pi = (struct _parseInfo *)info;
507
+
508
+ if (oj_symbolize_names_sym == k) {
509
+ pi->options.sym_key = (Qtrue == v) ? Yes : No;
510
+ } else if (oj_quirks_mode_sym == k) {
511
+ pi->options.quirks_mode = (Qtrue == v) ? Yes : No;
512
+ } else if (oj_create_additions_sym == k) {
513
+ pi->options.create_ok = (Qtrue == v) ? Yes : No;
514
+ } else if (oj_allow_nan_sym == k) {
515
+ pi->options.allow_nan = (Qtrue == v) ? Yes : No;
516
+ } else if (oj_hash_class_sym == k) {
517
+ if (Qnil == v) {
518
+ pi->options.hash_class = Qnil;
519
+ } else {
520
+ rb_check_type(v, T_CLASS);
521
+ pi->options.hash_class = v;
522
+ }
523
+ } else if (oj_object_class_sym == k) {
524
+ if (Qnil == v) {
525
+ pi->options.hash_class = Qnil;
526
+ } else {
527
+ rb_check_type(v, T_CLASS);
528
+ pi->options.hash_class = v;
529
+ }
530
+ } else if (oj_array_class_sym == k) {
531
+ if (Qnil == v) {
532
+ pi->options.array_class = Qnil;
533
+ } else {
534
+ rb_check_type(v, T_CLASS);
535
+ pi->options.array_class = v;
536
+ }
537
+ } else if (oj_decimal_class_sym == k) {
538
+ pi->options.compat_bigdec = (oj_bigdecimal_class == v);
539
+ } else if (oj_max_nesting_sym == k) {
540
+ if (Qtrue == v) {
541
+ pi->max_depth = 100;
542
+ } else if (Qfalse == v || Qnil == v) {
543
+ pi->max_depth = 0;
544
+ } else if (T_FIXNUM == rb_type(v)) {
545
+ pi->max_depth = NUM2INT(v);
546
+ }
547
+ }
548
+ return ST_CONTINUE;
549
+ }
550
+
502
551
  static VALUE mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
503
552
  struct _parseInfo pi;
504
553
  VALUE ropts;
@@ -524,59 +573,11 @@ static VALUE mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
524
573
  pi.max_depth = 100;
525
574
 
526
575
  if (Qnil != ropts) {
527
- VALUE v;
528
-
529
576
  if (T_HASH != rb_type(ropts)) {
530
577
  rb_raise(rb_eArgError, "options must be a hash.");
531
578
  }
532
- if (Qnil != (v = rb_hash_lookup(ropts, oj_symbolize_names_sym))) {
533
- pi.options.sym_key = (Qtrue == v) ? Yes : No;
534
- }
535
- if (Qnil != (v = rb_hash_lookup(ropts, oj_quirks_mode_sym))) {
536
- pi.options.quirks_mode = (Qtrue == v) ? Yes : No;
537
- }
538
- if (Qnil != (v = rb_hash_lookup(ropts, oj_create_additions_sym))) {
539
- pi.options.create_ok = (Qtrue == v) ? Yes : No;
540
- }
541
- if (Qnil != (v = rb_hash_lookup(ropts, oj_allow_nan_sym))) {
542
- pi.options.allow_nan = (Qtrue == v) ? Yes : No;
543
- }
544
579
 
545
- if (oj_hash_has_key(ropts, oj_hash_class_sym)) {
546
- if (Qnil == (v = rb_hash_lookup(ropts, oj_hash_class_sym))) {
547
- pi.options.hash_class = Qnil;
548
- } else {
549
- rb_check_type(v, T_CLASS);
550
- pi.options.hash_class = v;
551
- }
552
- }
553
- if (oj_hash_has_key(ropts, oj_object_class_sym)) {
554
- if (Qnil == (v = rb_hash_lookup(ropts, oj_object_class_sym))) {
555
- pi.options.hash_class = Qnil;
556
- } else {
557
- rb_check_type(v, T_CLASS);
558
- pi.options.hash_class = v;
559
- }
560
- }
561
- if (oj_hash_has_key(ropts, oj_array_class_sym)) {
562
- if (Qnil == (v = rb_hash_lookup(ropts, oj_array_class_sym))) {
563
- pi.options.array_class = Qnil;
564
- } else {
565
- rb_check_type(v, T_CLASS);
566
- pi.options.array_class = v;
567
- }
568
- }
569
- if (oj_hash_has_key(ropts, oj_decimal_class_sym)) {
570
- pi.options.compat_bigdec = (oj_bigdecimal_class == rb_hash_lookup(ropts, oj_decimal_class_sym));
571
- }
572
- v = rb_hash_lookup(ropts, oj_max_nesting_sym);
573
- if (Qtrue == v) {
574
- pi.max_depth = 100;
575
- } else if (Qfalse == v || Qnil == v) {
576
- pi.max_depth = 0;
577
- } else if (T_FIXNUM == rb_type(v)) {
578
- pi.max_depth = NUM2INT(v);
579
- }
580
+ rb_hash_foreach(ropts, parse_options_cb, (VALUE)&pi);
580
581
  oj_parse_opt_match_string(&pi.options.str_rx, ropts);
581
582
  if (Yes == pi.options.create_ok && Yes == pi.options.sym_key) {
582
583
  rb_raise(rb_eArgError, ":symbolize_names and :create_additions can not both be true.");
@@ -742,16 +743,15 @@ static struct _options mimic_object_to_json_options = {0, // indent
742
743
  }};
743
744
 
744
745
  static VALUE mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
745
- char buf[4096];
746
746
  struct _out out;
747
747
  VALUE rstr;
748
748
  struct _options copts = oj_default_options;
749
749
 
750
750
  copts.str_rx.head = NULL;
751
751
  copts.str_rx.tail = NULL;
752
- out.buf = buf;
753
- out.end = buf + sizeof(buf) - 10;
754
- out.allocated = false;
752
+
753
+ oj_out_init(&out);
754
+
755
755
  out.omit_nil = copts.dump_opts.omit_nil;
756
756
  copts.mode = CompatMode;
757
757
  copts.to_json = No;
@@ -767,9 +767,9 @@ static VALUE mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
767
767
  }
768
768
  rstr = rb_str_new2(out.buf);
769
769
  rstr = oj_encode(rstr);
770
- if (out.allocated) {
771
- xfree(out.buf);
772
- }
770
+
771
+ oj_out_free(&out);
772
+
773
773
  return rstr;
774
774
  }
775
775
 
data/ext/oj/object.c CHANGED
@@ -325,7 +325,7 @@ static int hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, vol
325
325
  int i, cnt = (int)RARRAY_LEN(e1);
326
326
 
327
327
  for (i = 0; i < cnt; i++) {
328
- rstr = rb_ary_entry(e1, i);
328
+ rstr = RARRAY_AREF(e1, i);
329
329
  args[i] = rb_funcall(rstr, oj_to_sym_id, 0);
330
330
  }
331
331
  sc = rb_funcall2(rb_cStruct, oj_new_id, cnt, args);
data/ext/oj/odd.c CHANGED
@@ -5,28 +5,27 @@
5
5
 
6
6
  #include <string.h>
7
7
 
8
- static struct _odd _odds[4]; // bump up if new initial Odd classes are added
9
- static struct _odd *odds = _odds;
10
- static long odd_cnt = 0;
11
- static ID sec_id;
12
- static ID sec_fraction_id;
13
- static ID to_f_id;
14
- static ID numerator_id;
15
- static ID denominator_id;
16
- static ID rational_id;
17
- static VALUE rational_class;
8
+ static Odd odds = NULL;
9
+ static ID sec_id;
10
+ static ID sec_fraction_id;
11
+ static ID to_f_id;
12
+ static ID numerator_id;
13
+ static ID denominator_id;
14
+ static ID rational_id;
18
15
 
19
16
  static void set_class(Odd odd, const char *classname) {
20
17
  const char **np;
21
- ID * idp;
18
+ ID *idp;
22
19
 
23
- odd->classname = classname;
24
- odd->clen = strlen(classname);
25
- odd->clas = rb_const_get(rb_cObject, rb_intern(classname));
20
+ odd->classname = classname;
21
+ odd->clen = strlen(classname);
22
+ odd->clas = rb_const_get(rb_cObject, rb_intern(classname));
23
+ rb_gc_register_mark_object(odd->clas);
26
24
  odd->create_obj = odd->clas;
27
- odd->create_op = rb_intern("new");
28
- odd->is_module = (T_MODULE == rb_type(odd->clas));
29
- odd->raw = 0;
25
+ rb_gc_register_mark_object(odd->create_obj);
26
+ odd->create_op = rb_intern("new");
27
+ odd->is_module = (T_MODULE == rb_type(odd->clas));
28
+ odd->raw = 0;
30
29
  for (np = odd->attr_names, idp = odd->attrs; 0 != *np; np++, idp++) {
31
30
  *idp = rb_intern(*np);
32
31
  }
@@ -37,15 +36,48 @@ static VALUE get_datetime_secs(VALUE obj) {
37
36
  volatile VALUE rsecs = rb_funcall(obj, sec_id, 0);
38
37
  volatile VALUE rfrac = rb_funcall(obj, sec_fraction_id, 0);
39
38
  long sec = NUM2LONG(rsecs);
40
- long long num = rb_num2ll(rb_funcall(rfrac, numerator_id, 0));
41
- long long den = rb_num2ll(rb_funcall(rfrac, denominator_id, 0));
39
+ long long num = NUM2LL(rb_funcall(rfrac, numerator_id, 0));
40
+ long long den = NUM2LL(rb_funcall(rfrac, denominator_id, 0));
42
41
 
43
42
  num += sec * den;
44
43
 
45
44
  return rb_funcall(rb_cObject, rational_id, 2, rb_ll2inum(num), rb_ll2inum(den));
46
45
  }
47
46
 
48
- void oj_odd_init() {
47
+ static void print_odd(Odd odd) {
48
+ const char **np;
49
+ int i;
50
+
51
+ printf(" %s {\n", odd->classname);
52
+ printf(" attr_cnt: %d %p\n", odd->attr_cnt, (void *)odd->attr_names);
53
+ printf(" attr_names: %p\n", (void *)*odd->attr_names);
54
+ printf(" attr_names: %c\n", **odd->attr_names);
55
+ for (i = odd->attr_cnt, np = odd->attr_names; 0 < i; i--, np++) {
56
+ printf(" %d %s\n", i, *np);
57
+ }
58
+ printf(" }\n");
59
+ }
60
+
61
+ void print_all_odds(const char *label) {
62
+ Odd odd;
63
+ printf("@ %s {\n", label);
64
+ for (odd = odds; NULL != odd; odd = odd->next) {
65
+ print_odd(odd);
66
+ }
67
+ printf("}\n");
68
+ }
69
+
70
+ static Odd odd_create(void) {
71
+ Odd odd = ALLOC(struct _odd);
72
+
73
+ memset(odd, 0, sizeof(struct _odd));
74
+ odd->next = odds;
75
+ odds = odd;
76
+
77
+ return odd;
78
+ }
79
+
80
+ void oj_odd_init(void) {
49
81
  Odd odd;
50
82
  const char **np;
51
83
 
@@ -55,11 +87,9 @@ void oj_odd_init() {
55
87
  numerator_id = rb_intern("numerator");
56
88
  denominator_id = rb_intern("denominator");
57
89
  rational_id = rb_intern("Rational");
58
- rational_class = rb_const_get(rb_cObject, rational_id);
59
90
 
60
- memset(_odds, 0, sizeof(_odds));
61
- odd = odds;
62
91
  // Rational
92
+ odd = odd_create();
63
93
  np = odd->attr_names;
64
94
  *np++ = "numerator";
65
95
  *np++ = "denominator";
@@ -68,8 +98,9 @@ void oj_odd_init() {
68
98
  odd->create_obj = rb_cObject;
69
99
  odd->create_op = rational_id;
70
100
  odd->attr_cnt = 2;
101
+
71
102
  // Date
72
- odd++;
103
+ odd = odd_create();
73
104
  np = odd->attr_names;
74
105
  *np++ = "year";
75
106
  *np++ = "month";
@@ -78,8 +109,9 @@ void oj_odd_init() {
78
109
  *np++ = 0;
79
110
  set_class(odd, "Date");
80
111
  odd->attr_cnt = 4;
112
+
81
113
  // DateTime
82
- odd++;
114
+ odd = odd_create();
83
115
  np = odd->attr_names;
84
116
  *np++ = "year";
85
117
  *np++ = "month";
@@ -93,8 +125,9 @@ void oj_odd_init() {
93
125
  set_class(odd, "DateTime");
94
126
  odd->attr_cnt = 8;
95
127
  odd->attrFuncs[5] = get_datetime_secs;
128
+
96
129
  // Range
97
- odd++;
130
+ odd = odd_create();
98
131
  np = odd->attr_names;
99
132
  *np++ = "begin";
100
133
  *np++ = "end";
@@ -102,15 +135,13 @@ void oj_odd_init() {
102
135
  *np++ = 0;
103
136
  set_class(odd, "Range");
104
137
  odd->attr_cnt = 3;
105
-
106
- odd_cnt = odd - odds + 1;
107
138
  }
108
139
 
109
140
  Odd oj_get_odd(VALUE clas) {
110
141
  Odd odd;
111
142
  const char *classname = NULL;
112
143
 
113
- for (odd = odds + odd_cnt - 1; odds <= odd; odd--) {
144
+ for (odd = odds; NULL != odd; odd = odd->next) {
114
145
  if (clas == odd->clas) {
115
146
  return odd;
116
147
  }
@@ -129,21 +160,20 @@ Odd oj_get_odd(VALUE clas) {
129
160
  Odd oj_get_oddc(const char *classname, size_t len) {
130
161
  Odd odd;
131
162
 
132
- for (odd = odds + odd_cnt - 1; odds <= odd; odd--) {
163
+ for (odd = odds; NULL != odd; odd = odd->next) {
133
164
  if (len == odd->clen && 0 == strncmp(classname, odd->classname, len)) {
134
165
  return odd;
135
166
  }
136
- if (odd->is_module && 0 == strncmp(odd->classname, classname, odd->clen) &&
137
- ':' == classname[odd->clen]) {
167
+ if (odd->is_module && 0 == strncmp(odd->classname, classname, odd->clen) && ':' == classname[odd->clen]) {
138
168
  return odd;
139
169
  }
140
170
  }
141
- return 0;
171
+ return NULL;
142
172
  }
143
173
 
144
174
  OddArgs oj_odd_alloc_args(Odd odd) {
145
175
  OddArgs oa = ALLOC_N(struct _oddArgs, 1);
146
- VALUE * a;
176
+ VALUE *a;
147
177
  int i;
148
178
 
149
179
  oa->odd = odd;
@@ -159,11 +189,10 @@ void oj_odd_free(OddArgs args) {
159
189
 
160
190
  int oj_odd_set_arg(OddArgs args, const char *key, size_t klen, VALUE value) {
161
191
  const char **np;
162
- VALUE * vp;
192
+ VALUE *vp;
163
193
  int i;
164
194
 
165
- for (i = args->odd->attr_cnt, np = args->odd->attr_names, vp = args->args; 0 < i;
166
- i--, np++, vp++) {
195
+ for (i = args->odd->attr_cnt, np = args->odd->attr_names, vp = args->args; 0 < i; i--, np++, vp++) {
167
196
  if (0 == strncmp(key, *np, klen) && '\0' == *((*np) + klen)) {
168
197
  *vp = value;
169
198
  return 0;
@@ -172,37 +201,26 @@ int oj_odd_set_arg(OddArgs args, const char *key, size_t klen, VALUE value) {
172
201
  return -1;
173
202
  }
174
203
 
175
- void oj_reg_odd(VALUE clas,
176
- VALUE create_object,
177
- VALUE create_method,
178
- int mcnt,
179
- VALUE *members,
180
- bool raw) {
204
+ void oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt, VALUE *members, bool raw) {
181
205
  Odd odd;
182
206
  const char **np;
183
- ID * ap;
207
+ ID *ap;
184
208
  AttrGetFunc *fp;
185
209
 
186
- if (_odds == odds) {
187
- odds = ALLOC_N(struct _odd, odd_cnt + 1);
188
-
189
- memcpy(odds, _odds, sizeof(struct _odd) * odd_cnt);
190
- } else {
191
- REALLOC_N(odds, struct _odd, odd_cnt + 1);
192
- }
193
- odd = odds + odd_cnt;
210
+ odd = odd_create();
194
211
  odd->clas = clas;
212
+ rb_gc_register_mark_object(odd->clas);
195
213
  if (NULL == (odd->classname = strdup(rb_class2name(clas)))) {
196
- rb_raise(rb_eNoMemError, "for attribute name.");
214
+ rb_raise(rb_eNoMemError, "for class name.");
197
215
  }
198
216
  odd->clen = strlen(odd->classname);
199
217
  odd->create_obj = create_object;
200
- odd->create_op = SYM2ID(create_method);
201
- odd->attr_cnt = mcnt;
202
- odd->is_module = (T_MODULE == rb_type(clas));
203
- odd->raw = raw;
204
- for (ap = odd->attrs, np = odd->attr_names, fp = odd->attrFuncs; 0 < mcnt;
205
- mcnt--, ap++, np++, members++, fp++) {
218
+ rb_gc_register_mark_object(odd->create_obj);
219
+ odd->create_op = SYM2ID(create_method);
220
+ odd->attr_cnt = mcnt;
221
+ odd->is_module = (T_MODULE == rb_type(clas));
222
+ odd->raw = raw;
223
+ for (ap = odd->attrs, np = odd->attr_names, fp = odd->attrFuncs; 0 < mcnt; mcnt--, ap++, np++, members++, fp++) {
206
224
  *fp = 0;
207
225
  switch (rb_type(*members)) {
208
226
  case T_STRING:
@@ -210,14 +228,16 @@ void oj_reg_odd(VALUE clas,
210
228
  rb_raise(rb_eNoMemError, "for attribute name.");
211
229
  }
212
230
  break;
213
- case T_SYMBOL: *np = rb_id2name(SYM2ID(*members)); break;
214
- default:
215
- rb_raise(rb_eArgError, "registered member identifiers must be Strings or Symbols.");
231
+ case T_SYMBOL:
232
+ // The symbol can move and invalidate the name so make a copy.
233
+ if (NULL == (*np = strdup(rb_id2name(SYM2ID(*members))))) {
234
+ rb_raise(rb_eNoMemError, "for attribute name.");
235
+ }
216
236
  break;
237
+ default: rb_raise(rb_eArgError, "registered member identifiers must be Strings or Symbols."); break;
217
238
  }
218
239
  *ap = rb_intern(*np);
219
240
  }
220
241
  *np = 0;
221
242
  *ap = 0;
222
- odd_cnt++;
223
243
  }
data/ext/oj/odd.h CHANGED
@@ -13,17 +13,18 @@
13
13
  typedef VALUE (*AttrGetFunc)(VALUE obj);
14
14
 
15
15
  typedef struct _odd {
16
- const char *classname;
17
- size_t clen;
18
- VALUE clas; // Ruby class or module
19
- VALUE create_obj;
20
- ID create_op;
21
- int attr_cnt;
22
- bool is_module;
23
- bool raw;
24
- const char *attr_names[MAX_ODD_ARGS]; // NULL terminated attr names
25
- ID attrs[MAX_ODD_ARGS]; // 0 terminated attr IDs
26
- AttrGetFunc attrFuncs[MAX_ODD_ARGS];
16
+ struct _odd *next;
17
+ const char * classname;
18
+ size_t clen;
19
+ VALUE clas; // Ruby class or module
20
+ VALUE create_obj;
21
+ ID create_op;
22
+ int attr_cnt;
23
+ bool is_module;
24
+ bool raw;
25
+ const char * attr_names[MAX_ODD_ARGS]; // NULL terminated attr names
26
+ ID attrs[MAX_ODD_ARGS]; // 0 terminated attr IDs
27
+ AttrGetFunc attrFuncs[MAX_ODD_ARGS];
27
28
  } * Odd;
28
29
 
29
30
  typedef struct _oddArgs {
@@ -37,7 +38,6 @@ extern Odd oj_get_oddc(const char *classname, size_t len);
37
38
  extern OddArgs oj_odd_alloc_args(Odd odd);
38
39
  extern void oj_odd_free(OddArgs args);
39
40
  extern int oj_odd_set_arg(OddArgs args, const char *key, size_t klen, VALUE value);
40
- extern void
41
- oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt, VALUE *members, bool raw);
41
+ extern void oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt, VALUE *members, bool raw);
42
42
 
43
43
  #endif /* OJ_ODD_H */
data/ext/oj/oj.c CHANGED
@@ -153,6 +153,7 @@ static VALUE xmlschema_sym;
153
153
  static VALUE xss_safe_sym;
154
154
 
155
155
  rb_encoding *oj_utf8_encoding = 0;
156
+ int oj_utf8_encoding_index = 0;
156
157
 
157
158
  #ifdef HAVE_PTHREAD_MUTEX_INIT
158
159
  pthread_mutex_t oj_cache_mutex;
@@ -916,7 +917,7 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
916
917
 
917
918
  copts->ignore = ALLOC_N(VALUE, cnt + 1);
918
919
  for (i = 0; i < cnt; i++) {
919
- copts->ignore[i] = rb_ary_entry(v, i);
920
+ copts->ignore[i] = RARRAY_AREF(v, i);
920
921
  }
921
922
  copts->ignore[i] = Qnil;
922
923
  }
@@ -1243,9 +1244,8 @@ static VALUE dump_body(VALUE a) {
1243
1244
  static VALUE dump_ensure(VALUE a) {
1244
1245
  volatile struct dump_arg *arg = (void *)a;
1245
1246
 
1246
- if (arg->out->allocated) {
1247
- xfree(arg->out->buf);
1248
- }
1247
+ oj_out_free(arg->out);
1248
+
1249
1249
  return Qnil;
1250
1250
  }
1251
1251
 
@@ -1257,7 +1257,6 @@ static VALUE dump_ensure(VALUE a) {
1257
1257
  * - *options* [_Hash_] same as default_options
1258
1258
  */
1259
1259
  static VALUE dump(int argc, VALUE *argv, VALUE self) {
1260
- char buf[4096];
1261
1260
  struct dump_arg arg;
1262
1261
  struct _out out;
1263
1262
  struct _options copts = oj_default_options;
@@ -1279,9 +1278,8 @@ static VALUE dump(int argc, VALUE *argv, VALUE self) {
1279
1278
  arg.argc = argc;
1280
1279
  arg.argv = argv;
1281
1280
 
1282
- arg.out->buf = buf;
1283
- arg.out->end = buf + sizeof(buf) - 10;
1284
- arg.out->allocated = false;
1281
+ oj_out_init(arg.out);
1282
+
1285
1283
  arg.out->omit_nil = copts.dump_opts.omit_nil;
1286
1284
  arg.out->caller = CALLER_DUMP;
1287
1285
 
@@ -1313,7 +1311,6 @@ static VALUE dump(int argc, VALUE *argv, VALUE self) {
1313
1311
  * Returns [_String_] the encoded JSON.
1314
1312
  */
1315
1313
  static VALUE to_json(int argc, VALUE *argv, VALUE self) {
1316
- char buf[4096];
1317
1314
  struct _out out;
1318
1315
  struct _options copts = oj_default_options;
1319
1316
  VALUE rstr;
@@ -1328,9 +1325,9 @@ static VALUE to_json(int argc, VALUE *argv, VALUE self) {
1328
1325
  }
1329
1326
  copts.mode = CompatMode;
1330
1327
  copts.to_json = Yes;
1331
- out.buf = buf;
1332
- out.end = buf + sizeof(buf) - 10;
1333
- out.allocated = false;
1328
+
1329
+ oj_out_init(&out);
1330
+
1334
1331
  out.omit_nil = copts.dump_opts.omit_nil;
1335
1332
  // For obj.to_json or generate nan is not allowed but if called from dump
1336
1333
  // it is.
@@ -1341,9 +1338,9 @@ static VALUE to_json(int argc, VALUE *argv, VALUE self) {
1341
1338
  }
1342
1339
  rstr = rb_str_new2(out.buf);
1343
1340
  rstr = oj_encode(rstr);
1344
- if (out.allocated) {
1345
- xfree(out.buf);
1346
- }
1341
+
1342
+ oj_out_free(&out);
1343
+
1347
1344
  return rstr;
1348
1345
  }
1349
1346
 
@@ -1703,6 +1700,15 @@ static VALUE protect_require(VALUE x) {
1703
1700
  return Qnil;
1704
1701
  }
1705
1702
 
1703
+ extern void print_all_odds(const char *label);
1704
+
1705
+ static VALUE
1706
+ debug_odd(VALUE self, VALUE label) {
1707
+ print_all_odds(RSTRING_PTR(label));
1708
+ return Qnil;
1709
+ }
1710
+
1711
+
1706
1712
  /* Document-module: Oj
1707
1713
  *
1708
1714
  * Optimized JSON (Oj), as the name implies was written to provide speed
@@ -1731,15 +1737,19 @@ static VALUE protect_require(VALUE x) {
1731
1737
  *
1732
1738
  * - *:wab* specifically for WAB data exchange.
1733
1739
  */
1734
- void Init_oj() {
1740
+ void Init_oj(void) {
1735
1741
  int err = 0;
1736
1742
 
1737
1743
  #if HAVE_RB_EXT_RACTOR_SAFE
1738
1744
  rb_ext_ractor_safe(true);
1739
1745
  #endif
1740
1746
  Oj = rb_define_module("Oj");
1747
+ rb_gc_register_address(&Oj);
1741
1748
 
1742
1749
  oj_cstack_class = rb_define_class_under(Oj, "CStack", rb_cObject);
1750
+ rb_gc_register_address(&oj_cstack_class);
1751
+
1752
+ rb_undef_alloc_func(oj_cstack_class);
1743
1753
 
1744
1754
  oj_string_writer_init();
1745
1755
  oj_stream_writer_init();
@@ -1748,9 +1758,11 @@ void Init_oj() {
1748
1758
  // On Rubinius the require fails but can be done from a ruby file.
1749
1759
  rb_protect(protect_require, Qnil, &err);
1750
1760
  rb_require("stringio");
1751
- oj_utf8_encoding = rb_enc_find("UTF-8");
1761
+ oj_utf8_encoding_index = rb_enc_find_index("UTF-8");
1762
+ oj_utf8_encoding = rb_enc_from_index(oj_utf8_encoding_index);
1752
1763
 
1753
1764
  // rb_define_module_function(Oj, "hash_test", hash_test, 0);
1765
+ rb_define_module_function(Oj, "debug_odd", debug_odd, 1);
1754
1766
 
1755
1767
  rb_define_module_function(Oj, "default_options", get_def_opts, 0);
1756
1768
  rb_define_module_function(Oj, "default_options=", set_def_opts, 1);