oj 3.11.7 → 3.12.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: 7ba25f766c9a47418e68db380346e3049b745fe7a84f7347eb747e1e78fcde68
4
- data.tar.gz: 4c0b5d9c78c2aef12ab964fde407e8b50a7666135b2b8c59f0781d55b49f6f39
3
+ metadata.gz: 89a87064f6668864cec4ab0c43892b4950c8ef7a9f7ea3da22f459af5bcd0083
4
+ data.tar.gz: bc078e8b28d710a2194e2943343db687ec15d35d2556efff2f9e46936f3bb0b0
5
5
  SHA512:
6
- metadata.gz: b950019944966b5a92839092463f45454e4f6f7178ce6e3fd9be6157a1a82891d65f7c058f4e9adcf200e074759ae2c1c679874e780509fd7151c06151c2dc4b
7
- data.tar.gz: 28368e1b926b053656357edec71bf595886a61c71c7cdd46f87217587970d3589a71f373ed478db407fa08bd7c79919ae613cd6180dc90b29f4f802c265436f9
6
+ metadata.gz: 95cb66c13e871bf85a351348b0c458c53fe2cd4057886396a62b763386fafe5d99c97143151808eb70dd526b8f13740cd43e266805c6b3454eac1be6940897db
7
+ data.tar.gz: '09e24c7ec1daf2c10850b071eb4060aed265db662a92a78439eee1746b22437396f3358f82d982e040874c0916af3c38def244e03416e4971c2c5649823ff7c2'
data/ext/oj/compat.c CHANGED
@@ -23,14 +23,34 @@ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, c
23
23
  parent->classname = oj_strndup(str, len);
24
24
  parent->clen = len;
25
25
  } else {
26
- volatile VALUE rstr = rb_str_new(str, len);
26
+ volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
27
27
 
28
28
  if (Qundef == rkey) {
29
- rkey = rb_str_new(key, klen);
30
- rstr = oj_encode(rstr);
31
- rkey = oj_encode(rkey);
32
- if (Yes == pi->options.sym_key) {
33
- rkey = rb_str_intern(rkey);
29
+ if (Yes != pi->options.cache_keys) {
30
+ rkey = rb_str_new(key, klen);
31
+ rkey = oj_encode(rkey);
32
+ if (Yes == pi->options.sym_key) {
33
+ rkey = rb_str_intern(rkey);
34
+ }
35
+ } else {
36
+ VALUE *slot;
37
+
38
+ if (Yes == pi->options.sym_key) {
39
+ if (Qnil == (rkey = oj_sym_hash_get(key, klen, &slot))) {
40
+ rkey = rb_str_new(key, klen);
41
+ rkey = oj_encode(rkey);
42
+ rkey = rb_str_intern(rkey);
43
+ *slot = rkey;
44
+ rb_gc_register_address(slot);
45
+ }
46
+ } else {
47
+ if (Qnil == (rkey = oj_str_hash_get(key, klen, &slot))) {
48
+ rkey = rb_str_new(key, klen);
49
+ rkey = oj_encode(rkey);
50
+ *slot = rkey;
51
+ rb_gc_register_address(slot);
52
+ }
53
+ }
34
54
  }
35
55
  }
36
56
  if (Yes == pi->options.create_ok && NULL != pi->options.str_rx.head) {
@@ -93,23 +113,9 @@ static void end_hash(struct _parseInfo *pi) {
93
113
  }
94
114
  }
95
115
 
96
- static VALUE calc_hash_key(ParseInfo pi, Val parent) {
97
- volatile VALUE rkey = parent->key_val;
98
-
99
- if (Qundef == rkey) {
100
- rkey = rb_str_new(parent->key, parent->klen);
101
- }
102
- rkey = oj_encode(rkey);
103
- if (Yes == pi->options.sym_key) {
104
- rkey = rb_str_intern(rkey);
105
- }
106
- return rkey;
107
- }
108
-
109
116
  static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
110
- volatile VALUE rstr = rb_str_new(str, len);
117
+ volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
111
118
 
112
- rstr = oj_encode(rstr);
113
119
  if (Yes == pi->options.create_ok && NULL != pi->options.str_rx.head) {
114
120
  VALUE clas = oj_rxclass_match(&pi->options.str_rx, str, (int)len);
115
121
 
@@ -142,10 +148,10 @@ static void hash_set_num(struct _parseInfo *pi, Val parent, NumInfo ni) {
142
148
  rb_funcall(stack_peek(&pi->stack)->val,
143
149
  rb_intern("[]="),
144
150
  2,
145
- calc_hash_key(pi, parent),
151
+ oj_calc_hash_key(pi, parent),
146
152
  rval);
147
153
  } else {
148
- rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), rval);
154
+ rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), rval);
149
155
  }
150
156
  if (Yes == pi->options.trace) {
151
157
  oj_trace_parse_call("set_number", pi, __FILE__, __LINE__, rval);
@@ -161,10 +167,10 @@ static void hash_set_value(ParseInfo pi, Val parent, VALUE value) {
161
167
  rb_funcall(stack_peek(&pi->stack)->val,
162
168
  rb_intern("[]="),
163
169
  2,
164
- calc_hash_key(pi, parent),
170
+ oj_calc_hash_key(pi, parent),
165
171
  value);
166
172
  } else {
167
- rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), value);
173
+ rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), value);
168
174
  }
169
175
  if (Yes == pi->options.trace) {
170
176
  oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
@@ -199,9 +205,8 @@ static void array_append_num(ParseInfo pi, NumInfo ni) {
199
205
  }
200
206
 
201
207
  static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
202
- volatile VALUE rstr = rb_str_new(str, len);
208
+ volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
203
209
 
204
- rstr = oj_encode(rstr);
205
210
  if (Yes == pi->options.create_ok && NULL != pi->options.str_rx.head) {
206
211
  VALUE clas = oj_rxclass_match(&pi->options.str_rx, str, (int)len);
207
212
 
data/ext/oj/custom.c CHANGED
@@ -955,6 +955,7 @@ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, c
955
955
  }
956
956
  }
