oj 3.13.13 → 3.13.16

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/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/parser.c CHANGED
@@ -533,6 +533,7 @@ static void calc_num(ojParser p) {
533
533
  // nothing to do
534
534
  break;
535
535
  }
536
+ p->type = OJ_NONE;
536
537
  }
537
538
 
538
539
  static void big_change(ojParser p) {
@@ -598,6 +599,8 @@ static void parse(ojParser p, const byte *json) {
598
599
  const byte *b = json;
599
600
  int i;
600
601
 
602
+ p->line = 1;
603
+ p->col = -1;
601
604
  #if DEBUG
602
605
  printf("*** parse - mode: %c %s\n", p->map[256], (const char *)json);
603
606
  #endif
@@ -652,6 +655,7 @@ static void parse(ojParser p, const byte *json) {
652
655
  }
653
656
  buf_append_string(&p->buf, (const char *)start, b - start);
654
657
  if ('"' == *b) {
658
+ p->cur = b - json;
655
659
  p->funcs[p->stack[p->depth]].add_str(p);
656
660
  p->map = (0 == p->depth) ? value_map : after_map;
657
661
  break;
@@ -661,12 +665,14 @@ static void parse(ojParser p, const byte *json) {
661
665
  p->next_map = (0 == p->depth) ? value_map : after_map;
662
666
  break;
663
667
  case OPEN_OBJECT:
668
+ p->cur = b - json;
664
669
  p->funcs[p->stack[p->depth]].open_object(p);
665
670
  p->depth++;
666
671
  p->stack[p->depth] = OBJECT_FUN;
667
672
  p->map = key1_map;
668
673
  break;
669
674
  case NUM_CLOSE_OBJECT:
675
+ p->cur = b - json;
670
676
  calc_num(p);
671
677
  // flow through
672
678
  case CLOSE_OBJECT:
@@ -677,15 +683,18 @@ static void parse(ojParser p, const byte *json) {
677
683
  return;
678
684
  }
679
685
  p->depth--;
686
+ p->cur = b - json;
680
687
  p->funcs[p->stack[p->depth]].close_object(p);
681
688
  break;
682
689
  case OPEN_ARRAY:
690
+ p->cur = b - json;
683
691
  p->funcs[p->stack[p->depth]].open_array(p);
684
692
  p->depth++;
685
693
  p->stack[p->depth] = ARRAY_FUN;
686
694
  p->map = value_map;
687
695
  break;
688
696
  case NUM_CLOSE_ARRAY:
697
+ p->cur = b - json;
689
698
  calc_num(p);
690
699
  // flow through
691
700
  case CLOSE_ARRAY:
@@ -696,9 +705,11 @@ static void parse(ojParser p, const byte *json) {
696
705
  return;
697
706
  }
698
707
  p->depth--;
708
+ p->cur = b - json;
699
709
  p->funcs[p->stack[p->depth]].close_array(p);
700
710
  break;
701
711
  case NUM_COMMA:
712
+ p->cur = b - json;
702
713
  calc_num(p);
703
714
  if (0 < p->depth && OBJECT_FUN == p->stack[p->depth]) {
704
715
  p->map = key_map;
@@ -860,8 +871,14 @@ static void parse(ojParser p, const byte *json) {
860
871
  b--;
861
872
  p->map = big_exp_map;
862
873
  break;
863
- case NUM_SPC: calc_num(p); break;
864
- case NUM_NEWLINE: calc_num(p); b++;
874
+ case NUM_SPC:
875
+ p->cur = b - json;
876
+ calc_num(p);
877
+ break;
878
+ case NUM_NEWLINE:
879
+ p->cur = b - json;
880
+ calc_num(p);
881
+ b++;
865
882
  #ifdef SPACE_JUMP
866
883
  // for (uint32_t *sj = (uint32_t*)b; 0x20202020 == *sj; sj++) { b += 4; }
867
884
  for (uint16_t *sj = (uint16_t *)b; 0x2020 == *sj; sj++) {
@@ -882,6 +899,7 @@ static void parse(ojParser p, const byte *json) {
882
899
  buf_append_string(&p->buf, (const char *)start, b - start);
883
900
  }
884
901
  if ('"' == *b) {
902
+ p->cur = b - json;
885
903
  p->funcs[p->stack[p->depth]].add_str(p);
886
904
  p->map = p->next_map;
887
905
  break;
@@ -890,6 +908,7 @@ static void parse(ojParser p, const byte *json) {
890
908
  break;
891
909
  case STR_SLASH: p->map = esc_map; break;
892
910
  case STR_QUOTE:
911
+ p->cur = b - json;
893
912
  p->funcs[p->stack[p->depth]].add_str(p);
894
913
  p->map = p->next_map;
895
914
  break;
@@ -967,6 +986,7 @@ static void parse(ojParser p, const byte *json) {
967
986
  case VAL_NULL:
968
987
  if ('u' == b[1] && 'l' == b[2] && 'l' == b[3]) {
969
988
  b += 3;
989
+ p->cur = b - json;
970
990
  p->funcs[p->stack[p->depth]].add_null(p);
971
991
  p->map = (0 == p->depth) ? value_map : after_map;
972
992
  break;
@@ -992,6 +1012,7 @@ static void parse(ojParser p, const byte *json) {
992
1012
  case VAL_TRUE:
993
1013
  if ('r' == b[1] && 'u' == b[2] && 'e' == b[3]) {
994
1014
  b += 3;
1015
+ p->cur = b - json;
995
1016
  p->funcs[p->stack[p->depth]].add_true(p);
996
1017
  p->map = (0 == p->depth) ? value_map : after_map;
997
1018
  break;
@@ -1017,6 +1038,7 @@ static void parse(ojParser p, const byte *json) {
1017
1038
  case VAL_FALSE:
1018
1039
  if ('a' == b[1] && 'l' == b[2] && 's' == b[3] && 'e' == b[4]) {
1019
1040
  b += 4;
1041
+ p->cur = b - json;
1020
1042
  p->funcs[p->stack[p->depth]].add_false(p);
1021
1043
  p->map = (0 == p->depth) ? value_map : after_map;
1022
1044
  break;
@@ -1050,6 +1072,7 @@ static void parse(ojParser p, const byte *json) {
1050
1072
  parse_error(p, "expected null");
1051
1073
  return;
1052
1074
  }
1075
+ p->cur = b - json;
1053
1076
  p->funcs[p->stack[p->depth]].add_null(p);
1054
1077
  p->map = (0 == p->depth) ? value_map : after_map;
1055
1078
  }
@@ -1061,6 +1084,7 @@ static void parse(ojParser p, const byte *json) {
1061
1084
  parse_error(p, "expected false");
1062
1085
  return;
1063
1086
  }
1087
+ p->cur = b - json;
1064
1088
  p->funcs[p->stack[p->depth]].add_false(p);
1065
1089
  p->map = (0 == p->depth) ? value_map : after_map;
1066
1090
  }
@@ -1072,6 +1096,7 @@ static void parse(ojParser p, const byte *json) {
1072
1096
  parse_error(p, "expected true");
1073
1097
  return;
1074
1098
  }
1099
+ p->cur = b - json;
1075
1100
  p->funcs[p->stack[p->depth]].add_true(p);
1076
1101
  p->map = (0 == p->depth) ? value_map : after_map;
1077
1102
  }
@@ -1099,7 +1124,10 @@ static void parse(ojParser p, const byte *json) {
1099
1124
  case 'D':
1100
1125
  case 'g':
1101
1126
  case 'B':
1102
- case 'Y': calc_num(p); break;
1127
+ case 'Y':
1128
+ p->cur = b - json;
1129
+ calc_num(p);
1130
+ break;
1103
1131
  }
1104
1132
  }
1105
1133
  return;
@@ -1456,7 +1484,7 @@ static VALUE saj_parser = Qundef;
1456
1484
  /* Document-method: saj
1457
1485
  * call-seq: saj
1458
1486
  *
1459
- * Returns the default saj parser. Note the default SAJ parser can not be used
1487
+ * Returns the default SAJ parser. Note the default SAJ parser can not be used
1460
1488
  * concurrently in more than one thread.
1461
1489
  */
1462
1490
  static VALUE parser_saj(VALUE self) {
data/ext/oj/parser.h CHANGED
@@ -80,6 +80,7 @@ typedef struct _ojParser {
80
80
 
81
81
  char token[8];
82
82
  long line;
83
+ long cur; // only set before call to a function
83
84
  long col;
84
85
  int ri;
85
86
  uint32_t ucode;
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