oj 3.13.2 → 3.13.6

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/saj2.c CHANGED
@@ -158,7 +158,7 @@ static void add_str(ojParser p) {
158
158
  const char * str = buf_str(&p->buf);
159
159
  size_t len = buf_len(&p->buf);
160
160
 
161
- if (d->cache_str <= len) {
161
+ if (d->cache_str < len) {
162
162
  rstr = cache_intern(d->str_cache, str, len);
163
163
  } else {
164
164
  rstr = rb_utf8_str_new(str, len);
@@ -172,7 +172,7 @@ static void add_str_key(ojParser p) {
172
172
  const char * str = buf_str(&p->buf);
173
173
  size_t len = buf_len(&p->buf);
174
174
 
175
- if (d->cache_str <= len) {
175
+ if (d->cache_str < len) {
176
176
  rstr = cache_intern(d->str_cache, str, len);
177
177
  } else {
178
178
  rstr = rb_utf8_str_new(str, len);
@@ -336,7 +336,7 @@ void oj_set_parser_saj(ojParser p) {
336
336
  d->klen = 256;
337
337
  d->keys = ALLOC_N(VALUE, d->klen);
338
338
  d->tail = d->keys;
339
- d->str_cache = cache_create(0, form_str, true);
339
+ d->str_cache = cache_create(0, form_str, true, false);
340
340
 
341
341
  p->ctx = (void *)d;
342
342
  reset(p);
data/ext/oj/strict.c CHANGED
@@ -16,7 +16,7 @@
16
16
  VALUE oj_cstr_to_value(const char *str, size_t len, size_t cache_str) {
17
17
  volatile VALUE rstr = Qnil;
18
18
 
19
- if (len <= cache_str) {
19
+ if (len < cache_str) {
20
20
  rstr = oj_str_intern(str, len);
21
21
  } else {
22
22
  rstr = rb_str_new(str, len);
@@ -37,8 +37,8 @@ VALUE oj_calc_hash_key(ParseInfo pi, Val parent) {
37
37
  } else {
38
38
  rkey = rb_str_new(parent->key, parent->klen);
39
39
  rkey = oj_encode(rkey);
40
+ OBJ_FREEZE(rkey); // frozen when used as a Hash key anyway
40
41
  }
41
- OBJ_FREEZE(rkey);
42
42
  return rkey;
43
43
  }
44
44
  if (Yes == pi->options.sym_key) {
@@ -46,7 +46,6 @@ VALUE oj_calc_hash_key(ParseInfo pi, Val parent) {
46
46
  } else {
47
47
  rkey = oj_str_intern(parent->key, parent->klen);
48
48
  }
49
- OBJ_FREEZE(rkey);
50
49
  return rkey;
51
50
  }
52
51
 
data/ext/oj/usual.c CHANGED
@@ -39,7 +39,7 @@ typedef struct _col {
39
39
  typedef union _key {
40
40
  struct {
41
41
  int16_t len;
42
- char buf[22];
42
+ char buf[30];
43
43
  };
44
44
  struct {
45
45
  int16_t xlen; // should be the same as len
@@ -77,6 +77,7 @@ typedef struct _delegate {
77
77
  char * create_id;
78
78
  uint8_t create_id_len;
79
79
  uint8_t cache_str;
80
+ uint8_t cache_xrate;
80
81
  uint8_t miss_class;
81
82
  bool cache_keys;
82
83
  bool ignore_json_create;
@@ -100,7 +101,6 @@ static VALUE form_str(const char *str, size_t len) {
100
101
  }
101
102
 
102
103
  static VALUE form_sym(const char *str, size_t len) {
103
- // return ID2SYM(rb_intern3(str, len, oj_utf8_encoding));
104
104
  return rb_str_intern(rb_utf8_str_new(str, len));
105
105
  }
106
106
 
@@ -209,21 +209,21 @@ static void push(ojParser p, VALUE v) {
209
209
  static VALUE cache_key(ojParser p, Key kp) {
210
210
  Delegate d = (Delegate)p->ctx;
211
211
 
212
- if ((size_t)kp->len < sizeof(kp->buf) - 1) {
212
+ if ((size_t)kp->len < sizeof(kp->buf)) {
213
213
  return cache_intern(d->key_cache, kp->buf, kp->len);
214
214
  }
215
215
  return cache_intern(d->key_cache, kp->key, kp->len);
216
216
  }
217
217
 
218
218
  static VALUE str_key(ojParser p, Key kp) {
219
- if ((size_t)kp->len < sizeof(kp->buf) - 1) {
219
+ if ((size_t)kp->len < sizeof(kp->buf)) {
220
220
  return rb_str_freeze(rb_utf8_str_new(kp->buf, kp->len));
221
221
  }
222
222
  return rb_str_freeze(rb_utf8_str_new(kp->key, kp->len));
223
223
  }
224
224
 
225
225
  static VALUE sym_key(ojParser p, Key kp) {
226
- if ((size_t)kp->len < sizeof(kp->buf) - 1) {
226
+ if ((size_t)kp->len < sizeof(kp->buf)) {
227
227
  return rb_str_freeze(rb_str_intern(rb_utf8_str_new(kp->buf, kp->len)));
228
228
  }
229
229
  return rb_str_freeze(rb_str_intern(rb_utf8_str_new(kp->key, kp->len)));
@@ -232,7 +232,7 @@ static VALUE sym_key(ojParser p, Key kp) {
232
232
  static ID get_attr_id(ojParser p, Key kp) {
233
233
  Delegate d = (Delegate)p->ctx;
234
234
 
235
- if ((size_t)kp->len < sizeof(kp->buf) - 1) {
235
+ if ((size_t)kp->len < sizeof(kp->buf)) {
236
236
  return (ID)cache_intern(d->attr_cache, kp->buf, kp->len);
237
237
  }
238
238
  return (ID)cache_intern(d->attr_cache, kp->key, kp->len);
@@ -253,7 +253,7 @@ static void push_key(ojParser p) {
253
253
  d->kend = d->khead + cap;
254
254
  }
255
255
  d->ktail->len = klen;
256
- if (klen <= sizeof(d->ktail->buf) + 1) {
256
+ if (klen < sizeof(d->ktail->buf)) {
257
257
  memcpy(d->ktail->buf, key, klen);
258
258
  d->ktail->buf[klen] = '\0';
259
259
  } else {
@@ -323,7 +323,7 @@ static void open_array_key(ojParser p) {
323
323
  }
324
324
 
325
325
  static void close_object(ojParser p) {
326
- VALUE *vp;
326
+ VALUE * vp;
327
327
  Delegate d = (Delegate)p->ctx;
328
328
 
329
329
  d->ctail--;
@@ -336,7 +336,7 @@ static void close_object(ojParser p) {
336
336
  #if HAVE_RB_HASH_BULK_INSERT
337
337
  for (vp = head; kp < d->ktail; kp++, vp += 2) {
338
338
  *vp = d->get_key(p, kp);
339
- if (sizeof(kp->buf) - 1 < (size_t)kp->len) {
339
+ if (sizeof(kp->buf) <= (size_t)kp->len) {
340
340
  xfree(kp->key);
341
341
  }
342
342
  }
@@ -344,7 +344,7 @@ static void close_object(ojParser p) {
344
344
  #else
345
345
  for (vp = head; kp < d->ktail; kp++, vp += 2) {
346
346
  rb_hash_aset(obj, d->get_key(p, kp), *(vp + 1));
347
- if (sizeof(kp->buf) - 1 < (size_t)kp->len) {
347
+ if (sizeof(kp->buf) <= (size_t)kp->len) {
348
348
  xfree(kp->key);
349
349
  }
350
350
  }
@@ -356,7 +356,7 @@ static void close_object(ojParser p) {
356
356
  }
357
357
 
358
358
  static void close_object_class(ojParser p) {
359
- VALUE *vp;
359
+ VALUE * vp;
360
360
  Delegate d = (Delegate)p->ctx;
361
361
 
362
362
  d->ctail--;
@@ -368,7 +368,7 @@ static void close_object_class(ojParser p) {
368
368
 
369
369
  for (vp = head; kp < d->ktail; kp++, vp += 2) {
370
370
  rb_funcall(obj, hset_id, 2, d->get_key(p, kp), *(vp + 1));
371
- if (sizeof(kp->buf) - 1 < (size_t)kp->len) {
371
+ if (sizeof(kp->buf) <= (size_t)kp->len) {
372
372
  xfree(kp->key);
373
373
  }
374
374
  }
@@ -379,7 +379,7 @@ static void close_object_class(ojParser p) {
379
379
  }
380
380
 
381
381
  static void close_object_create(ojParser p) {
382
- VALUE *vp;
382
+ VALUE * vp;
383
383
  Delegate d = (Delegate)p->ctx;
384
384
 
385
385
  d->ctail--;
@@ -396,7 +396,7 @@ static void close_object_create(ojParser p) {
396
396
  #if HAVE_RB_HASH_BULK_INSERT
397
397
  for (vp = head; kp < d->ktail; kp++, vp += 2) {
398
398
  *vp = d->get_key(p, kp);
399
- if (sizeof(kp->buf) - 1 < (size_t)kp->len) {
399
+ if (sizeof(kp->buf) <= (size_t)kp->len) {
400
400
  xfree(kp->key);
401
401
  }
402
402
  }
@@ -404,7 +404,7 @@ static void close_object_create(ojParser p) {
404
404
  #else
405
405
  for (vp = head; kp < d->ktail; kp++, vp += 2) {
406
406
  rb_hash_aset(obj, d->get_key(p, kp), *(vp + 1));
407
- if (sizeof(kp->buf) - 1 < (size_t)kp->len) {
407
+ if (sizeof(kp->buf) <= (size_t)kp->len) {
408
408
  xfree(kp->key);
409
409
  }
410
410
  }
@@ -413,7 +413,7 @@ static void close_object_create(ojParser p) {
413
413
  obj = rb_class_new_instance(0, NULL, d->hash_class);
414
414
  for (vp = head; kp < d->ktail; kp++, vp += 2) {
415
415
  rb_funcall(obj, hset_id, 2, d->get_key(p, kp), *(vp + 1));
416
- if (sizeof(kp->buf) - 1 < (size_t)kp->len) {
416
+ if (sizeof(kp->buf) <= (size_t)kp->len) {
417
417
  xfree(kp->key);
418
418
  }
419
419
  }
@@ -428,7 +428,7 @@ static void close_object_create(ojParser p) {
428
428
  #if HAVE_RB_HASH_BULK_INSERT
429
429
  for (vp = head; kp < d->ktail; kp++, vp += 2) {
430
430
  *vp = d->get_key(p, kp);
431
- if (sizeof(kp->buf) - 1 < (size_t)kp->len) {
431
+ if (sizeof(kp->buf) <= (size_t)kp->len) {
432
432
  xfree(kp->key);
433
433
  }
434
434
  }
@@ -436,7 +436,7 @@ static void close_object_create(ojParser p) {
436
436
  #else
437
437
  for (vp = head; kp < d->ktail; kp++, vp += 2) {
438
438
  rb_hash_aset(arg, d->get_key(p, kp), *(vp + 1));
439
- if (sizeof(kp->buf) - 1 < (size_t)kp->len) {
439
+ if (sizeof(kp->buf) <= (size_t)kp->len) {
440
440
  xfree(kp->key);
441
441
  }
442
442
  }
@@ -446,7 +446,7 @@ static void close_object_create(ojParser p) {
446
446
  obj = rb_class_new_instance(0, NULL, clas);
447
447
  for (vp = head; kp < d->ktail; kp++, vp += 2) {
448
448
  rb_ivar_set(obj, get_attr_id(p, kp), *(vp + 1));
449
- if (sizeof(kp->buf) - 1 < (size_t)kp->len) {
449
+ if (sizeof(kp->buf) <= (size_t)kp->len) {
450
450
  xfree(kp->key);
451
451
  }
452
452
  }
@@ -471,7 +471,7 @@ static void close_array(ojParser p) {
471
471
  }
472
472
 
473
473
  static void close_array_class(ojParser p) {
474
- VALUE *vp;
474
+ VALUE * vp;
475
475
  Delegate d = (Delegate)p->ctx;
476
476
 
477
477
  d->ctail--;
@@ -686,10 +686,10 @@ static void mark(ojParser p) {
686
686
  return;
687
687
  }
688
688
  Delegate d = (Delegate)p->ctx;
689
- VALUE *vp;
689
+ VALUE * vp;
690
690
 
691
691
  if (NULL == d) {
692
- return;
692
+ return;
693
693
  }
694
694
  cache_mark(d->str_cache);
695
695
  if (NULL != d->sym_cache) {
@@ -792,6 +792,30 @@ static VALUE opt_cache_strings_set(ojParser p, VALUE value) {
792
792
  return INT2NUM((int)d->cache_str);
793
793
  }
794
794
 
795
+ static VALUE opt_cache_expunge(ojParser p, VALUE value) {
796
+ Delegate d = (Delegate)p->ctx;
797
+
798
+ return INT2NUM((int)d->cache_xrate);
799
+ }
800
+
801
+ static VALUE opt_cache_expunge_set(ojParser p, VALUE value) {
802
+ Delegate d = (Delegate)p->ctx;
803
+ int rate = NUM2INT(value);
804
+
805
+ if (rate < 0) {
806
+ rate = 0;
807
+ } else if (3 < rate) {
808
+ rate = 3;
809
+ }
810
+ d->cache_xrate = (uint8_t)rate;
811
+ cache_set_expunge_rate(d->str_cache, rate);
812
+ cache_set_expunge_rate(d->attr_cache, rate);
813
+ if (NULL != d->sym_cache) {
814
+ cache_set_expunge_rate(d->sym_cache, rate);
815
+ }
816
+ return INT2NUM((int)rate);
817
+ }
818
+
795
819
  static VALUE opt_capacity(ojParser p, VALUE value) {
796
820
  Delegate d = (Delegate)p->ctx;
797
821
 
@@ -830,11 +854,7 @@ static VALUE opt_class_cache_set(ojParser p, VALUE value) {
830
854
 
831
855
  if (Qtrue == value) {
832
856
  if (NULL == d->class_cache) {
833
- if (MISS_AUTO == d->miss_class) {
834
- d->class_cache = cache_create(0, form_class_auto, true);
835
- } else {
836
- d->class_cache = cache_create(0, form_class, false);
837
- }
857
+ d->class_cache = cache_create(0, form_class_auto, MISS_AUTO == d->miss_class, false);
838
858
  }
839
859
  } else if (NULL != d->class_cache) {
840
860
  cache_free(d->class_cache);
@@ -1078,7 +1098,8 @@ static VALUE opt_symbol_keys_set(ojParser p, VALUE value) {
1078
1098
  Delegate d = (Delegate)p->ctx;
1079
1099
 
1080
1100
  if (Qtrue == value) {
1081
- d->sym_cache = cache_create(0, form_sym, true);
1101
+ d->sym_cache = cache_create(0, form_sym, true, false);
1102
+ cache_set_expunge_rate(d->sym_cache, d->cache_xrate);
1082
1103
  d->key_cache = d->sym_cache;
1083
1104
  if (!d->cache_keys) {
1084
1105
  d->get_key = sym_key;
@@ -1097,13 +1118,15 @@ static VALUE opt_symbol_keys_set(ojParser p, VALUE value) {
1097
1118
 
1098
1119
  static VALUE option(ojParser p, const char *key, VALUE value) {
1099
1120
  struct opt *op;
1100
- struct opt opts[] = {
1121
+ struct opt opts[] = {
1101
1122
  {.name = "array_class", .func = opt_array_class},
1102
1123
  {.name = "array_class=", .func = opt_array_class_set},
1103
1124
  {.name = "cache_keys", .func = opt_cache_keys},
1104
1125
  {.name = "cache_keys=", .func = opt_cache_keys_set},
1105
1126
  {.name = "cache_strings", .func = opt_cache_strings},
1106
1127
  {.name = "cache_strings=", .func = opt_cache_strings_set},
1128
+ {.name = "cache_expunge", .func = opt_cache_expunge},
1129
+ {.name = "cache_expunge=", .func = opt_cache_expunge_set},
1107
1130
  {.name = "capacity", .func = opt_capacity},
1108
1131
  {.name = "capacity=", .func = opt_capacity_set},
1109
1132
  {.name = "class_cache", .func = opt_class_cache},
@@ -1163,6 +1186,7 @@ void oj_set_parser_usual(ojParser p) {
1163
1186
  d->create_id = NULL;
1164
1187
  d->create_id_len = 0;
1165
1188
  d->miss_class = MISS_IGNORE;
1189
+ d->cache_xrate = 1;
1166
1190
 
1167
1191
  Funcs f = &p->funcs[TOP_FUN];
1168
1192
  f->add_null = add_null;
@@ -1203,8 +1227,8 @@ void oj_set_parser_usual(ojParser p) {
1203
1227
  f->open_object = open_object_key;
1204
1228
  f->close_object = close_object;
1205
1229
 
1206
- d->str_cache = cache_create(0, form_str, true);
1207
- d->attr_cache = cache_create(0, form_attr, false);
1230
+ d->str_cache = cache_create(0, form_str, true, false);
1231
+ d->attr_cache = cache_create(0, form_attr, false, false);
1208
1232
  d->sym_cache = NULL;
1209
1233
  d->class_cache = NULL;
1210
1234
  d->key_cache = d->str_cache;
data/ext/oj/wab.c CHANGED
@@ -305,11 +305,14 @@ static VALUE calc_hash_key(ParseInfo pi, Val parent) {
305
305
  if (Yes == pi->options.cache_keys) {
306
306
  rkey = oj_sym_intern(parent->key, parent->klen);
307
307
  } else {
308
- rkey = rb_str_new(parent->key, parent->klen);
309
- rkey = oj_encode(rkey);
308
+ #if HAVE_RB_ENC_INTERNED_STR
309
+ rkey = rb_enc_interned_str(parent->key, parent->klen, oj_utf8_encoding);
310
+ #else
311
+ rkey = rb_utf8_str_new(parent->key, parent->klen);
310
312
  rkey = rb_str_intern(rkey);
313
+ OBJ_FREEZE(rkey);
314
+ #endif
311
315
  }
312
- OBJ_FREEZE(rkey);
313
316
  return rkey;
314
317
  }
315
318
 
data/lib/oj/state.rb CHANGED
@@ -1,7 +1,7 @@
1
1
 
2
2
  module JSON
3
3
  module Ext
4
- module Generator
4
+ module Generator
5
5
  unless defined?(::JSON::Ext::Generator::State)
6
6
  # This class exists for json gem compatibility only. While it can be
7
7
  # used as the options for other than compatibility a simple Hash is
@@ -44,11 +44,11 @@ module JSON
44
44
  def to_h()
45
45
  return @attrs.dup
46
46
  end
47
-
47
+
48
48
  def to_hash()
49
49
  return @attrs.dup
50
50
  end
51
-
51
+
52
52
  def allow_nan?()
53
53
  @attrs[:allow_nan]
54
54
  end
@@ -104,7 +104,7 @@ module JSON
104
104
  def has_key?(k)
105
105
  @attrs.has_key?(key.to_sym)
106
106
  end
107
-
107
+
108
108
  # Handles requests for Hash values. Others cause an Exception to be raised.
109
109
  # @param [Symbol|String] m method symbol
110
110
  # @return [Boolean] the value of the specified instance variable.
@@ -116,11 +116,12 @@ module JSON
116
116
  m = m.to_s[0..-2]
117
117
  m = m.to_sym
118
118
  return @attrs.store(m, args[0])
119
- else
119
+ end
120
+ if @attrs.has_key?(m.to_sym)
120
121
  raise ArgumentError.new("wrong number of arguments (#{args.size} for 0 with #{m}) to method #{m}") unless args.nil? or args.empty?
121
122
  return @attrs[m.to_sym]
122
- end
123
- raise NoMethodError.new("undefined method #{m}", m)
123
+ end
124
+ return @attrs.send(m, *args, &block)
124
125
  end
125
126
 
126
127
  end # State
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.13.2'
4
+ VERSION = '3.13.6'
5
5
  end
data/pages/Options.md CHANGED
@@ -75,12 +75,22 @@ parse option to match the JSON gem. In that case either `Float`,
75
75
  If true Hash keys are cached or interned. There are trade-offs with
76
76
  caching keys. Large caches will use more memory and in extreme cases
77
77
  (like over a million) the cache may be slower than not using
78
- it. Repeated parsing of similar JSON docs is where cache_keys shines.
78
+ it. Repeated parsing of similar JSON docs is where cache_keys shines
79
+ especially with symbol keys.
80
+
81
+ There is a maximum length for cached keys. Any key longer than 34
82
+ bytes is not cached. Everything still works but the key is not cached.
79
83
 
80
84
  ### :cache_strings [Int]
81
85
 
82
86
  Shorter strings can be cached for better performance. A limit,
83
- cache_strings, defines the upper limit on what strings are cached.
87
+ cache_strings, defines the upper limit on what strings are cached. As
88
+ with cached keys only strings less than 35 bytes are cached even if
89
+ the limit is set higher. Setting the limit to zero effectively
90
+ disables the caching of string values.
91
+
92
+ Note that caching for strings is for string values and not Hash keys
93
+ or Object attributes.
84
94
 
85
95
  ### :circular [Boolean]
86
96
 
data/test/bar.rb CHANGED
@@ -1,35 +1,16 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $: << File.dirname(__FILE__)
4
- $oj_dir = File.dirname(File.expand_path(File.dirname(__FILE__)))
5
- %w(lib ext).each do |dir|
6
- $: << File.join($oj_dir, dir)
7
- end
8
-
9
- require 'active_support'
10
- require "active_support/json"
11
-
12
- $s = "\u2014 & \n \u{1F618}"
13
-
14
- =begin
15
- def check(label)
16
- puts "\n--- #{label} --------------------"
17
-
18
- ActiveSupport::JSON::Encoding.use_standard_json_time_format = true
19
- puts "with standard_json == true: t.to_json - #{$t.to_json}"
20
- ActiveSupport::JSON::Encoding.use_standard_json_time_format = false
21
- puts "with standard_json == false: t.to_json - #{$t.to_json}"
22
- end
23
-
24
- check('Before Oj')
25
- =end
3
+ $: << '.'
4
+ $: << File.join(File.dirname(__FILE__), "../lib")
5
+ $: << File.join(File.dirname(__FILE__), "../ext")
26
6
 
27
7
  require 'oj'
28
8
 
29
- ActiveSupport::JSON::Encoding.escape_html_entities_in_json = false
30
- puts "ActiveSupport.encode(s) - #{ActiveSupport::JSON.encode($s)}"
9
+ json = %|[{"x12345678901234567890": true}]|
31
10
 
32
- Oj.optimize_rails
33
- Oj.default_options = { mode: :rails }
11
+ p = Oj::Parser.new(:usual)
12
+ p.cache_keys = false
13
+ p.symbol_keys = true
14
+ x = p.parse(json)
34
15
 
35
- puts "Oj.dump(s) - #{Oj.dump($s)}"
16
+ pp x