oj 3.7.12 → 3.9.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 596316b0a9a9e4fa7a82486f0589182f15a1c0c679d2d58f50357a291720cbfa
4
- data.tar.gz: 3d58bd1344943d671222f1a7412c77731ecce70ddd3469a03ad15263374c243e
3
+ metadata.gz: bda4706ea9e50aef4bdfcd1c9708566b573da4e4c9f000ddf12f3e403a821c88
4
+ data.tar.gz: 56dbfecea94b2c0e43aa4193aed7749e30d55e4c288770a193aac3c57850bea2
5
5
  SHA512:
6
- metadata.gz: 4273557f2d93c634e3a9ffc789a503f80ee5ca80a8031c1406a63a3e926648dd15294faa8820d6f6c63a625b9be4a34dd36bbde954ba8f68fe418f7182a84f55
7
- data.tar.gz: ad6468ca75db3d8ebc792fcabbf417490c2cfe2927ab4859ef1c059fe36b8bad1c311fa03608a878350dd8324d3ab75887728a6ec4af1ffb1ea8739027642c69
6
+ metadata.gz: 73176c366166bb1b6fbe0a20501db677679ef7af8aaab547b9dadbba5856370d844f3595b06208a05c9efd9437d6f167298a0c73ef41fed905017a9aa5b2f764
7
+ data.tar.gz: 3c4731da851590f39cc71bd2cce9fb9e1e987ec22b54e2bfc948f8004d78dcb0b2bde464b784500958352f8dec045ba8e2ce3804769426821c7c03a11d95ce07
data/README.md CHANGED
@@ -65,7 +65,7 @@ See [{file:CHANGELOG.md}](CHANGELOG.md)
65
65
 
66
66
  ## Links
67
67
 
68
- - *Documentation*: http://www.ohler.com/oj/doc, http://rubydoc.info/gems/oj
68
+ - *Documentation*: http://www.ohler.com/oj/doc, http://rubydoc.info/gems/oj
69
69
 
70
70
  - *GitHub* *repo*: https://github.com/ohler55/oj
71
71
 
