oj 3.13.12 → 3.13.15

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: f7a88552e986523c822f5122a3ae557833daa68a31b606afd53d6a187b188e4b
4
- data.tar.gz: b58d251e6020e4400322a37f2bfcbf1423578892bb9c6571ff07b782b248cbd8
3
+ metadata.gz: 2dd6fd9c107efe5095ca235c398e2fb7cc4fb9cdd9feffb4f27fef1ed1e3faa3
4
+ data.tar.gz: 072e3744f4cbb880f1e5296ad1abba448341d9934173fa101ba1d65efe20de64
5
5
  SHA512:
6
- metadata.gz: cb0cd1c01c4cdaed0a21d31b27b02dafb222f104ac5698f146ed9bcf58325c3bdf99d8308f6638e7100fab14caeb46d103abb896d16d2dfcf5cdde1081b7838a
7
- data.tar.gz: 1ebd2819902faba5ebddf98a384ee27b1d35820d8beaae42bc254809245d3bdfeefec587769aea7c5a63ca85625bc93e543c9d3b1d127f8c88c44f9c39117d0e
6
+ metadata.gz: 76fbaa3e575553ffbf37e45447429b58da392d58e59afa82491363a17ee3ab7cacf5283986db7242f1cf8b0340449d8a1d97a6f54c288076110a2fdc5ccebf30
7
+ data.tar.gz: 116f07d7db9124f62007eff33a2583f4de5a1338009fec59eca267a483be229285a7ec66c6fbb1feb92f05284afe76ae39629aca2e8f2a7ff20caa27adddc0c4
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 3.13.15 - 2022-07-03
4
+
5
+ - Fixed issue dumping NaN value in object mode.
6
+
7
+ ## 3.13.14 - 2022-06-03
8
+
9
+ - Double fclose() due to bad merger fixed by tonobo.
10
+
11
+ ## 3.13.13 - 2022-05-20
12
+
13
+ - Fixed flooding stdout with debug output when dumping.
14
+
3
15
  ## 3.13.12 - 2022-05-20
4
16
 
5
17
  - Fixed crash on no arguments to pretty_generate. Now raises an exception.
data/ext/oj/dump.c CHANGED
@@ -32,6 +32,7 @@ static const char nan_val[] = NAN_VAL;
32
32
  typedef unsigned long ulong;
33
33
 
34
34
  static size_t hibit_friendly_size(const uint8_t *str, size_t len);
35
+ static size_t slash_friendly_size(const uint8_t *str, size_t len);
35
36
  static size_t xss_friendly_size(const uint8_t *str, size_t len);
36
37
  static size_t ascii_friendly_size(const uint8_t *str, size_t len);
37
38
 
@@ -59,6 +60,17 @@ static char hibit_friendly_chars[256] = "\
59
60
  11111111111111111111111111111111\
60
61
  11111111111111111111111111111111";
61
62
 
63
+ // JSON standard but escape forward slashes `/`
64
+ static char slash_friendly_chars[256] = "\
65
+ 66666666222622666666666666666666\
66
+ 11211111111111121111111111111111\
67
+ 11111111111111111111111111112111\
68
+ 11111111111111111111111111111111\
69
+ 11111111111111111111111111111111\
70
+ 11111111111111111111111111111111\
71
+ 11111111111111111111111111111111\
72
+ 11111111111111111111111111111111";
73
+
62
74
  // High bit set characters are always encoded as unicode. Worse case is 3
63
75
  // bytes per character in the output. That makes this conservative.
64
76
  static char ascii_friendly_chars[256] = "\
@@ -143,6 +155,10 @@ inline static size_t hibit_friendly_size(const uint8_t *str, size_t len) {
143
155
  return calculate_string_size(str, len, hibit_friendly_chars);
144
156
  }
145
157
 
158
+ inline static size_t slash_friendly_size(const uint8_t *str, size_t len) {
159
+ return calculate_string_size(str, len, slash_friendly_chars);
160
+ }
161
+
146
162
  inline static size_t ascii_friendly_size(const uint8_t *str, size_t len) {
147
163
  return calculate_string_size(str, len, ascii_friendly_chars);
148
164
  }