957
957
  } else {
958
+ //volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
958
959
  volatile VALUE rstr = rb_str_new(str, len);
959
960
 
960
961
  if (Qundef == rkey) {
@@ -1010,19 +1011,6 @@ static void end_hash(struct _parseInfo *pi) {
1010
1011
  }
1011
1012
  }
1012
1013
 
1013
- static VALUE calc_hash_key(ParseInfo pi, Val parent) {
1014
- volatile VALUE rkey = parent->key_val;
1015
-
1016
- if (Qundef == rkey) {
1017
- rkey = rb_str_new(parent->key, parent->klen);
1018
- }
1019
- rkey = oj_encode(rkey);
1020
- if (Yes == pi->options.sym_key) {
1021
- rkey = rb_str_intern(rkey);
1022
- }
1023
- return rkey;
1024
- }
1025
-
1026
1014
  static void hash_set_num(struct _parseInfo *pi, Val kval, NumInfo ni) {
1027
1015
  Val parent = stack_peek(&pi->stack);
1028
1016
  volatile VALUE rval = oj_num_as_value(ni);
@@ -1067,7 +1055,7 @@ static void hash_set_num(struct _parseInfo *pi, Val kval, NumInfo ni) {
1067
1055
  }
1068
1056
  rval = parent->val;
1069
1057
  } else {
1070
- rb_hash_aset(parent->val, calc_hash_key(pi, kval), rval);
1058
+ rb_hash_aset(parent->val, oj_calc_hash_key(pi, kval), rval);
1071
1059
  }
1072
1060
  break;
1073
1061
  default: break;
@@ -1082,7 +1070,7 @@ static void hash_set_value(ParseInfo pi, Val kval, VALUE value) {
1082
1070
 
1083
1071
  switch (rb_type(parent->val)) {
1084
1072
  case T_OBJECT: oj_set_obj_ivar(parent, kval, value); break;
1085
- case T_HASH: rb_hash_aset(parent->val, calc_hash_key(pi, kval), value); break;
1073
+ case T_HASH: rb_hash_aset(parent->val, oj_calc_hash_key(pi, kval), value); break;
1086
1074
  default: break;
1087
1075
  }
1088
1076
  if (Yes == pi->options.trace) {
data/ext/oj/dump.c CHANGED
@@ -535,59 +535,57 @@ void oj_dump_xml_time(VALUE obj, Out out) {
535
535
  }
536
536
  if ((0 == nsec && !out->opts->sec_prec_set) || 0 == out->opts->sec_prec) {
537
537
  if (0 == tzsecs && rb_funcall2(obj, oj_utcq_id, 0, 0)) {
538
- sprintf(buf,
539
- "%04d-%02d-%02dT%02d:%02d:%02dZ",
540
- ti.year,
541
- ti.mon,
542
- ti.day,
543
- ti.hour,
544
- ti.min,
545
- ti.sec);
546
- oj_dump_cstr(buf, 20, 0, 0, out);
538
+ int len = sprintf(buf,
539
+ "%04d-%02d-%02dT%02d:%02d:%02dZ",
540
+ ti.year,
541
+ ti.mon,
542
+ ti.day,
543
+ ti.hour,
544
+ ti.min,
545
+ ti.sec);
546
+ oj_dump_cstr(buf, len, 0, 0, out);
547
547
  } else {
548
- sprintf(buf,
549
- "%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
550
- ti.year,
551
- ti.mon,
552
- ti.day,
553
- ti.hour,
554
- ti.min,
555
- ti.sec,
556
- tzsign,
557
- tzhour,
558
- tzmin);
559
- oj_dump_cstr(buf, 25, 0, 0, out);
548
+ int len = sprintf(buf,
549
+ "%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
550
+ ti.year,
551
+ ti.mon,
552
+ ti.day,
553
+ ti.hour,
554
+ ti.min,
555
+ ti.sec,
556
+ tzsign,
557
+ tzhour,
558
+ tzmin);
559
+ oj_dump_cstr(buf, len, 0, 0, out);
560
560
  }
561
561
  } else if (0 == tzsecs && rb_funcall2(obj, oj_utcq_id, 0, 0)) {
562
562
  char format[64] = "%04d-%02d-%02dT%02d:%02d:%02d.%09ldZ";
563
- int len = 30;
563
+ int len;
564
564
 
565
565
  if (9 > out->opts->sec_prec) {
566
566
  format[32] = '0' + out->opts->sec_prec;
567
- len -= 9 - out->opts->sec_prec;
568
567
  }
569
- sprintf(buf, format, ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, (long)nsec);
568
+ len = sprintf(buf, format, ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, (long)nsec);
570
569
  oj_dump_cstr(buf, len, 0, 0, out);
571
570
  } else {
572
571
  char format[64] = "%04d-%02d-%02dT%02d:%02d:%02d.%09ld%c%02d:%02d";
573
- int len = 35;
572
+ int len;
574
573
 
575
574
  if (9 > out->opts->sec_prec) {
576
575
  format[32] = '0' + out->opts->sec_prec;
577
- len -= 9 - out->opts->sec_prec;
578
576
  }
579
- sprintf(buf,
580
- format,
581
- ti.year,
582
- ti.mon,
583
- ti.day,
584
- ti.hour,
585
- ti.min,
586
- ti.sec,
587
- (long)nsec,
588
- tzsign,
589
- tzhour,
590
- tzmin);
577
+ len = sprintf(buf,
578
+ format,
579
+ ti.year,
580
+ ti.mon,
581
+ ti.day,
582
+ ti.hour,
583
+ ti.min,
584
+ ti.sec,
585
+ (long)nsec,
586
+ tzsign,
587
+ tzhour,
588
+ tzmin);
591
589
  oj_dump_cstr(buf, len, 0, 0, out);
592
590
  }
593
591
  }
@@ -827,9 +825,8 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
827
825
  if (is_sym) {
828
826
  *out->cur++ = ':';
829
827
  }
830
- for (; '\0' != *str; str++) {
831
- *out->cur++ = *str;
832
- }
828
+ memcpy(out->cur, str, cnt);
829
+ out->cur += cnt;
833
830
  *out->cur++ = '"';
834
831
  } else {
835
832
  const char *end = str + cnt;
@@ -1206,7 +1203,7 @@ void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
1206
1203
  if ((int)sizeof(buf) <= cnt) {
1207
1204
  cnt = sizeof(buf) - 1;
1208
1205
  }
1209
- strncpy(buf, rb_string_value_ptr((VALUE *)&rstr), cnt);
1206
+ memcpy(buf, rb_string_value_ptr((VALUE *)&rstr), cnt);
1210
1207
  buf[cnt] = '\0';
1211
1208
  } else {
1212
1209
  cnt = oj_dump_float_printf(buf, sizeof(buf), obj, d, out->opts->float_fmt);
data/ext/oj/dump_strict.c CHANGED
@@ -98,7 +98,7 @@ static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
98
98
  if ((int)sizeof(buf) <= cnt) {
99
99
  cnt = sizeof(buf) - 1;
100
100
  }
101
- strncpy(buf, rb_string_value_ptr((VALUE *)&rstr), cnt);
101
+ memcpy(buf, rb_string_value_ptr((VALUE *)&rstr), cnt);
102
102
  buf[cnt] = '\0';
103
103
  } else {
104
104
  cnt = oj_dump_float_printf(buf, sizeof(buf), obj, d, out->opts->float_fmt);
data/ext/oj/hash.c CHANGED
@@ -5,8 +5,8 @@
5
5
 
6
6
  #include <stdint.h>
7
7
 
8
- #define HASH_MASK 0x000003FF
9
- #define HASH_SLOT_CNT 1024
8
+ #define HASH_SLOT_CNT ((uint32_t)8192)
9
+ #define HASH_MASK (HASH_SLOT_CNT - 1)
10
10
 
11
11
  typedef struct _keyVal {
12
12
  struct _keyVal *next;
@@ -20,6 +20,8 @@ struct _hash {
20
20
  };
21
21
 
22
22
  struct _hash class_hash;
23
+ struct _hash str_hash;
24
+ struct _hash sym_hash;
23
25
  struct _hash intern_hash;
24
26
 
25
27
  // almost the Murmur hash algorithm
@@ -64,6 +66,8 @@ static uint32_t hash_calc(const uint8_t *key, size_t len) {
64
66
 
65
67
  void oj_hash_init() {
66
68
  memset(class_hash.slots, 0, sizeof(class_hash.slots));
69
+ memset(str_hash.slots, 0, sizeof(str_hash.slots));
70
+ memset(sym_hash.slots, 0, sizeof(sym_hash.slots));
67
71
  memset(intern_hash.slots, 0, sizeof(intern_hash.slots));
68
72
  }
69
73
 
@@ -100,8 +104,8 @@ static VALUE hash_get(Hash hash, const char *key, size_t len, VALUE **slotp, VAL
100
104
  }
101
105
 
102
106
  void oj_hash_print() {
103
- int i;
104
- KeyVal b;
107
+ uint32_t i;
108
+ KeyVal b;
105
109
 
106
110
  for (i = 0; i < HASH_SLOT_CNT; i++) {
107
111
  printf("%4d:", i);
@@ -112,11 +116,44 @@ void oj_hash_print() {
112
116
  }
113
117
  }
114
118
 
119
+ void oj_hash_sizes() {
120
+ uint32_t i;
121
+ KeyVal b;
122
+ int max = 0;
123
+ int min = 1000000;
124
+
125
+ for (i = 0; i < HASH_SLOT_CNT; i++) {
126
+ int cnt = 0;
127
+
128
+ for (b = str_hash.slots + i; 0 != b && 0 != b->key; b = b->next) {
129
+ cnt++;
130
+ }
131
+ // printf(" %4d\n", cnt);
132
+ if (max < cnt) {
133
+ max = cnt;
134
+ }
135
+ if (cnt < min) {
136
+ min = cnt;
137
+ }
138
+ }
139
+ printf("min: %d max: %d\n", min, max);
140
+ }
141
+
115
142
  VALUE
116
143
  oj_class_hash_get(const char *key, size_t len, VALUE **slotp) {
117
144
  return hash_get(&class_hash, key, len, slotp, Qnil);
118
145
  }
119
146
 
147
+ VALUE
148
+ oj_str_hash_get(const char *key, size_t len, VALUE **slotp) {
149
+ return hash_get(&str_hash, key, len, slotp, Qnil);
150
+ }
151
+
152
+ VALUE
153
+ oj_sym_hash_get(const char *key, size_t len, VALUE **slotp) {
154
+ return hash_get(&sym_hash, key, len, slotp, Qnil);
155
+ }
156
+
120
157
  ID oj_attr_hash_get(const char *key, size_t len, ID **slotp) {
121
158
  return (ID)hash_get(&intern_hash, key, len, (VALUE **)slotp, 0);
122
159
  }
data/ext/oj/hash.h CHANGED
@@ -11,6 +11,8 @@ typedef struct _hash *Hash;
11
11
  extern void oj_hash_init();
12
12
 
13
13
  extern VALUE oj_class_hash_get(const char *key, size_t len, VALUE **slotp);
14
+ extern VALUE oj_str_hash_get(const char *key, size_t len, VALUE **slotp);
15
+ extern VALUE oj_sym_hash_get(const char *key, size_t len, VALUE **slotp);
14
16
  extern ID oj_attr_hash_get(const char *key, size_t len, ID **slotp);
15
17
 
16
18
  extern void oj_hash_print();
data/ext/oj/mimic_json.c CHANGED
@@ -389,9 +389,9 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
389
389
  } else {
390
390
  VALUE active_hack[1];
391
391
 
392
- if (Qundef == state_class) {
393
- oj_define_mimic_json(0, NULL, Qnil);
394
- }
392
+ if (Qundef == state_class) {
393
+ oj_define_mimic_json(0, NULL, Qnil);
394
+ }
395
395
  active_hack[0] = rb_funcall(state_class, oj_new_id, 0);
396
396
  oj_dump_obj_to_json_using_params(*argv, copts, &out, 1, active_hack);
397
397
  }
@@ -480,7 +480,7 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
480
480
  rb_hash_aset(h, oj_array_nl_sym, rb_str_new2("\n"));
481
481
  }
482
482
  if (Qundef == state_class) {
483
- oj_define_mimic_json(0, NULL, Qnil);
483
+ oj_define_mimic_json(0, NULL, Qnil);
484
484
  }
485
485
  rargs[1] = rb_funcall(state_class, oj_new_id, 1, h);
486
486
 
@@ -713,6 +713,8 @@ static struct _options mimic_object_to_json_options = {0, // indent
713
713
  No, // safe
714
714
  false, // sec_prec_set
715
715
  No, // ignore_under
716
+ Yes, // cache_keys
717
+ 3, // cache_str
716
718
  0, // int_range_min
717
719
  0, // int_range_max
718
720
  oj_json_class, // create_id
data/ext/oj/object.c CHANGED
@@ -30,11 +30,38 @@ inline static long read_long(const char *str, size_t len) {
30
30
 
31
31
  static VALUE calc_hash_key(ParseInfo pi, Val kval, char k1) {
32
32
  volatile VALUE rkey;
33
+ #if 0
34
+ VALUE *slot;
33
35
 
36
+ if (':' == k1) {
37
+ if (Qnil == (rkey = oj_sym_hash_get(kval->key + 1, kval->klen - 1, &slot))) {
38
+ rkey = rb_str_new(kval->key + 1, kval->klen - 1);
39
+ rkey = oj_encode(rkey);
40
+ rkey = rb_str_intern(rkey);
41
+ *slot = rkey;
42
+ rb_gc_register_address(slot);
43
+ }
44
+ } else if (Yes == pi->options.sym_key) {
45
+ if (Qnil == (rkey = oj_sym_hash_get(kval->key, kval->klen, &slot))) {
46
+ rkey = rb_str_new(kval->key, kval->klen);
47
+ rkey = oj_encode(rkey);
48
+ rkey = rb_str_intern(rkey);
49
+ *slot = rkey;
50
+ rb_gc_register_address(slot);
51
+ }
52
+ } else {
53
+ if (Qnil == (rkey = oj_str_hash_get(kval->key, kval->klen, &slot))) {
54
+ rkey = rb_str_new(kval->key, kval->klen);
55
+ rkey = oj_encode(rkey);
56
+ *slot = rkey;
57
+ rb_gc_register_address(slot);
58
+ }
59
+ }
60
+ #else
34
61
  if (':' == k1) {
35
62
  rkey = rb_str_new(kval->key + 1, kval->klen - 1);
36
63
  rkey = oj_encode(rkey);
37
- rkey = rb_funcall(rkey, oj_to_sym_id, 0);
64
+ rkey = rb_str_intern(rkey);
38
65
  } else {
39
66
  rkey = rb_str_new(kval->key, kval->klen);
40
67
  rkey = oj_encode(rkey);
@@ -42,6 +69,7 @@ static VALUE calc_hash_key(ParseInfo pi, Val kval, char k1) {
42
69
  rkey = rb_str_intern(rkey);
43
70
  }
44
71
  }
72
+ #endif
45
73
  return rkey;
46
74
  }
47
75
 
@@ -405,22 +433,22 @@ void oj_set_obj_ivar(Val parent, Val kval, VALUE value) {
405
433
  char *buf = ALLOC_N(char, klen + 2);
406
434
 
407
435
  if ('~' == *key) {
408
- strncpy(buf, key + 1, klen - 1);
436
+ memcpy(buf, key + 1, klen - 1);
409
437
  buf[klen - 1] = '\0';
410
438
  } else {
411
439
  *buf = '@';
412
- strncpy(buf + 1, key, klen);
440
+ memcpy(buf + 1, key, klen);
413
441
  buf[klen + 1] = '\0';
414
442
  }
415
443
  var_id = rb_intern(buf);
416
444
  xfree(buf);
417
445
  } else {
418
446
  if ('~' == *key) {
419
- strncpy(attr, key + 1, klen - 1);
447
+ memcpy(attr, key + 1, klen - 1);
420
448
  attr[klen - 1] = '\0';
421
449
  } else {
422
450
  *attr = '@';
423
- strncpy(attr + 1, key, klen);
451
+ memcpy(attr + 1, key, klen);
424
452
  attr[klen + 1] = '\0';
425
453
  }
426
454
  var_id = rb_intern(attr);
data/ext/oj/oj.c CHANGED
@@ -106,6 +106,8 @@ static VALUE auto_sym;
106
106
  static VALUE bigdecimal_as_decimal_sym;
107
107
  static VALUE bigdecimal_load_sym;
108
108
  static VALUE bigdecimal_sym;
109
+ static VALUE cache_keys_sym;
110
+ static VALUE cache_str_sym;
109
111
  static VALUE circular_sym;
110
112
  static VALUE class_cache_sym;
111
113
  static VALUE compat_bigdecimal_sym;
@@ -186,6 +188,8 @@ struct _options oj_default_options = {
186
188
  No, // safe
187
189
  false, // sec_prec_set
188
190
  No, // ignore_under
191
+ Yes, // cache_keys
192
+ 3, // cache_str
189
193
  0, // int_range_min
190
194
  0, // int_range_max
191
195
  oj_json_class, // create_id
@@ -279,9 +283,11 @@ struct _options oj_default_options = {
279
283
  *used
280
284
  * - *:array_class* [_Class_|_nil_] Class to use instead of Array on load
281
285
  * - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil values are omitted
282
- * - *:ignore* [_nil_|Array] either nil or an Array of classes to ignore when dumping
283
- * - *:ignore_under* [Boolean] if true then attributes that start with _ are ignored when dumping in
286
+ * - *:ignore* [_nil_|_Array_] either nil or an Array of classes to ignore when dumping
287
+ * - *:ignore_under* [_Boolean_] if true then attributes that start with _ are ignored when dumping in
284
288
  *object or custom mode.
289
+ * - *:cache_keys* [_Boolean_] if true then hash keys are cached
290
+ * - *:cache_str* [_Fixnum_] maximum string value length to cache
285
291
  * - *:integer_range* [_Range_] Dump integers outside range as strings.
286
292
  * - *:trace* [_true,_|_false_] Trace all load and dump calls, default is false (trace is off)
287
293
  * - *:safe* [_true,_|_false_] Safe mimic breaks JSON mimic to be safer, default is false (safe is
@@ -389,11 +395,17 @@ static VALUE get_def_opts(VALUE self) {
389
395
  ? Qtrue
390
396
  : ((No == oj_default_options.safe) ? Qfalse : Qnil));
391
397
  rb_hash_aset(opts, float_prec_sym, INT2FIX(oj_default_options.float_prec));
398
+ rb_hash_aset(opts, cache_str_sym, INT2FIX(oj_default_options.cache_str));
392
399
  rb_hash_aset(opts,
393
400
  ignore_under_sym,
394
401
  (Yes == oj_default_options.ignore_under)
395
402
  ? Qtrue
396
403
  : ((No == oj_default_options.ignore_under) ? Qfalse : Qnil));
404
+ rb_hash_aset(opts,
405
+ cache_keys_sym,
406
+ (Yes == oj_default_options.cache_keys)
407
+ ? Qtrue
408
+ : ((No == oj_default_options.cache_keys) ? Qfalse : Qnil));
397
409
  switch (oj_default_options.mode) {
398
410
  case StrictMode: rb_hash_aset(opts, mode_sym, strict_sym); break;
399
411
  case CompatMode: rb_hash_aset(opts, mode_sym, compat_sym); break;
@@ -557,6 +569,8 @@ static VALUE get_def_opts(VALUE self) {
557
569
  * - *:ignore* [_nil_|Array] either nil or an Array of classes to ignore when dumping
558
570
  * - *:ignore_under* [_Boolean_] if true then attributes that start with _ are ignored when
559
571
  *dumping in object or custom mode.
572
+ * - *:cache_keys* [_Boolean_] if true then hash keys are cached
573
+ * - *:cache_str* [_Fixnum_] maximum string vsalue length to cache
560
574
  * - *:integer_range* [_Range_] Dump integers outside range as strings.
561
575
  * - *:trace* [_Boolean_] turn trace on or off.
562
576
  * - *:safe* [_Boolean_] turn safe mimic on or off.
@@ -589,6 +603,7 @@ void oj_parse_options(VALUE ropts, Options copts) {
589
603
  {oj_safe_sym, &copts->safe},
590
604
  {ignore_under_sym, &copts->ignore_under},
591
605
  {oj_create_additions_sym, &copts->create_ok},
606
+ {cache_keys_sym, &copts->cache_keys},
592
607
  {Qnil, 0}};
593
608
  YesNoOpt o;
594
609
  volatile VALUE v;
@@ -647,6 +662,28 @@ void oj_parse_options(VALUE ropts, Options copts) {
647
662
  copts->float_prec = n;
648
663
  }
649
664
  }
665
+ if (Qnil != (v = rb_hash_lookup(ropts, cache_str_sym))) {
666
+ int n;
667
+
668
+ #ifdef RUBY_INTEGER_UNIFICATION
669
+ if (rb_cInteger != rb_obj_class(v)) {
670
+ rb_raise(rb_eArgError, ":cache_str must be a Integer.");
671
+ }
672
+ #else
673
+ if (T_FIXNUM != rb_type(v)) {
674
+ rb_raise(rb_eArgError, ":cache_str must be a Fixnum.");
675
+ }
676
+ #endif
677
+ n = FIX2INT(v);
678
+ if (0 >= n) {
679
+ copts->cache_str = 0;
680
+ } else {
681
+ if (32 < n) {
682
+ n = 32;
683
+ }
684
+ copts->cache_str = (char)n;
685
+ }
686
+ }
650
687
  if (Qnil != (v = rb_hash_lookup(ropts, sec_prec_sym))) {
651
688
  int n;
652
689
 
@@ -1636,13 +1673,20 @@ extern VALUE oj_optimize_rails(VALUE self);
1636
1673
 
1637
1674
  /*
1638
1675
  extern void oj_hash_test();
1639
-
1640
1676
  static VALUE
1641
1677
  hash_test(VALUE self) {
1642
1678
  oj_hash_test();
1643
1679
  return Qnil;
1644
1680
  }
1645
1681
  */
1682
+ /*
1683
+ extern void oj_hash_sizes();
1684
+ static VALUE
1685
+ hash_test(VALUE self) {
1686
+ oj_hash_sizes();
1687
+ return Qnil;
1688
+ }
1689
+ */
1646
1690
 
1647
1691
  static VALUE protect_require(VALUE x) {
1648
1692
  rb_require("time");
@@ -1816,6 +1860,10 @@ void Init_oj() {
1816
1860
  rb_gc_register_address(&bigdecimal_load_sym);
1817
1861
  bigdecimal_sym = ID2SYM(rb_intern("bigdecimal"));
1818
1862
  rb_gc_register_address(&bigdecimal_sym);
1863
+ cache_keys_sym = ID2SYM(rb_intern("cache_keys"));
1864
+ rb_gc_register_address(&cache_keys_sym);
1865
+ cache_str_sym = ID2SYM(rb_intern("cache_str"));
1866
+ rb_gc_register_address(&cache_str_sym);
1819
1867
  circular_sym = ID2SYM(rb_intern("circular"));
1820
1868
  rb_gc_register_address(&circular_sym);
1821
1869
  class_cache_sym = ID2SYM(rb_intern("class_cache"));
data/ext/oj/oj.h CHANGED
@@ -143,6 +143,8 @@ typedef struct _options {
143
143
  char safe; // YesNo
144
144
  char sec_prec_set; // boolean (0 or 1)
145
145
  char ignore_under; // YesNo - ignore attrs starting with _ if true in object and custom modes
146
+ char cache_keys; // YexNo
147
+ char cache_str; // string short than or equal to this are cache
146
148
  int64_t int_range_min; // dump numbers below as string
147
149
  int64_t int_range_max; // dump numbers above as string
148
150
  const char * create_id; // 0 or string
data/ext/oj/parse.h CHANGED
@@ -90,6 +90,9 @@ extern void oj_set_wab_callbacks(ParseInfo pi);
90
90
  extern void oj_sparse2(ParseInfo pi);
91
91
  extern VALUE oj_pi_sparse(int argc, VALUE *argv, ParseInfo pi, int fd);
92
92
 
93
+ extern VALUE oj_cstr_to_value(const char *str, size_t len, size_t cache_str);
94
+ extern VALUE oj_calc_hash_key(ParseInfo pi, Val parent);
95
+
93
96
  static inline void parse_info_init(ParseInfo pi) {
94
97
  memset(pi, 0, sizeof(struct _parseInfo));
95
98
  }
data/ext/oj/rails.c CHANGED
@@ -828,7 +828,8 @@ rails_mimic_json(VALUE self) {
828
828
  json = rb_define_module("JSON");
829
829
  }
830
830
  oj_mimic_json_methods(json);
831
- oj_default_options.mode = RailsMode;
831
+ // Setting the default mode breaks the prmoise in the docs not to.
832
+ //oj_default_options.mode = RailsMode;
832
833
 
833
834
  return Qnil;
834
835
  }
data/ext/oj/scp.c CHANGED
@@ -9,6 +9,7 @@
9
9
  #include <unistd.h>
10
10
 
11
11
  #include "encode.h"
12
+ #include "hash.h"
12
13
  #include "oj.h"
13
14
  #include "parse.h"
14
15
 
@@ -82,19 +83,6 @@ static void end_array(ParseInfo pi) {
82
83
  rb_funcall(pi->handler, oj_array_end_id, 0);
83
84
  }
84
85
 
85
- static VALUE calc_hash_key(ParseInfo pi, Val kval) {
86
- volatile VALUE rkey = kval->key_val;
87
-
88
- if (Qundef == rkey) {
89
- rkey = rb_str_new(kval->key, kval->klen);
90
- rkey = oj_encode(rkey);
91
- if (Yes == pi->options.sym_key) {
92
- rkey = rb_str_intern(rkey);
93
- }
94
- }
95
- return rkey;
96
- }
97
-
98
86
  static VALUE hash_key(ParseInfo pi, const char *key, size_t klen) {
99
87
  return rb_funcall(pi->handler, oj_hash_key_id, 1, rb_str_new(key, klen));
100
88
  }
@@ -107,7 +95,7 @@ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, c
107
95
  oj_hash_set_id,
108
96
  3,
109
97
  stack_peek(&pi->stack)->val,
110
- calc_hash_key(pi, kval),
98
+ oj_calc_hash_key(pi, kval),
111
99
  rstr);
112
100
  }
113
101
 
@@ -116,7 +104,7 @@ static void hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
116
104
  oj_hash_set_id,
117
105
  3,
118
106
  stack_peek(&pi->stack)->val,
119
- calc_hash_key(pi, kval),
107
+ oj_calc_hash_key(pi, kval),
120
108
  oj_num_as_value(ni));
121
109
  }
122
110
 
@@ -125,7 +113,7 @@ static void hash_set_value(ParseInfo pi, Val kval, VALUE value) {
125
113
  oj_hash_set_id,
126
114
  3,
127
115
  stack_peek(&pi->stack)->val,
128
- calc_hash_key(pi, kval),
116
+ oj_calc_hash_key(pi, kval),
129
117
  value);
130
118
  }
131
119
 
data/ext/oj/strict.c CHANGED
@@ -8,10 +8,65 @@
8
8
 
9
9
  #include "encode.h"
10
10
  #include "err.h"
11
+ #include "hash.h"
11
12
  #include "oj.h"
12
13
  #include "parse.h"
13
14
  #include "trace.h"
14
15
 
16
+ VALUE oj_cstr_to_value(const char *str, size_t len, size_t cache_str) {
17
+ volatile VALUE rstr = Qnil;
18
+
19
+ if (len <= cache_str) {
20
+ VALUE *slot;
21
+
22
+ if (Qnil == (rstr = oj_str_hash_get(str, len, &slot))) {
23
+ rstr = rb_str_new(str, len);
24
+ rstr = oj_encode(rstr);
25
+ *slot = rstr;
26
+ rb_gc_register_address(slot);
27
+ }
28
+ } else {
29
+ rstr = rb_str_new(str, len);
30
+ rstr = oj_encode(rstr);
31
+ }
32
+ return rstr;
33
+ }
34
+
35
+ VALUE oj_calc_hash_key(ParseInfo pi, Val parent) {
36
+ volatile VALUE rkey = parent->key_val;
37
+
38
+ if (Qundef != rkey) {
39
+ return rkey;
40
+ }
41
+ if (Yes != pi->options.cache_keys) {
42
+ rkey = rb_str_new(parent->key, parent->klen);
43
+ rkey = oj_encode(rkey);
44
+ if (Yes == pi->options.sym_key) {
45
+ rkey = rb_str_intern(rkey);
46
+ }
47
+ return rkey;
48
+ }
49
+ VALUE *slot;
50
+
51
+ if (Yes == pi->options.sym_key) {
52
+ if (Qnil == (rkey = oj_sym_hash_get(parent->key, parent->klen, &slot))) {
53
+ rkey = rb_str_new(parent->key, parent->klen);
54
+ rkey = oj_encode(rkey);
55
+ rkey = rb_str_intern(rkey);
56
+ *slot = rkey;
57
+ rb_gc_register_address(slot);
58
+ }
59
+ } else {
60
+ if (Qnil == (rkey = oj_str_hash_get(parent->key, parent->klen, &slot))) {
61
+ rkey = rb_str_new(parent->key, parent->klen);
62
+ rkey = oj_encode(rkey);
63
+ *slot = rkey;
64
+ rb_gc_register_address(slot);
65
+ }
66
+ }
67
+ return rkey;
68
+ }
69
+
15
70
  static void hash_end(ParseInfo pi) {
16
71
  if (Yes == pi->options.trace) {
17
72
  oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
@@ -36,9 +91,8 @@ static void add_value(ParseInfo pi, VALUE val) {
36
91
  }
37
92
 
38
93
  static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
39
- volatile VALUE rstr = rb_str_new(str, len);
94
+ volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
40
95
 
41
- rstr = oj_encode(rstr);
42
96
  pi->stack.head->val = rstr;
43
97
  if (Yes == pi->options.trace) {
44
98
  oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, rstr);
@@ -65,24 +119,12 @@ static VALUE start_hash(ParseInfo pi) {
65
119
  return rb_hash_new();
66
120
  }
67
121
 
68
- static VALUE calc_hash_key(ParseInfo pi, Val parent) {
69
- volatile VALUE rkey = parent->key_val;
70
-
71
- if (Qundef == rkey) {
72
- rkey = rb_str_new(parent->key, parent->klen);
73
- }
74
- rkey = oj_encode(rkey);
75
- if (Yes == pi->options.sym_key) {
76
- rkey = rb_str_intern(rkey);
77
- }
78
- return rkey;
79
- }
80
-
81
122
  static void hash_set_cstr(ParseInfo pi, Val parent, const char *str, size_t len, const char *orig) {
82
- volatile VALUE rstr = rb_str_new(str, len);
123
+ volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
83
124
 
84
- rstr = oj_encode(rstr);
85
- rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), rstr);
125
+ rb_hash_aset(stack_peek(&pi->stack)->val,
126
+ oj_calc_hash_key(pi, parent),
127
+ rstr);
86
128
  if (Yes == pi->options.trace) {
87
129
  oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rstr);
88
130
  }
@@ -95,14 +137,18 @@ static void hash_set_num(ParseInfo pi, Val parent, NumInfo ni) {
95
137
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
96
138
  }
97
139
  v = oj_num_as_value(ni);
98
- rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), v);
140
+ rb_hash_aset(stack_peek(&pi->stack)->val,
141
+ oj_calc_hash_key(pi, parent),
142
+ v);
99
143
  if (Yes == pi->options.trace) {
100
144
  oj_trace_parse_call("set_number", pi, __FILE__, __LINE__, v);
101
145
  }
102
146
  }
103
147
 
104
148
  static void hash_set_value(ParseInfo pi, Val parent, VALUE value) {
105
- rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), value);
149
+ rb_hash_aset(stack_peek(&pi->stack)->val,
150
+ oj_calc_hash_key(pi, parent),
151
+ value);
106
152
  if (Yes == pi->options.trace) {
107
153
  oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
108
154
  }
@@ -116,9 +162,8 @@ static VALUE start_array(ParseInfo pi) {
116
162
  }
117
163
 
118
164
  static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
119
- volatile VALUE rstr = rb_str_new(str, len);
165
+ volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
120
166
 
121
- rstr = oj_encode(rstr);
122
167
  rb_ary_push(stack_peek(&pi->stack)->val, rstr);
123
168
  if (Yes == pi->options.trace) {
124
169
  oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rstr);
data/ext/oj/wab.c CHANGED
@@ -10,6 +10,7 @@
10
10
  #include "dump.h"
11
11
  #include "encode.h"
12
12
  #include "err.h"
13
+ #include "hash.h"
13
14
  #include "oj.h"
14
15
  #include "parse.h"
15
16
  #include "trace.h"
@@ -292,6 +293,34 @@ void oj_dump_wab_val(VALUE obj, int depth, Out out) {
292
293
 
293
294
  ///// load functions /////
294
295
 
296
+ static VALUE calc_hash_key(ParseInfo pi, Val parent) {
297
+ volatile VALUE rkey = parent->key_val;
298
+
299
+ if (Qundef != rkey) {
300
+ rkey = oj_encode(rkey);
301
+ rkey = rb_str_intern(rkey);
302
+
303
+ return rkey;
304
+ }
305
+ if (Yes != pi->options.cache_keys) {
306
+ rkey = rb_str_new(parent->key, parent->klen);
307
+ rkey = oj_encode(rkey);
308
+ rkey = rb_str_intern(rkey);
309
+
310
+ return rkey;
311
+ }
312
+ VALUE *slot;
313
+
314
+ if (Qnil == (rkey = oj_sym_hash_get(parent->key, parent->klen, &slot))) {
315
+ rkey = rb_str_new(parent->key, parent->klen);
316
+ rkey = oj_encode(rkey);
317
+ rkey = rb_str_intern(rkey);
318
+ *slot = rkey;
319
+ rb_gc_register_address(slot);
320
+ }
321
+ return rkey;
322
+ }
323
+
295
324
  static void hash_end(ParseInfo pi) {
296
325
  if (Yes == pi->options.trace) {
297
326
  oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
@@ -432,7 +461,7 @@ static VALUE protect_uri(VALUE rstr) {
432
461
  return rb_funcall(resolve_uri_class(), oj_parse_id, 1, rstr);
433
462
  }
434
463
 
435
- static VALUE cstr_to_rstr(const char *str, size_t len) {
464
+ static VALUE cstr_to_rstr(ParseInfo pi, const char *str, size_t len) {
436
465
  volatile VALUE v = Qnil;
437
466
 
438
467
  if (30 == len && '-' == str[4] && '-' == str[7] && 'T' == str[10] && ':' == str[13] &&
@@ -445,20 +474,20 @@ static VALUE cstr_to_rstr(const char *str, size_t len) {
445
474
  uuid_check(str, (int)len) && Qnil != resolve_wab_uuid_class()) {
446
475
  return rb_funcall(wab_uuid_clas, oj_new_id, 1, rb_str_new(str, len));
447
476
  }
448
- v = rb_str_new(str, len);
449
477
  if (7 < len && 0 == strncasecmp("http://", str, 7)) {
450
478
  int err = 0;
479
+ v = rb_str_new(str, len);
451
480
  volatile VALUE uri = rb_protect(protect_uri, v, &err);
452
481
 
453
482
  if (0 == err) {
454
483
  return uri;
455
484
  }
456
485
  }
457
- return oj_encode(v);
486
+ return oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
458
487
  }
459
488
 
460
489
  static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
461
- pi->stack.head->val = cstr_to_rstr(str, len);
490
+ pi->stack.head->val = cstr_to_rstr(pi, str, len);
462
491
  if (Yes == pi->options.trace) {
463
492
  oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, pi->stack.head->val);
464
493
  }
@@ -484,20 +513,8 @@ static VALUE start_hash(ParseInfo pi) {
484
513
  return rb_hash_new();
485
514
  }
486
515
 
487
- static VALUE calc_hash_key(ParseInfo pi, Val parent) {
488
- volatile VALUE rkey = parent->key_val;
489
-
490
- if (Qundef == rkey) {
491
- rkey = rb_str_new(parent->key, parent->klen);
492
- }
493
- rkey = oj_encode(rkey);
494
- rkey = rb_str_intern(rkey);
495
-
496
- return rkey;
497
- }
498
-
499
516
  static void hash_set_cstr(ParseInfo pi, Val parent, const char *str, size_t len, const char *orig) {
500
- volatile VALUE rval = cstr_to_rstr(str, len);
517
+ volatile VALUE rval = cstr_to_rstr(pi, str, len);
501
518
 
502
519
  rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), rval);
503
520
  if (Yes == pi->options.trace) {
@@ -533,7 +550,7 @@ static VALUE start_array(ParseInfo pi) {
533
550
  }
534
551
 
535
552
  static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
536
- volatile VALUE rval = cstr_to_rstr(str, len);
553
+ volatile VALUE rval = cstr_to_rstr(pi, str, len);
537
554
 
538
555
  rb_ary_push(stack_peek(&pi->stack)->val, rval);
539
556
  if (Yes == pi->options.trace) {
data/lib/oj/mimic.rb CHANGED
@@ -23,6 +23,8 @@ module Oj
23
23
  bigdecimal_load: :auto,
24
24
  circular: false,
25
25
  class_cache: false,
26
+ cache_keys: true,
27
+ cache_str: false,
26
28
  create_additions: false,
27
29
  create_id: "json_class",
28
30
  empty_string: false,
data/lib/oj/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Oj
3
3
  # Current version of the module.
4
- VERSION = '3.11.7'
4
+ VERSION = '3.12.2'
5
5
  end
data/pages/Options.md CHANGED
@@ -251,7 +251,13 @@ compatibility. Using just indent as an integer gives better performance.
251
251
 
252
252
  ### :symbol_keys [Boolean]
253
253
 
254
- Use symbols instead of strings for hash keys. :symbolize_names is an alias.
254
+ Use symbols instead of strings for hash keys.
255
+
256
+ ### :symbolize_names [Boolean]
257
+
258
+ Like :symbol_keys has keys are made into symbols but only when
259
+ mimicing the JSON gem and then only as the JSON gem honors it so
260
+ JSON.parse honors the option but JSON.load does not.
255
261
 
256
262
  ### :trace
257
263
 
data/test/foo.rb CHANGED
@@ -7,14 +7,7 @@ $oj_dir = File.dirname(File.expand_path(File.dirname(__FILE__)))
7
7
  end
8
8
 
9
9
  require 'oj'
10
- require 'active_support'
11
10
 
12
- Oj.default_options = {trace: true}
11
+ p = Oj::Parser.new(:debug)
13
12
 
14
- Oj::Rails.mimic_JSON
15
- #Oj.mimic_JSON
16
- begin
17
- ::JSON.load('foo=&bar')
18
- rescue Exception => e
19
- puts "*** #{e.class}: #{e.message}"
20
- end
13
+ p.parse("[true, false]")
data/test/perf.rb CHANGED
@@ -17,7 +17,7 @@ class Perf
17
17
  end
18
18
  end
19
19
  end
20
-
20
+
21
21
  def run(iter)
22
22
  base = Item.new(nil, nil) { }
23
23
  base.run(iter, 0.0)
data/test/perf_scp.rb CHANGED
@@ -14,16 +14,16 @@ require 'oj'
14
14
 
15
15
  $verbose = false
16
16
  $indent = 0
17
- $iter = 50000
17
+ $iter = 50_000
18
18
  $with_bignum = false
19
- $size = 0
19
+ $size = 1
20
20
 
21
21
  opts = OptionParser.new
22
22
  opts.on("-v", "verbose") { $verbose = true }
23
23
  opts.on("-c", "--count [Int]", Integer, "iterations") { |i| $iter = i }
24
24
  opts.on("-i", "--indent [Int]", Integer, "indentation") { |i| $indent = i }
25
- opts.on("-s", "--size [Int]", Integer, "size (~Kbytes)") { |i| $size = i }
26
- opts.on("-b", "with bignum") { $with_bignum = true }
25
+ opts.on("-s", "--size [Int]", Integer, "size (~Kbytes)") { |i| $size = i }
26
+ opts.on("-b", "with bignum") { $with_bignum = true }
27
27
  opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
28
28
  files = opts.parse(ARGV)
29
29
 
@@ -47,7 +47,7 @@ if 0 < $size
47
47
  end
48
48
  end
49
49
 
50
- Oj.default_options = { :indent => $indent, :mode => :compat }
50
+ Oj.default_options = { :indent => $indent, :mode => :strict, cache_keys: true, cache_str: 5 }
51
51
 
52
52
  $json = Oj.dump($obj)
53
53
  $failed = {} # key is same as String used in tests later
@@ -105,7 +105,7 @@ class AllHandler < Oj::ScHandler
105
105
 
106
106
  def hash_set(h, key, value)
107
107
  end
108
-
108
+
109
109
  def array_append(a, value)
110
110
  end
111
111
 
@@ -137,10 +137,11 @@ end
137
137
  puts '-' * 80
138
138
  puts "Parse Performance"
139
139
  perf = Perf.new()
140
- perf.add('Oj::Saj', 'all') { Oj.saj_parse(saj_handler, $json) }
141
- perf.add('Oj::Saj', 'none') { Oj.saj_parse(no_saj, $json) }
142
- perf.add('Oj::Scp', 'all') { Oj.sc_parse(sc_handler, $json) }
143
- perf.add('Oj::Scp', 'none') { Oj.sc_parse(no_handler, $json) }
140
+ perf.add('Oj::Saj.all', 'all') { Oj.saj_parse(saj_handler, $json) }
141
+ perf.add('Oj::Saj.none', 'none') { Oj.saj_parse(no_saj, $json) }
142
+ perf.add('Oj::Scp.all', 'all') { Oj.sc_parse(sc_handler, $json) }
143
+ perf.add('Oj::Scp.none', 'none') { Oj.sc_parse(no_handler, $json) }
144
+ perf.add('Oj::load', 'none') { Oj.wab_load($json) }
144
145
  perf.add('Yajl', 'parse') { Yajl::Parser.parse($json) } unless $failed.has_key?('Yajl')
145
146
  perf.add('JSON::Ext', 'parse') { JSON::Ext::Parser.new($json).parse } unless $failed.has_key?('JSON::Ext')
146
147
  perf.run($iter)
data/test/perf_strict.rb CHANGED
@@ -15,6 +15,8 @@ $iter = 20000
15
15
  $with_bignum = false
16
16
  $with_nums = true
17
17
  $size = 0
18
+ $symbolize = false
19
+ $cache_keys = true
18
20
 
19
21
  opts = OptionParser.new
20
22
  opts.on("-v", "verbose") { $verbose = true }
@@ -23,6 +25,8 @@ opts.on("-i", "--indent [Int]", Integer, "indentation") { |i| $indent = i }
23
25
  opts.on("-s", "--size [Int]", Integer, "size (~Kbytes)") { |i| $size = i }
24
26
  opts.on("-b", "with bignum") { $with_bignum = true }
25
27
  opts.on("-n", "without numbers") { $with_nums = false }
28
+ opts.on("-z", "--symbolize", "symbolize keys") { $symbolize = true }
29
+ opts.on("-k", "--no-cache", "turn off key caching") { $cache_keys = false }
26
30
  opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
27
31
  files = opts.parse(ARGV)
28
32
 
@@ -51,7 +55,7 @@ else
51
55
  }
52
56
  end
53
57
 
54
- Oj.default_options = { :indent => $indent, :mode => :strict }
58
+ Oj.default_options = { :indent => $indent, :mode => :strict, cache_keys: $cache_keys, cache_str: 5 }
55
59
 
56
60
  if 0 < $size
57
61
  o = $obj
@@ -62,9 +66,6 @@ if 0 < $size
62
66
  end
63
67
 
64
68
  $json = Oj.dump($obj)
65
- $obj_json = Oj.dump($obj, :mode => :object)
66
- #puts "*** size: #{$obj_json.size}"
67
- #puts "*** #{$obj_json}"
68
69
  $failed = {} # key is same as String used in tests later
69
70
 
70
71
  def capture_error(tag, orig, load_key, dump_key, &blk)
@@ -77,8 +78,13 @@ def capture_error(tag, orig, load_key, dump_key, &blk)
77
78
  end
78
79
 
79
80
  # Verify that all packages dump and load correctly and return the same Object as the original.
80
- capture_error('Oj:strict', $obj, 'load', 'dump') { |o| Oj.strict_load(Oj.dump(o, :mode => :strict)) }
81
- capture_error('Yajl', $obj, 'encode', 'parse') { |o| require 'yajl'; Yajl::Parser.parse(Yajl::Encoder.encode(o)) }
81
+ capture_error('Oj:strict', $obj, 'load', 'dump') { |o|
82
+ Oj.strict_load(Oj.dump(o))
83
+ }
84
+ capture_error('Yajl', $obj, 'encode', 'parse') { |o|
85
+ require 'yajl'
86
+ Yajl::Parser.parse(Yajl::Encoder.encode(o))
87
+ }
82
88
  capture_error('JSON::Ext', $obj, 'generate', 'parse') { |o|
83
89
  require 'json'
84
90
  require 'json/ext'
@@ -86,16 +92,11 @@ capture_error('JSON::Ext', $obj, 'generate', 'parse') { |o|
86
92
  JSON.parser = JSON::Ext::Parser
87
93
  JSON.parse(JSON.generate(o))
88
94
  }
89
- capture_error('JSON::Pure', $obj, 'generate', 'parse') { |o|
90
- require 'json/pure'
91
- JSON.generator = JSON::Pure::Generator
92
- JSON.parser = JSON::Pure::Parser
93
- JSON.parse(JSON.generate(o))
94
- }
95
+
96
+ Oj.default_options = { symbol_keys: $symbolize }
95
97
 
96
98
  if $verbose
97
99
  puts "json:\n#{$json}\n"
98
- puts "object json:\n#{$obj_json}\n"
99
100
  puts "Oj loaded object:\n#{Oj.strict_load($json)}\n"
100
101
  puts "Yajl loaded object:\n#{Yajl::Parser.parse($json)}\n"
101
102
  puts "JSON loaded object:\n#{JSON::Ext::Parser.new($json).parse}\n"
@@ -105,15 +106,12 @@ puts '-' * 80
105
106
  puts "Strict Parse Performance"
106
107
  perf = Perf.new()
107
108
  unless $failed.has_key?('JSON::Ext')
108
- perf.add('JSON::Ext', 'parse') { JSON.parse($json) }
109
+ perf.add('JSON::Ext', 'parse') { JSON.parse($json, symbolize_names: $symbolize) }
109
110
  perf.before('JSON::Ext') { JSON.parser = JSON::Ext::Parser }
110
111
  end
111
- unless $failed.has_key?('JSON::Pure')
112
- perf.add('JSON::Pure', 'parse') { JSON.parse($json) }
113
- perf.before('JSON::Pure') { JSON.parser = JSON::Pure::Parser }
114
- end
115
112
  unless $failed.has_key?('Oj:strict')
116
113
  perf.add('Oj:strict', 'strict_load') { Oj.strict_load($json) }
114
+ perf.add('Oj:wab', 'wab_load') { Oj.wab_load($json) }
117
115
  end
118
116
  perf.add('Yajl', 'parse') { Yajl::Parser.parse($json) } unless $failed.has_key?('Yajl')
119
117
  perf.run($iter)
@@ -125,12 +123,8 @@ unless $failed.has_key?('JSON::Ext')
125
123
  perf.add('JSON::Ext', 'dump') { JSON.generate($obj) }
126
124
  perf.before('JSON::Ext') { JSON.generator = JSON::Ext::Generator }
127
125
  end
128
- unless $failed.has_key?('JSON::Pure')
129
- perf.add('JSON::Pure', 'generate') { JSON.generate($obj) }
130
- perf.before('JSON::Pure') { JSON.generator = JSON::Pure::Generator }
131
- end
132
126
  unless $failed.has_key?('Oj:strict')
133
- perf.add('Oj:strict', 'dump') { Oj.dump($obj, :mode => :strict) }
127
+ perf.add('Oj:strict', 'dump') { Oj.dump($obj) }
134
128
  end
135
129
  perf.add('Yajl', 'encode') { Yajl::Encoder.encode($obj) } unless $failed.has_key?('Yajl')
136
130
  perf.run($iter)
data/test/test_various.rb CHANGED
@@ -123,6 +123,8 @@ class Juice < Minitest::Test
123
123
  compat_bigdecimal: true,
124
124
  create_id: 'classy',
125
125
  create_additions: true,
126
+ cache_keys: false,
127
+ cache_str: 5,
126
128
  space: 'z',
127
129
  array_nl: 'a',
128
130
  object_nl: 'o',
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oj
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.11.7
4
+ version: 3.12.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Ohler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-22 00:00:00.000000000 Z
11
+ date: 2021-07-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -285,7 +285,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
285
285
  - !ruby/object:Gem::Version
286
286
  version: '0'
287
287
  requirements: []
288
- rubygems_version: 3.2.3
288
+ rubygems_version: 3.2.22
289
289
  signing_key:
290
290
  specification_version: 4
291
291
  summary: A fast JSON parser and serializer.