@@ -93,4 +93,12 @@ Follow [@peterohler on Twitter](http://twitter.com/peterohler) for announcements
93
93
 
94
94
  - *OjC, a C JSON parser*: https://www.ohler.com/ojc also at https://github.com/ohler55/ojc
95
95
 
96
- - *Piper Push Cache, push JSON to browsers*: http://www.piperpushcache.com
96
+ - *Agoo, a high performance Ruby web server supporting GraphQL on GitHub*: https://github.com/ohler55/agoo
97
+
98
+ - *Agoo-C, a high performance C web server supporting GraphQL on GitHub*: https://github.com/ohler55/agoo-c
99
+
100
+ #### Contributing
101
+
102
+ + Provide a Pull Request off the `develop` branch.
103
+ + Report a bug
104
+ + Suggest an idea
@@ -32,6 +32,13 @@ dump_obj_str(VALUE obj, int depth, Out out) {
32
32
  oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
33
33
  }
34
34
 
35
+ static void
36
+ dump_obj_as_str(VALUE obj, int depth, Out out) {
37
+ volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
38
+ const char *str = rb_string_value_ptr((VALUE*)&rstr);
39
+
40
+ oj_dump_cstr(str, RSTRING_LEN(rstr), 0, 0, out);
41
+ }
35
42
 
36
43
  static void
37
44
  bigdecimal_dump(VALUE obj, int depth, Out out) {
@@ -57,19 +64,23 @@ static ID imag_id = 0;
57
64
 
58
65
  static void
59
66
  complex_dump(VALUE obj, int depth, Out out) {
60
- struct _attr attrs[] = {
61
- { "real", 4, Qnil },
62
- { "imag", 4, Qnil },
63
- { NULL, 0, Qnil },
64
- };
65
- if (0 == real_id) {
66
- real_id = rb_intern("real");
67
- imag_id = rb_intern("imag");
68
- }
69
- attrs[0].value = rb_funcall(obj, real_id, 0);
70
- attrs[1].value = rb_funcall(obj, imag_id, 0);
67
+ if (NULL != out->opts->create_id) {
68
+ struct _attr attrs[] = {
69
+ { "real", 4, Qnil },
70
+ { "imag", 4, Qnil },
71
+ { NULL, 0, Qnil },
72
+ };
73
+ if (0 == real_id) {
74
+ real_id = rb_intern("real");
75
+ imag_id = rb_intern("imag");
76
+ }
77
+ attrs[0].value = rb_funcall(obj, real_id, 0);
78
+ attrs[1].value = rb_funcall(obj, imag_id, 0);
71
79
 
72
- oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
80
+ oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
81
+ } else {
82
+ dump_obj_as_str(obj, depth, out);
83
+ }
73
84
  }
74
85
 
75
86
  static VALUE
@@ -115,7 +126,7 @@ date_dump(VALUE obj, int depth, Out out) {
115
126
  } else {
116
127
  volatile VALUE v;
117
128
  volatile VALUE ov;
118
-
129
+
119
130
  switch (out->opts->time_format) {
120
131
  case RubyTime:
121
132
  case XmlTime:
@@ -150,7 +161,7 @@ date_dump(VALUE obj, int depth, Out out) {
150
161
  static VALUE
151
162
  date_load(VALUE clas, VALUE args) {
152
163
  volatile VALUE v;
153
-
164
+
154
165
  if (Qnil != (v = rb_hash_aref(args, rb_str_new2("s")))) {
155
166
  return rb_funcall(oj_date_class, rb_intern("parse"), 1, v);
156
167
  }
@@ -160,7 +171,7 @@ date_load(VALUE clas, VALUE args) {
160
171
  static VALUE
161
172
  datetime_load(VALUE clas, VALUE args) {
162
173
  volatile VALUE v;
163
-
174
+
164
175
  if (Qnil != (v = rb_hash_aref(args, rb_str_new2("s")))) {
165
176
  return rb_funcall(oj_datetime_class, rb_intern("parse"), 1, v);
166
177
  }
@@ -193,23 +204,27 @@ openstruct_load(VALUE clas, VALUE args) {
193
204
 
194
205
  static void
195
206
  range_dump(VALUE obj, int depth, Out out) {
196
- struct _attr attrs[] = {
197
- { "begin", 5, Qnil },
198
- { "end", 3, Qnil },
199
- { "exclude", 7, Qnil },
200
- { NULL, 0, Qnil },
201
- };
202
- attrs[0].value = rb_funcall(obj, oj_begin_id, 0);
203
- attrs[1].value = rb_funcall(obj, oj_end_id, 0);
204
- attrs[2].value = rb_funcall(obj, oj_exclude_end_id, 0);
207
+ if (NULL != out->opts->create_id) {
208
+ struct _attr attrs[] = {
209
+ { "begin", 5, Qnil },
210
+ { "end", 3, Qnil },
211
+ { "exclude", 7, Qnil },
212
+ { NULL, 0, Qnil },
213
+ };
214
+ attrs[0].value = rb_funcall(obj, oj_begin_id, 0);
215
+ attrs[1].value = rb_funcall(obj, oj_end_id, 0);
216
+ attrs[2].value = rb_funcall(obj, oj_exclude_end_id, 0);
205
217
 
206
- oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
218
+ oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
219
+ } else {
220
+ dump_obj_as_str(obj, depth, out);
221
+ }
207
222
  }
208
223
 
209
224
  static VALUE
210
225
  range_load(VALUE clas, VALUE args) {
211
226
  VALUE nargs[3];
212
-
227
+
213
228
  nargs[0] = rb_hash_aref(args, rb_id2str(oj_begin_id));
214
229
  nargs[1] = rb_hash_aref(args, rb_id2str(oj_end_id));
215
230
  nargs[2] = rb_hash_aref(args, rb_id2str(oj_exclude_end_id));
@@ -222,19 +237,23 @@ static ID denominator_id = 0;
222
237
 
223
238
  static void
224
239
  rational_dump(VALUE obj, int depth, Out out) {
225
- struct _attr attrs[] = {
226
- { "numerator", 9, Qnil },
227
- { "denominator", 11, Qnil },
228
- { NULL, 0, Qnil },
229
- };
230
- if (0 == numerator_id) {
231
- numerator_id = rb_intern("numerator");
232
- denominator_id = rb_intern("denominator");
233
- }
234
- attrs[0].value = rb_funcall(obj, numerator_id, 0);
235
- attrs[1].value = rb_funcall(obj, denominator_id, 0);
240
+ if (NULL != out->opts->create_id) {
241
+ struct _attr attrs[] = {
242
+ { "numerator", 9, Qnil },
243
+ { "denominator", 11, Qnil },
244
+ { NULL, 0, Qnil },
245
+ };
246
+ if (0 == numerator_id) {
247
+ numerator_id = rb_intern("numerator");
248
+ denominator_id = rb_intern("denominator");
249
+ }
250
+ attrs[0].value = rb_funcall(obj, numerator_id, 0);
251
+ attrs[1].value = rb_funcall(obj, denominator_id, 0);
236
252
 
237
- oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
253
+ oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
254
+ } else {
255
+ dump_obj_as_str(obj, depth, out);
256
+ }
238
257
  }
239
258
 
240
259
  static VALUE
@@ -250,7 +269,7 @@ rational_load(VALUE clas, VALUE args) {
250
269
  static VALUE
251
270
  regexp_load(VALUE clas, VALUE args) {
252
271
  volatile VALUE v;
253
-
272
+
254
273
  if (Qnil != (v = rb_hash_aref(args, rb_str_new2("s")))) {
255
274
  return rb_funcall(rb_cRegexp, oj_new_id, 1, v);
256
275
  }
@@ -423,7 +442,7 @@ dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
423
442
  v = rb_funcall(obj, *odd->attrs, 0);
424
443
  if (Qundef == v || T_STRING != rb_type(v)) {
425
444
  rb_raise(rb_eEncodingError, "Invalid type for raw JSON.\n");
426
- } else {
445
+ } else {
427
446
  const char *s = rb_string_value_ptr((VALUE*)&v);
428
447
  int len = (int)RSTRING_LEN(v);
429
448
  const char *name = rb_id2name(*odd->attrs);
@@ -459,7 +478,7 @@ dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
459
478
  char *n;
460
479
  char *end;
461
480
  ID i;
462
-
481
+
463
482
  if (sizeof(nbuf) <= nlen) {
464
483
  if (NULL == (n2 = strdup(name))) {
465
484
  rb_raise(rb_eNoMemError, "for attribute name.");
@@ -497,7 +516,10 @@ dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
497
516
  // Return class if still needs dumping.
498
517
  static VALUE
499
518
  dump_common(VALUE obj, int depth, Out out) {
500
- if (Yes == out->opts->to_json && rb_respond_to(obj, oj_to_json_id)) {
519
+
520
+ if (Yes == out->opts->raw_json && rb_respond_to(obj, oj_raw_json_id)) {
521
+ oj_dump_raw_json(obj, depth, out);
522
+ } else if (Yes == out->opts->to_json && rb_respond_to(obj, oj_to_json_id)) {
501
523
  volatile VALUE rs;
502
524
  const char *s;
503
525
  int len;
@@ -608,7 +630,7 @@ dump_attr_cb(ID key, VALUE value, Out out) {
608
630
  oj_dump_custom_val(value, depth, out, true);
609
631
  out->depth = depth;
610
632
  *out->cur++ = ',';
611
-
633
+
612
634
  return ST_CONTINUE;
613
635
  }
614
636
 
@@ -780,7 +802,7 @@ static void
780
802
  dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
781
803
  long id = oj_check_circular(obj, out);
782
804
  VALUE clas;
783
-
805
+
784
806
  if (0 > id) {
785
807
  oj_dump_nil(Qnil, depth, out, false);
786
808
  } else if (Qnil != (clas = dump_common(obj, depth, out))) {
@@ -793,7 +815,7 @@ dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
793
815
  size_t size = d2 * out->indent + d3 * out->indent + 3;
794
816
  const char *name;
795
817
  int cnt;
796
- size_t len;
818
+ size_t len;
797
819
 
798
820
  assure_size(out, size);
799
821
  if (clas == rb_cRange) {
@@ -871,7 +893,11 @@ dump_data(VALUE obj, int depth, Out out, bool as_ok) {
871
893
 
872
894
  static void
873
895
  dump_regexp(VALUE obj, int depth, Out out, bool as_ok) {
874
- dump_obj_str(obj, depth, out);
896
+ if (NULL != out->opts->create_id) {
897
+ dump_obj_str(obj, depth, out);
898
+ } else {
899
+ dump_obj_as_str(obj, depth, out);
900
+ }
875
901
  }
876
902
 
877
903
  static void
@@ -1113,7 +1139,7 @@ static void
1113
1139
  array_append_num(ParseInfo pi, NumInfo ni) {
1114
1140
  Val parent = stack_peek(&pi->stack);
1115
1141
  volatile VALUE rval = oj_num_as_value(ni);
1116
-
1142
+
1117
1143
  rb_ary_push(parent->val, rval);
1118
1144
  if (Yes == pi->options.trace) {
1119
1145
  oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
@@ -15,6 +15,7 @@
15
15
  #include "cache8.h"
16
16
  #include "dump.h"
17
17
  #include "odd.h"
18
+ #include "trace.h"
18
19
  #include "util.h"
19
20
 
20
21
  // Workaround in case INFINITY is not defined in math.h or if the OS is CentOS
@@ -166,7 +167,7 @@ hixss_friendly_size(const uint8_t *str, size_t len) {
166
167
  size_t size = 0;
167
168
  size_t i = len;
168
169
  bool check = false;
169
-
170
+
170
171
  for (; 0 < i; str++, i--) {
171
172
  size += hixss_friendly_chars[*str];
172
173
  if (0 != (0x80 & *str)) {
@@ -201,7 +202,7 @@ rails_friendly_size(const uint8_t *str, size_t len) {
201
202
  const char*
202
203
  oj_nan_str(VALUE obj, int opt, int mode, bool plus, int *lenp) {
203
204
  const char *str = NULL;
204
-
205
+
205
206
  if (AutoNan == opt) {
206
207
  switch (mode) {
207
208
  case CompatMode: opt = WordNan; break;
@@ -323,7 +324,7 @@ dump_unicode(const char *str, const char *end, Out out, const char *orig) {
323
324
  *out->cur++ = 'u';
324
325
  for (i = 3; 0 <= i; i--) {
325
326
  *out->cur++ = hex_chars[(uint8_t)(code >> (i * 4)) & 0x0F];
326
- }
327
+ }
327
328
  return str - 1;
328
329
  }
329
330
 
@@ -331,7 +332,7 @@ static const char*
331
332
  check_unicode(const char *str, const char *end, const char *orig) {
332
333
  uint8_t b = *(uint8_t*)str;
333
334
  int cnt = 0;
334
-
335
+
335
336
  if (0xC0 == (0xE0 & b)) {
336
337
  cnt = 1;
337
338
  } else if (0xE0 == (0xF0 & b)) {
@@ -411,7 +412,7 @@ oj_dump_time(VALUE obj, Out out, int withZone) {
411
412
  sec = rb_num2ll(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
412
413
  nsec = rb_num2ll(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
413
414
  #endif
414
-
415
+
415
416
  *b-- = '\0';
416
417
  if (withZone) {
417
418
  long tzsecs = NUM2LONG(rb_funcall2(obj, oj_utc_offset_id, 0, 0));
@@ -740,6 +741,30 @@ debug_raise(const char *orig, size_t cnt, int line) {
740
741
  rb_raise(oj_json_generator_error_class, "Partial character in string. %s @ %d", buf, line);
741
742
  }
742
743
 
744
+ void
745
+ oj_dump_raw_json(VALUE obj, int depth, Out out) {
746
+ if (oj_string_writer_class == rb_obj_class(obj)) {
747
+ StrWriter sw = (StrWriter)DATA_PTR(obj);
748
+ size_t len = sw->out.cur - sw->out.buf;
749
+
750
+ if (0 < len) {
751
+ len--;
752
+ }
753
+ oj_dump_raw(sw->out.buf, len, out);
754
+ } else {
755
+ volatile VALUE jv;
756
+
757
+ if (Yes == out->opts->trace) {
758
+ oj_trace("raw_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyIn);
759
+ }
760
+ jv = rb_funcall(obj, oj_raw_json_id, 2, RB_INT2NUM(depth), RB_INT2NUM(out->indent));
761
+ if (Yes == out->opts->trace) {
762
+ oj_trace("raw_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyOut);
763
+ }
764
+ oj_dump_raw(rb_string_value_ptr((VALUE*)&jv), (size_t)RSTRING_LEN(jv), out);
765
+ }
766
+ }
767
+
743
768
  void
744
769
  oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out out) {
745
770
  size_t size;
@@ -801,7 +826,7 @@ oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out out) {
801
826
  } else {
802
827
  const char *end = str + cnt;
803
828
  const char *check_start = str;
804
-
829
+
805
830
  if (is_sym) {
806
831
  *out->cur++ = ':';
807
832
  }
@@ -867,13 +892,13 @@ oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out out) {
867
892
  break; // ignore, should never happen if the table is correct
868
893
  }
869
894
  }
870
- *out->cur++ = '"';
895
+ *out->cur++ = '"';
871
896
  }
872
897
  if ((JXEsc == out->opts->escape_mode || RailsXEsc == out->opts->escape_mode) && 0 < str - orig && 0 != (0x80 & *(str - 1))) {
873
898
  uint8_t c = (uint8_t)*(str - 1);
874
899
  int i;
875
900
  int scnt = (int)(str - orig);
876
-
901
+
877
902
  // Last utf-8 characters must be 0x10xxxxxx. The start must be
878
903
  // 0x110xxxxx for 2 characters, 0x1110xxxx for 3, and 0x11110xxx for
879
904
  // 4.
@@ -939,7 +964,7 @@ oj_grow_out(Out out, size_t len) {
939
964
  size_t size = out->end - out->buf;
940
965
  long pos = out->cur - out->buf;
941
966
  char *buf = out->buf;
942
-
967
+
943
968
  size *= 2;
944
969
  if (size <= len * 2 + pos) {
945
970
  size += len;
@@ -996,24 +1021,21 @@ oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
996
1021
  char *b = buf + sizeof(buf) - 1;
997
1022
  long long num = rb_num2ll(obj);
998
1023
  int neg = 0;
999
- bool dump_as_string = false;
1024
+ bool dump_as_string = false;
1000
1025
 
1001
- if (out->opts->integer_range_max != 0 && out->opts->integer_range_min != 0 &&
1002
- (out->opts->integer_range_max < num || out->opts->integer_range_min > num)) {
1026
+ if (out->opts->integer_range_max != 0 && out->opts->integer_range_min != 0 &&
1027
+ (out->opts->integer_range_max < num || out->opts->integer_range_min > num)) {
1003
1028
  dump_as_string = true;
1004
- }
1005
-
1029
+ }
1006
1030
  if (0 > num) {
1007
1031
  neg = 1;
1008
1032
  num = -num;
1009
1033
  }
1010
-
1011
1034
  *b-- = '\0';
1012
1035
 
1013
- if (dump_as_string) {
1036
+ if (dump_as_string) {
1014
1037
  *b-- = '"';
1015
- }
1016
-
1038
+ }
1017
1039
  if (0 < num) {
1018
1040
  for (; 0 < num; num /= 10, b--) {
1019
1041
  *b = (num % 10) + '0';
@@ -1026,11 +1048,9 @@ oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
1026
1048
  } else {
1027
1049
  *b = '0';
1028
1050
  }
1029
-
1030
- if (dump_as_string) {
1051
+ if (dump_as_string) {
1031
1052
  *--b = '"';
1032
- }
1033
-
1053
+ }
1034
1054
  assure_size(out, (sizeof(buf) - (b - buf)));
1035
1055
  for (; '\0' != *b; b++) {
1036
1056
  *out->cur++ = *b;
@@ -1045,7 +1065,7 @@ oj_dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
1045
1065
  bool dump_as_string = false;
1046
1066
 
1047
1067
  if (out->opts->integer_range_max != 0 || out->opts->integer_range_min != 0) { // Bignum cannot be inside of Fixnum range
1048
- dump_as_string = true;
1068
+ dump_as_string = true;
1049
1069
  assure_size(out, cnt + 2);
1050
1070
  *out->cur++ = '"';
1051
1071
  } else {
@@ -1083,7 +1103,7 @@ oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
1083
1103
  cnt = sizeof(inf_val) - 1;
1084
1104
  } else {
1085
1105
  NanDump nd = out->opts->dump_opts.nan_dump;
1086
-
1106
+
1087
1107
  if (AutoNan == nd) {
1088
1108
  switch (out->opts->mode) {
1089
1109
  case CompatMode: nd = WordNan; break;
@@ -1118,7 +1138,7 @@ oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
1118
1138
  cnt = sizeof(ninf_val) - 1;
1119
1139
  } else {
1120
1140
  NanDump nd = out->opts->dump_opts.nan_dump;
1121
-
1141
+
1122
1142
  if (AutoNan == nd) {
1123
1143
  switch (out->opts->mode) {
1124
1144
  case CompatMode: nd = WordNan; break;
@@ -1152,7 +1172,7 @@ oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
1152
1172
  cnt = sizeof(ninf_val) - 1;
1153
1173
  } else {
1154
1174
  NanDump nd = out->opts->dump_opts.nan_dump;
1155
-
1175
+
1156
1176
  if (AutoNan == nd) {
1157
1177
  switch (out->opts->mode) {
1158
1178
  case ObjectMode: nd = HugeNan; break;