oj 3.13.9 → 3.13.12

Sign up to get free protection for your applications and to get access to all the features.
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);