@@ -365,7 +381,6 @@ void oj_dump_time(VALUE obj, Out out, int withZone) {
365
381
  long long sec;
366
382
  long long nsec;
367
383
 
368
- #ifdef HAVE_RB_TIME_TIMESPEC
369
384
  // rb_time_timespec as well as rb_time_timeeval have a bug that causes an
370
385
  // exception to be raised if a time is before 1970 on 32 bit systems so
371
386
  // check the timespec size and use the ruby calls if a 32 bit system.
@@ -378,10 +393,6 @@ void oj_dump_time(VALUE obj, Out out, int withZone) {
378
393
  sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
379
394
  nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
380
395
  }
381
- #else
382
- sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
383
- nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
384
- #endif
385
396
 
386
397
  *b-- = '\0';
387
398
  if (withZone) {
@@ -467,7 +478,6 @@ void oj_dump_xml_time(VALUE obj, Out out) {
467
478
  int tzhour, tzmin;
468
479
  char tzsign = '+';
469
480
 
470
- #ifdef HAVE_RB_TIME_TIMESPEC
471
481
  if (16 <= sizeof(struct timespec)) {
472
482
  struct timespec ts = rb_time_timespec(obj);
473
483
 
@@ -477,10 +487,6 @@ void oj_dump_xml_time(VALUE obj, Out out) {
477
487
  sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
478
488
  nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
479
489
  }
480
- #else
481
- sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
482
- nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
483
- #endif
484
490
 
485
491
  assure_size(out, 36);
486
492
  if (9 > out->opts->sec_prec) {
@@ -614,7 +620,6 @@ void oj_write_obj_to_file(VALUE obj, const char *path, Options copts) {
614
620
 
615
621
  oj_out_free(&out);
616
622
 
617
- fclose(f);
618
623
  if (!ok) {
619
624
  int err = ferror(f);
620
625
  fclose(f);
@@ -757,6 +762,11 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
757
762
  cmap = ascii_friendly_chars;
758
763
  size = ascii_friendly_size((uint8_t *)str, cnt);
759
764
  break;
765
+ case SlashEsc:
766
+ has_hi = true;
767
+ cmap = slash_friendly_chars;
768
+ size = slash_friendly_size((uint8_t *)str, cnt);
769
+ break;
760
770
  case XSSEsc:
761
771
  cmap = xss_friendly_chars;
762
772
  size = xss_friendly_size((uint8_t *)str, cnt);
@@ -951,7 +961,6 @@ void oj_grow_out(Out out, size_t len) {
951
961
  long pos = out->cur - out->buf;
952
962
  char *buf = out->buf;
953
963
 
954
- printf("*** grow %ld\n", len);
955
964
  size *= 2;
956
965
  if (size <= len * 2 + pos) {
957
966
  size += len;
@@ -1132,7 +1141,7 @@ void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
1132
1141
  } else if (isnan(d)) {
1133
1142
  if (ObjectMode == out->opts->mode) {
1134
1143
  strcpy(buf, nan_val);
1135
- cnt = sizeof(ninf_val) - 1;
1144
+ cnt = sizeof(nan_val) - 1;
1136
1145
  } else {
1137
1146
  NanDump nd = out->opts->dump_opts.nan_dump;
1138
1147
 
data/ext/oj/dump_compat.c CHANGED
@@ -444,7 +444,6 @@ time_alt(VALUE obj, int depth, Out out) {
444
444
  time_t sec;
445
445
  long long nsec;
446
446
 
447
- #ifdef HAVE_RB_TIME_TIMESPEC
448
447
  if (16 <= sizeof(struct timespec)) {
449
448
  struct timespec ts = rb_time_timespec(obj);
450
449
 
@@ -454,10 +453,6 @@ time_alt(VALUE obj, int depth, Out out) {
454
453
  sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
455
454
  nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
456
455
  }
457
- #else
458
- sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
459
- nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
460
- #endif
461
456
 
462
457
  attrs[0].num = sec;
463
458
  attrs[1].num = nsec;
data/ext/oj/dump_object.c CHANGED
@@ -315,7 +315,6 @@ static void dump_hash_class(VALUE obj, VALUE clas, int depth, Out out) {
315
315
  *out->cur = '\0';
316
316
  }
317
317
 
318
- #ifdef HAVE_RB_IVAR_FOREACH
319
318
  static int dump_attr_cb(ID key, VALUE value, VALUE ov) {
320
319
  Out out = (Out)ov;
321
320
  int depth = out->depth;
@@ -358,7 +357,6 @@ static int dump_attr_cb(ID key, VALUE value, VALUE ov) {
358
357
 
359
358
  return ST_CONTINUE;
360
359
  }
361
- #endif
362
360
 
363
361
  static void dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
364
362
  dump_hash_class(obj, rb_obj_class(obj), depth, out);
@@ -510,19 +508,8 @@ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out)
510
508
  default: break;
511
509
  }
512
510
  {
513
- int cnt;
514
- #ifdef HAVE_RB_IVAR_COUNT
515
- cnt = (int)rb_ivar_count(obj);
516
- #else
517
- volatile VALUE vars = rb_funcall2(obj, oj_instance_variables_id, 0, 0);
518
- VALUE * np = RARRAY_PTR(vars);
519
- ID vid;
520
- const char * attr;
521
- int i;
522
- int first = 1;
523
-
524
- cnt = (int)RARRAY_LEN(vars);
525
- #endif
511
+ int cnt = (int)rb_ivar_count(obj);
512
+
526
513
  if (Qundef != clas && 0 < cnt) {
527
514
  *out->cur++ = ',';
528
515
  }
@@ -535,52 +522,10 @@ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out)
535
522
  }
536
523
  }
537
524
  out->depth = depth + 1;
538
- #ifdef HAVE_RB_IVAR_FOREACH
539
525
  rb_ivar_foreach(obj, dump_attr_cb, (VALUE)out);
540
526
  if (',' == *(out->cur - 1)) {
541
527
  out->cur--; // backup to overwrite last comma
542
528
  }
543
- #else
544
- size = d2 * out->indent + 1;
545
- for (i = cnt; 0 < i; i--, np++) {
546
- VALUE value;
547
-
548
- vid = rb_to_id(*np);
549
- attr = rb_id2name(vid);
550
- if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
551
- continue;
552
- }
553
- value = rb_ivar_get(obj, vid);
554
-
555
- if (dump_ignore(out->opts, value)) {
556
- continue;
557
- }
558
- if (out->omit_nil && Qnil == value) {
559
- continue;
560
- }
561
- if (first) {
562
- first = 0;
563
- } else {
564
- *out->cur++ = ',';
565
- }
566
- assure_size(out, size);
567
- fill_indent(out, d2);
568
- if ('@' == *attr) {
569
- attr++;
570
- oj_dump_cstr(attr, strlen(attr), 0, 0, out);
571
- } else {
572
- char buf[32];
573
-
574
- *buf = '~';
575
- strncpy(buf + 1, attr, sizeof(buf) - 2);
576
- buf[sizeof(buf) - 1] = '\0';
577
- oj_dump_cstr(buf, strlen(attr) + 1, 0, 0, out);
578
- }
579
- *out->cur++ = ':';
580
- oj_dump_obj_val(value, d2, out);
581
- assure_size(out, 2);
582
- }
583
- #endif
584
529
  if (rb_obj_is_kind_of(obj, rb_eException)) {
585
530
  volatile VALUE rv;
586
531
 
data/ext/oj/extconf.rb CHANGED
@@ -23,14 +23,10 @@ dflags = {
23
23
  'RSTRUCT_LEN_RETURNS_INTEGER_OBJECT' => ('ruby' == type && '2' == version[0] && '4' == version[1] && '1' >= version[2]) ? 1 : 0,
24
24
  }
25
25
 
26
- have_func('rb_time_timespec')
27
- have_func('rb_ivar_count')
28
- have_func('rb_ivar_foreach')
29
26
  # Support for compaction.
30
27
  have_func('rb_gc_mark_movable')
31
28
  have_func('stpcpy')
32
29
  have_func('pthread_mutex_init')
33
- have_func('rb_enc_associate')
34
30
  have_func('rb_enc_interned_str')
35
31
  have_func('rb_ext_ractor_safe', 'ruby.h')
36
32
  # rb_hash_bulk_insert is deep down in a header not included in normal build and that seems to fool have_func.
@@ -38,6 +34,11 @@ have_func('rb_hash_bulk_insert', 'ruby.h') unless '2' == version[0] && '6' == ve
38
34
 
39
35
  dflags['OJ_DEBUG'] = true unless ENV['OJ_DEBUG'].nil?
40
36
 
37
+ if try_cflags('-msse4.2')
38
+ $CPPFLAGS += ' -msse4.2'
39
+ dflags['OJ_USE_SSE4_2'] = 1
40
+ end
41
+
41
42
  dflags.each do |k,v|
42
43
  if v.nil?
43
44
  $CPPFLAGS += " -D#{k}"
data/ext/oj/mimic_json.c CHANGED
@@ -388,6 +388,10 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
388
388
  VALUE active_hack[1];
389
389
 
390
390
  if (Qundef == state_class) {
391
+ rb_warn(
392
+ "Oj::Rails.mimic_JSON was called implicitly. "
393
+ "Call it explicitly beforehand if you want to remove this warning."
394
+ );
391
395
  oj_define_mimic_json(0, NULL, Qnil);
392
396
  }
393
397
  active_hack[0] = rb_funcall(state_class, oj_new_id, 0);
@@ -460,7 +464,7 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
460
464
  if (0 == argc) {
461
465
  rb_raise(rb_eArgError, "wrong number of arguments (0))");
462
466
  }
463
- if (1 == argc) {
467
+ if (1 == argc || Qnil == argv[1]) {
464
468
  h = rb_hash_new();
465
469
  } else {
466
470
  h = argv[1];
@@ -481,6 +485,10 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
481
485
  rb_hash_aset(h, oj_array_nl_sym, rb_str_new2("\n"));
482
486
  }
483
487
  if (Qundef == state_class) {
488
+ rb_warn(
489
+ "Oj::Rails.mimic_JSON was called implicitly. "
490
+ "Call it explicitly beforehand if you want to remove this warning."
491
+ );
484
492
  oj_define_mimic_json(0, NULL, Qnil);
485
493
  }
486
494
  rargs[1] = rb_funcall(state_class, oj_new_id, 1, h);
@@ -536,14 +544,6 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE info) {
536
544
  }
537
545
  } else if (oj_decimal_class_sym == k) {
538
546
  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
547
  }
548
548
  return ST_CONTINUE;
549
549
  }
@@ -573,11 +573,21 @@ static VALUE mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
573
573
  pi.max_depth = 100;
574
574
 
575
575
  if (Qnil != ropts) {
576
+ VALUE v;
577
+
576
578
  if (T_HASH != rb_type(ropts)) {
577
579
  rb_raise(rb_eArgError, "options must be a hash.");
578
580
  }
579
581
 
580
582
  rb_hash_foreach(ropts, parse_options_cb, (VALUE)&pi);
583
+ v = rb_hash_lookup(ropts, oj_max_nesting_sym);
584
+ if (Qtrue == v) {
585
+ pi.max_depth = 100;
586
+ } else if (Qfalse == v || Qnil == v) {
587
+ pi.max_depth = 0;
588
+ } else if (T_FIXNUM == rb_type(v)) {
589
+ pi.max_depth = NUM2INT(v);
590
+ }
581
591
  oj_parse_opt_match_string(&pi.options.str_rx, ropts);
582
592
  if (Yes == pi.options.create_ok && Yes == pi.options.sym_key) {
583
593
  rb_raise(rb_eArgError, ":symbolize_names and :create_additions can not both be true.");
data/ext/oj/oj.c CHANGED
@@ -45,7 +45,6 @@ ID oj_hash_key_id;
45
45
  ID oj_hash_set_id;
46
46
  ID oj_hash_start_id;
47
47
  ID oj_iconv_id;
48
- ID oj_instance_variables_id;
49
48
  ID oj_json_create_id;
50
49
  ID oj_length_id;
51
50
  ID oj_new_id;
@@ -137,6 +136,7 @@ static VALUE rails_sym;
137
136
  static VALUE raise_sym;
138
137
  static VALUE ruby_sym;
139
138
  static VALUE sec_prec_sym;
139
+ static VALUE slash_sym;
140
140
  static VALUE strict_sym;
141
141
  static VALUE symbol_keys_sym;
142
142
  static VALUE time_format_sym;
@@ -405,6 +405,7 @@ static VALUE get_def_opts(VALUE self) {
405
405
  switch (oj_default_options.escape_mode) {
406
406
  case NLEsc: rb_hash_aset(opts, escape_mode_sym, newline_sym); break;
407
407
  case JSONEsc: rb_hash_aset(opts, escape_mode_sym, json_sym); break;
408
+ case SlashEsc: rb_hash_aset(opts, escape_mode_sym, slash_sym); break;
408
409
  case XSSEsc: rb_hash_aset(opts, escape_mode_sym, xss_safe_sym); break;
409
410
  case ASCIIEsc: rb_hash_aset(opts, escape_mode_sym, ascii_sym); break;
410
411
  case JXEsc: rb_hash_aset(opts, escape_mode_sym, unicode_xss_sym); break;
@@ -734,6 +735,8 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
734
735
  copts->escape_mode = NLEsc;
735
736
  } else if (json_sym == v) {
736
737
  copts->escape_mode = JSONEsc;
738
+ } else if (slash_sym == v) {
739
+ copts->escape_mode = SlashEsc;
737
740
  } else if (xss_safe_sym == v) {
738
741
  copts->escape_mode = XSSEsc;
739
742
  } else if (ascii_sym == v) {
@@ -1148,7 +1151,17 @@ static VALUE load_file(int argc, VALUE *argv, VALUE self) {
1148
1151
  }
1149
1152
  }
1150
1153
  path = StringValuePtr(*argv);
1151
- if (0 == (fd = open(path, O_RDONLY))) {
1154
+ #ifdef _WIN32
1155
+ {
1156
+ WCHAR *wide_path;
1157
+ wide_path = rb_w32_mbstr_to_wstr(CP_UTF8, path, -1, NULL);
1158
+ fd = rb_w32_wopen(wide_path, O_RDONLY);
1159
+ free(wide_path);
1160
+ }
1161
+ #else
1162
+ fd = open(path, O_RDONLY);
1163
+ #endif
1164
+ if (0 == fd) {
1152
1165
  rb_raise(rb_eIOError, "%s", strerror(errno));
1153
1166
  }
1154
1167
  switch (mode) {
@@ -1814,7 +1827,6 @@ void Init_oj(void) {
1814
1827
  oj_hash_set_id = rb_intern("hash_set");
1815
1828
  oj_hash_start_id = rb_intern("hash_start");
1816
1829
  oj_iconv_id = rb_intern("iconv");
1817
- oj_instance_variables_id = rb_intern("instance_variables");
1818
1830
  oj_json_create_id = rb_intern("json_create");
1819
1831
  oj_length_id = rb_intern("length");
1820
1832
  oj_new_id = rb_intern("new");
@@ -1977,6 +1989,8 @@ void Init_oj(void) {
1977
1989
  rb_gc_register_address(&ruby_sym);
1978
1990
  sec_prec_sym = ID2SYM(rb_intern("second_precision"));
1979
1991
  rb_gc_register_address(&sec_prec_sym);
1992
+ slash_sym = ID2SYM(rb_intern("slash"));
1993
+ rb_gc_register_address(&slash_sym);
1980
1994
  strict_sym = ID2SYM(rb_intern("strict"));
1981
1995
  rb_gc_register_address(&strict_sym);
1982
1996
  symbol_keys_sym = ID2SYM(rb_intern("symbol_keys"));
data/ext/oj/oj.h CHANGED
@@ -66,6 +66,7 @@ typedef enum { UnixTime = 'u', UnixZTime = 'z', XmlTime = 'x', RubyTime = 'r' }
66
66
  typedef enum {
67
67
  NLEsc = 'n',
68
68
  JSONEsc = 'j',
69
+ SlashEsc = 's',
69
70
  XSSEsc = 'x',
70
71
  ASCIIEsc = 'a',
71
72
  JXEsc = 'g', // json gem
@@ -346,7 +347,6 @@ extern ID oj_hash_key_id;
346
347
  extern ID oj_hash_set_id;
347
348
  extern ID oj_hash_start_id;
348
349
  extern ID oj_iconv_id;
349
- extern ID oj_instance_variables_id;
350
350
  extern ID oj_json_create_id;
351
351
  extern ID oj_length_id;
352
352
  extern ID oj_new_id;
data/ext/oj/parse.c CHANGED
@@ -327,26 +327,61 @@ static void read_escaped_str(ParseInfo pi, const char *start) {
327
327
  buf_cleanup(&buf);
328
328
  }
329
329
 
330
- static void read_str(ParseInfo pi) {
331
- const char *str = pi->cur;
332
- Val parent = stack_peek(&pi->stack);
333
-
330
+ static inline void scan_string_noSIMD(ParseInfo pi) {
334
331
  for (; '"' != *pi->cur; pi->cur++) {
335
- if (pi->end <= pi->cur) {
336
- oj_set_error_at(pi,
337
- oj_parse_error_class,
338
- __FILE__,
339
- __LINE__,
340
- "quoted string not terminated");
332
+ if (pi->end <= pi->cur || '\0' == *pi->cur || '\\' == *pi->cur) {
341
333
  return;
342
- } else if ('\0' == *pi->cur) {
343
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "NULL byte in string");
344
- return;
345
- } else if ('\\' == *pi->cur) {
346
- read_escaped_str(pi, str);
334
+ }
335
+ }
336
+ }
337
+
338
+ #if defined(OJ_USE_SSE4_2)
339
+ #include <nmmintrin.h>
340
+
341
+ static inline void scan_string_SIMD(ParseInfo pi) {
342
+ static const char chars[16] = "\x00\\\"";
343
+ const __m128i terminate = _mm_loadu_si128((const __m128i *)&chars[0]);
344
+ const char *end = (const char *)(pi->end - 16);
345
+
346
+ for (; pi->cur <= end; pi->cur += 16) {
347
+ const __m128i string = _mm_loadu_si128((const __m128i *)pi->cur);
348
+ const int r = _mm_cmpestri(terminate, 3, string, 16, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT);
349
+ if (r != 16) {
350
+ pi->cur = (const char*)(pi->cur + r);
347
351
  return;
348
352
  }
349
353
  }
354
+
355
+ scan_string_noSIMD(pi);
356
+ }
357
+ #endif
358
+
359
+ static void read_str(ParseInfo pi) {
360
+ const char *str = pi->cur;
361
+ Val parent = stack_peek(&pi->stack);
362
+
363
+ #if defined(OJ_USE_SSE4_2)
364
+ scan_string_SIMD(pi);
365
+ #else
366
+ scan_string_noSIMD(pi);
367
+ #endif
368
+ if (RB_UNLIKELY(pi->end <= pi->cur)) {
369
+ oj_set_error_at(pi,
370
+ oj_parse_error_class,
371
+ __FILE__,
372
+ __LINE__,
373
+ "quoted string not terminated");
374
+ return;
375
+ }
376
+ if (RB_UNLIKELY('\0' == *pi->cur)) {
377
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "NULL byte in string");
378
+ return;
379
+ }
380
+ if ('\\' == *pi->cur) {
381
+ read_escaped_str(pi, str);
382
+ return;
383
+ }
384
+
350
385
  if (0 == parent) { // simple add
351
386
  pi->add_cstr(pi, str, pi->cur - str, str);
352
387
  } else {
data/ext/oj/rails.c CHANGED
@@ -320,7 +320,6 @@ static void dump_time(VALUE obj, int depth, Out out, bool as_ok) {
320
320
  long long sec;
321
321
  long long nsec;
322
322
 
323
- #ifdef HAVE_RB_TIME_TIMESPEC
324
323
  if (16 <= sizeof(struct timespec)) {
325
324
  struct timespec ts = rb_time_timespec(obj);
326
325
 
@@ -330,10 +329,6 @@ static void dump_time(VALUE obj, int depth, Out out, bool as_ok) {
330
329
  sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
331
330
  nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
332
331
  }
333
- #else
334
- sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
335
- nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
336
- #endif
337
332
  dump_sec_nano(obj, sec, nsec, out);
338
333
  }
339
334
 
data/ext/oj/sparse.c CHANGED
@@ -953,7 +953,11 @@ CLEANUP:
953
953
  }
954
954
  stack_cleanup(&pi->stack);
955
955
  if (0 != fd) {
956
+ #ifdef _WIN32
957
+ rb_w32_close(fd);
958
+ #else
956
959
  close(fd);
960
+ #endif
957
961
  }
958
962
  if (err_has(&pi->err)) {
959
963
  rb_set_errinfo(Qnil);
data/ext/oj/wab.c CHANGED
@@ -194,7 +194,6 @@ static void dump_time(VALUE obj, Out out) {
194
194
  time_t sec;
195
195
  long long nsec;
196
196
 
197
- #ifdef HAVE_RB_TIME_TIMESPEC
198
197
  if (16 <= sizeof(struct timespec)) {
199
198
  struct timespec ts = rb_time_timespec(obj);
200
199
 
@@ -204,10 +203,6 @@ static void dump_time(VALUE obj, Out out) {
204
203
  sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
205
204
  nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
206
205
  }
207
- #else
208
- sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
209
- nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
210
- #endif
211
206
 
212
207
  assure_size(out, 36);
213
208
  // 2012-01-05T23:58:07.123456000Z
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.12'
4
+ VERSION = '3.13.15'
5
5
  end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ ORIG_ARGV = ARGV.dup
4
+
5
+ require "bundler/setup"
6
+ require "active_support/core_ext/kernel/reporting"
7
+
8
+ silence_warnings do
9
+ Encoding.default_internal = Encoding::UTF_8
10
+ Encoding.default_external = Encoding::UTF_8
11
+ end
12
+
13
+ require "active_support/testing/autorun"
14
+ require "active_support/testing/method_call_assertions"
15
+
16
+ ENV["NO_RELOAD"] = "1"
17
+ require "active_support"
18
+
19
+ Thread.abort_on_exception = true
20
+
21
+ # Show backtraces for deprecated behavior for quicker cleanup.
22
+ ActiveSupport::Deprecation.debug = true
23
+
24
+ # Default to old to_time behavior but allow running tests with new behavior
25
+ ActiveSupport.to_time_preserves_timezone = ENV["PRESERVE_TIMEZONES"] == "1"
26
+
27
+ # Disable available locale checks to avoid warnings running the test suite.
28
+ I18n.enforce_available_locales = false
29
+
30
+ class ActiveSupport::TestCase
31
+ if Process.respond_to?(:fork) && !Gem.win_platform?
32
+ parallelize
33
+ else
34
+ parallelize(with: :threads)
35
+ end
36
+
37
+ include ActiveSupport::Testing::MethodCallAssertions
38
+
39
+ private
40
+ # Skips the current run on Rubinius using Minitest::Assertions#skip
41
+ def rubinius_skip(message = "")
42
+ skip message if RUBY_ENGINE == "rbx"
43
+ end
44
+
45
+ # Skips the current run on JRuby using Minitest::Assertions#skip
46
+ def jruby_skip(message = "")
47
+ skip message if defined?(JRUBY_VERSION)
48
+ end
49
+ end