oj 3.13.2 → 3.13.6

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