oj 3.13.7 → 3.13.11

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: 44e493d06f06095e80eb1af563739efca81076a8d3cfd89d02e537ada1f00a60
4
- data.tar.gz: 9502a2285781a49c8a2cec4937bb92c1b04a4c95e44b8f34fdd9a6295f0f69f4
3
+ metadata.gz: dcb5f80ad6384640d44889424c39f91ee2db778b17c91b9505b5b3b4c280abf1
4
+ data.tar.gz: 85b70200f48f46019ecf1020ca8e1b8ea604bca1161120b3747a8aeac2903682
5
5
  SHA512:
6
- metadata.gz: fa5e096b0ec018cc964c98e108967e766454d48bbfbd7a0ec55fc86aa2e4cac1d54f2b069613823d183df128ed836c95b2b3851793243985b531bbe41b045132
7
- data.tar.gz: 22a9ded2a0442a64f4ac91e3fc5b1d0be86ea6c53dd857039a92ef515a74b6e348b3587899df5e4a78550ec8e1c4c7c06986a0b8912ef90a419e6c8ac2f65450
6
+ metadata.gz: f96776be4f9431b160f1d9f588e8688fb7e0c4a431c58a10fa43a71f5a6f95781456287f40db5dfba03bb69350946ad36f246d0b59c196f9dc95218f51005f7a
7
+ data.tar.gz: e106b88134f86d82b9740f3e836ecb2aaa4af7ad643b96a4600eaa09392ba5f630c402101a6fb476823c41bc127b5c3d9625c6900a033cf6f9830ca01e57d459
data/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 3.13.11 - 2022-01-05
4
+
5
+ - Fixed write blocking failures on writes to a slow stream with larger writes.
6
+
7
+ ## 3.13.10 - 2021-12-12
8
+
9
+ - Fixed Oj::Doc re-entrant issue with each_child.
10
+ - Fixed each_child on empty Oj::Doc.
11
+
12
+ ## 3.13.9 - 2021-10-06
13
+
14
+ - Fix mimic JSON load so that it honors the `:symbolize_names` option.
15
+
16
+ ## 3.13.8 - 2021-09-27
17
+
18
+ - Fix `Oj::Doc` behaviour for inexisting path.
19
+ ```ruby
20
+ Oj::Doc.open('{"foo":1}') do |doc|
21
+ doc.fetch('/foo/bar') # used to give `1`, now gives `nil`
22
+ doc.exists?('/foo/bar') # used to give `true`, now gives `false`
23
+ end
24
+ ```
25
+
26
+ - Fix `Oj::Parser` handling of BigDecimal. `snprint()` does not handle `%Lg` correctly but `sprintf()` does.
27
+
3
28
  ## 3.13.7 - 2021-09-16
4
29
 
5
30
  - The JSON gem allows invalid unicode so Oj, when mimicing JSON now
data/README.md CHANGED
@@ -43,6 +43,15 @@ or in Bundler:
43
43
  gem 'oj'
44
44
  ```
45
45
 
46
+ ## Rails and json quickstart
47
+
48
+ See the Quickstart sections of the [Rails](pages/Rails.md) and [json](pages/JsonGem.md) docs.
49
+
50
+ ## multi_json
51
+
52
+ Code which uses [multi_json](https://github.com/intridea/multi_json)
53
+ will automatically prefer Oj if it is installed.
54
+
46
55
  ## Support
47
56
 
48
57
  [Get supported Oj with a Tidelift Subscription.](https://tidelift.com/subscription/pkg/rubygems-oj?utm_source=rubygems-oj&utm_medium=referral&utm_campaign=readme) Security updates are [supported](https://tidelift.com/security).
data/ext/oj/custom.c CHANGED
@@ -282,7 +282,7 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
282
282
  Out out = (Out)ov;
283
283
  int depth = out->depth;
284
284
 
285
- if (oj_dump_ignore(out->opts, value)) {
285
+ if (dump_ignore(out->opts, value)) {
286
286
  return ST_CONTINUE;
287
287
  }
288
288
  if (out->omit_nil && Qnil == value) {
@@ -577,7 +577,7 @@ static int dump_attr_cb(ID key, VALUE value, VALUE ov) {
577
577
  size_t size;
578
578
  const char *attr;
579
579
 
580
- if (oj_dump_ignore(out->opts, value)) {
580
+ if (dump_ignore(out->opts, value)) {
581
581
  return ST_CONTINUE;
582
582
  }
583
583
  if (out->omit_nil && Qnil == value) {
@@ -749,7 +749,7 @@ static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
749
749
  } else {
750
750
  fill_indent(out, d2);
751
751
  }
752
- oj_dump_custom_val(rb_ary_entry(a, i), d2, out, true);
752
+ oj_dump_custom_val(RARRAY_AREF(a, i), d2, out, true);
753
753
  if (i < cnt) {
754
754
  *out->cur++ = ',';
755
755
  }
@@ -833,7 +833,7 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
833
833
  v = rb_struct_aref(obj, INT2FIX(i));
834
834
  #endif
835
835
  if (ma != Qnil) {
836
- volatile VALUE s = rb_sym2str(rb_ary_entry(ma, i));
836
+ volatile VALUE s = rb_sym2str(RARRAY_AREF(ma, i));
837
837
 
838
838
  name = RSTRING_PTR(s);
839
839
  len = (int)RSTRING_LEN(s);
data/ext/oj/dump.c CHANGED
@@ -10,6 +10,9 @@
10
10
  #include <stdlib.h>
11
11
  #include <string.h>
12
12
  #include <unistd.h>
13
+ #if !IS_WINDOWS
14
+ #include <poll.h>
15
+ #endif
13
16
 
14
17
  #include "cache8.h"
15
18
  #include "odd.h"
@@ -113,49 +116,39 @@ static char rails_friendly_chars[256] = "\
113
116
  11111111111111111111111111111111";
114
117
 
115
118
  static void raise_strict(VALUE obj) {
116
- rb_raise(rb_eTypeError,
117
- "Failed to dump %s Object to JSON in strict mode.",
118
- rb_class2name(rb_obj_class(obj)));
119
+ rb_raise(rb_eTypeError, "Failed to dump %s Object to JSON in strict mode.", rb_class2name(rb_obj_class(obj)));
119
120
  }
120
121
 
121
- inline static size_t newline_friendly_size(const uint8_t *str, size_t len) {
122
+ inline static size_t calculate_string_size(const uint8_t *str, size_t len, const char *table) {
122
123
  size_t size = 0;
123
124
  size_t i = len;
124
125
 
125
- for (; 0 < i; str++, i--) {
126
- size += newline_friendly_chars[*str];
126
+ for (; 3 < i; i -= 4) {
127
+ size += table[*str++];
128
+ size += table[*str++];
129
+ size += table[*str++];
130
+ size += table[*str++];
131
+ }
132
+ for (; 0 < i; i--) {
133
+ size += table[*str++];
127
134
  }
128
135
  return size - len * (size_t)'0';
129
136
  }
130
137
 
131
- inline static size_t hibit_friendly_size(const uint8_t *str, size_t len) {
132
- size_t size = 0;
133
- size_t i = len;
138
+ inline static size_t newline_friendly_size(const uint8_t *str, size_t len) {
139
+ return calculate_string_size(str, len, newline_friendly_chars);
140
+ }
134
141
 
135
- for (; 0 < i; str++, i--) {
136
- size += hibit_friendly_chars[*str];
137
- }
138
- return size - len * (size_t)'0';
142
+ inline static size_t hibit_friendly_size(const uint8_t *str, size_t len) {
143
+ return calculate_string_size(str, len, hibit_friendly_chars);
139
144
  }
140
145
 
141
146
  inline static size_t ascii_friendly_size(const uint8_t *str, size_t len) {
142
- size_t size = 0;
143
- size_t i = len;
144
-
145
- for (; 0 < i; str++, i--) {
146
- size += ascii_friendly_chars[*str];
147
- }
148
- return size - len * (size_t)'0';
147
+ return calculate_string_size(str, len, ascii_friendly_chars);
149
148
  }
150
149
 
151
150
  inline static size_t xss_friendly_size(const uint8_t *str, size_t len) {
152
- size_t size = 0;
153
- size_t i = len;
154
-
155
- for (; 0 < i; str++, i--) {
156
- size += xss_friendly_chars[*str];
157
- }
158
- return size - len * (size_t)'0';
151
+ return calculate_string_size(str, len, xss_friendly_chars);
159
152
  }
160
153
 
161
154
  inline static size_t hixss_friendly_size(const uint8_t *str, size_t len) {
@@ -188,13 +181,7 @@ inline static long rails_xss_friendly_size(const uint8_t *str, size_t len) {
188
181
  }
189
182
 
190
183
  inline static size_t rails_friendly_size(const uint8_t *str, size_t len) {
191
- size_t size = 0;
192
- size_t i = len;
193
-
194
- for (; 0 < i; str++, i--) {
195
- size += rails_friendly_chars[*str];
196
- }
197
- return size - len * (size_t)'0';
184
+ return calculate_string_size(str, len, rails_friendly_chars);
198
185
  }
199
186
 
200
187
  const char *oj_nan_str(VALUE obj, int opt, int mode, bool plus, int *lenp) {
@@ -535,14 +522,7 @@ void oj_dump_xml_time(VALUE obj, Out out) {
535
522
  }
536
523
  if ((0 == nsec && !out->opts->sec_prec_set) || 0 == out->opts->sec_prec) {
537
524
  if (0 == tzsecs && rb_funcall2(obj, oj_utcq_id, 0, 0)) {
538
- int len = sprintf(buf,
539
- "%04d-%02d-%02dT%02d:%02d:%02dZ",
540
- ti.year,
541
- ti.mon,
542
- ti.day,
543
- ti.hour,
544
- ti.min,
545
- ti.sec);
525
+ int len = sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02dZ", ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec);
546
526
  oj_dump_cstr(buf, len, 0, 0, out);
547
527
  } else {
548
528
  int len = sprintf(buf,
@@ -574,18 +554,7 @@ void oj_dump_xml_time(VALUE obj, Out out) {
574
554
  if (9 > out->opts->sec_prec) {
575
555
  format[32] = '0' + out->opts->sec_prec;
576
556
  }
577
- len = sprintf(buf,
578
- format,
579
- ti.year,
580
- ti.mon,
581
- ti.day,
582
- ti.hour,
583
- ti.min,
584
- ti.sec,
585
- (long)nsec,
586
- tzsign,
587
- tzhour,
588
- tzmin);
557
+ len = sprintf(buf, format, ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, (long)nsec, tzsign, tzhour, tzmin);
589
558
  oj_dump_cstr(buf, len, 0, 0, out);
590
559
  }
591
560
  }
@@ -666,6 +635,21 @@ void oj_write_obj_to_file(VALUE obj, const char *path, Options copts) {
666
635
  }
667
636
  }
668
637
 
638
+ static void write_ready(int fd) {
639
+ struct pollfd pp;
640
+ int i;
641
+
642
+ pp.fd = fd;
643
+ pp.events = POLLERR | POLLOUT;
644
+ pp.revents = 0;
645
+ if (0 >= (i = poll(&pp, 1, 5000))) {
646
+ if (0 == i || EAGAIN == errno) {
647
+ rb_raise(rb_eIOError, "write timed out");
648
+ }
649
+ rb_raise(rb_eIOError, "write failed. %d %s.", errno, strerror(errno));
650
+ }
651
+ }
652
+
669
653
  void oj_write_obj_to_stream(VALUE obj, VALUE stream, Options copts) {
670
654
  char buf[4096];
671
655
  struct _out out;
@@ -685,13 +669,24 @@ void oj_write_obj_to_stream(VALUE obj, VALUE stream, Options copts) {
685
669
  if (oj_stringio_class == clas) {
686
670
  rb_funcall(stream, oj_write_id, 1, rb_str_new(out.buf, size));
687
671
  #if !IS_WINDOWS
688
- } else if (rb_respond_to(stream, oj_fileno_id) &&
689
- Qnil != (s = rb_funcall(stream, oj_fileno_id, 0)) && 0 != (fd = FIX2INT(s))) {
690
- if (size != write(fd, out.buf, size)) {
691
- if (out.allocated) {
692
- xfree(out.buf);
672
+ } else if (rb_respond_to(stream, oj_fileno_id) && Qnil != (s = rb_funcall(stream, oj_fileno_id, 0)) &&
673
+ 0 != (fd = FIX2INT(s))) {
674
+ ssize_t cnt;
675
+ ssize_t total = 0;
676
+
677
+ while (true) {
678
+ if (0 > (cnt = write(fd, out.buf + total, size - total))) {
679
+ if (EAGAIN != errno) {
680
+ rb_raise(rb_eIOError, "write failed. %d %s.", errno, strerror(errno));
681
+ break;
682
+ }
683
+ }
684
+ total += cnt;
685
+ if (size <= total) {
686
+ // Completed
687
+ break;
693
688
  }
694
- rb_raise(rb_eIOError, "Write failed. [%d:%s]", errno, strerror(errno));
689
+ write_ready(fd);
695
690
  }
696
691
  #endif
697
692
  } else if (rb_respond_to(stream, oj_write_id)) {
@@ -835,8 +830,7 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
835
830
  for (; str < end; str++) {
836
831
  switch (cmap[(uint8_t)*str]) {
837
832
  case '1':
838
- if ((JXEsc == out->opts->escape_mode || RailsXEsc == out->opts->escape_mode) &&
839
- check_start <= str) {
833
+ if ((JXEsc == out->opts->escape_mode || RailsXEsc == out->opts->escape_mode) && check_start <= str) {
840
834
  if (0 != (0x80 & (uint8_t)*str)) {
841
835
  if (0xC0 == (0xC0 & (uint8_t)*str)) {
842
836
  check_start = check_unicode(str, end, orig);
@@ -860,11 +854,9 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
860
854
  }
861
855
  break;
862
856
  case '3': // Unicode
863
- if (0xe2 == (uint8_t)*str &&
864
- (JXEsc == out->opts->escape_mode || RailsXEsc == out->opts->escape_mode) &&
857
+ if (0xe2 == (uint8_t)*str && (JXEsc == out->opts->escape_mode || RailsXEsc == out->opts->escape_mode) &&
865
858
  2 <= end - str) {
866
- if (0x80 == (uint8_t)str[1] &&
867
- (0xa8 == (uint8_t)str[2] || 0xa9 == (uint8_t)str[2])) {
859
+ if (0x80 == (uint8_t)str[1] && (0xa8 == (uint8_t)str[2] || 0xa9 == (uint8_t)str[2])) {
868
860
  str = dump_unicode(str, end, out, orig);
869
861
  } else {
870
862
  check_start = check_unicode(str, end, orig);
@@ -883,10 +875,8 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
883
875
  dump_hex((uint8_t)*str, out);
884
876
  } else {
885
877
  if (0xe2 == (uint8_t)*str &&
886
- (JXEsc == out->opts->escape_mode || RailsXEsc == out->opts->escape_mode) &&
887
- 2 <= end - str) {
888
- if (0x80 == (uint8_t)str[1] &&
889
- (0xa8 == (uint8_t)str[2] || 0xa9 == (uint8_t)str[2])) {
878
+ (JXEsc == out->opts->escape_mode || RailsXEsc == out->opts->escape_mode) && 2 <= end - str) {
879
+ if (0x80 == (uint8_t)str[1] && (0xa8 == (uint8_t)str[2] || 0xa9 == (uint8_t)str[2])) {
890
880
  str = dump_unicode(str, end, out, orig);
891
881
  } else {
892
882
  check_start = check_unicode(str, end, orig);
@@ -902,8 +892,8 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
902
892
  }
903
893
  *out->cur++ = '"';
904
894
  }
905
- if ((JXEsc == out->opts->escape_mode || RailsXEsc == out->opts->escape_mode) &&
906
- 0 < str - orig && 0 != (0x80 & *(str - 1))) {
895
+ if ((JXEsc == out->opts->escape_mode || RailsXEsc == out->opts->escape_mode) && 0 < str - orig &&
896
+ 0 != (0x80 & *(str - 1))) {
907
897
  uint8_t c = (uint8_t) * (str - 1);
908
898
  int i;
909
899
  int scnt = (int)(str - orig);
@@ -1064,8 +1054,7 @@ void oj_dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
1064
1054
  int cnt = (int)RSTRING_LEN(rs);
1065
1055
  bool dump_as_string = false;
1066
1056
 
1067
- if (out->opts->int_range_max != 0 ||
1068
- out->opts->int_range_min != 0) { // Bignum cannot be inside of Fixnum range
1057
+ if (out->opts->int_range_max != 0 || out->opts->int_range_min != 0) { // Bignum cannot be inside of Fixnum range
1069
1058
  dump_as_string = true;
1070
1059
  assure_size(out, cnt + 2);
1071
1060
  *out->cur++ = '"';
@@ -1225,17 +1214,3 @@ int oj_dump_float_printf(char *buf, size_t blen, VALUE obj, double d, const char
1225
1214
  }
1226
1215
  return cnt;
1227
1216
  }
1228
-
1229
- bool oj_dump_ignore(Options opts, VALUE obj) {
1230
- if (NULL != opts->ignore && (ObjectMode == opts->mode || CustomMode == opts->mode)) {
1231
- VALUE *vp = opts->ignore;
1232
- VALUE clas = rb_obj_class(obj);
1233
-
1234
- for (; Qnil != *vp; vp++) {
1235
- if (clas == *vp) {
1236
- return true;
1237
- }
1238
- }
1239
- }
1240
- return false;
1241
- }
data/ext/oj/dump.h CHANGED
@@ -50,7 +50,6 @@ extern VALUE oj_remove_to_json(int argc, VALUE *argv, VALUE self);
50
50
 
51
51
  extern int oj_dump_float_printf(char *buf, size_t blen, VALUE obj, double d, const char *format);
52
52
 
53
- extern bool oj_dump_ignore(Options opts, VALUE obj);
54
53
  extern time_t oj_sec_from_time_hard_way(VALUE obj);
55
54
 
56
55
  inline static void assure_size(Out out, size_t len) {
@@ -69,6 +68,20 @@ inline static void fill_indent(Out out, int cnt) {
69
68
  }
70
69
  }
71
70
 
71
+ inline static bool dump_ignore(Options opts, VALUE obj) {
72
+ if (NULL != opts->ignore && (ObjectMode == opts->mode || CustomMode == opts->mode)) {
73
+ VALUE *vp = opts->ignore;
74
+ VALUE clas = rb_obj_class(obj);
75
+
76
+ for (; Qnil != *vp; vp++) {
77
+ if (clas == *vp) {
78
+ return true;
79
+ }
80
+ }
81
+ }
82
+ return false;
83
+ }
84
+
72
85
  inline static void dump_ulong(unsigned long num, Out out) {
73
86
  char buf[32];
74
87
  char *b = buf + sizeof(buf) - 1;
data/ext/oj/dump_compat.c CHANGED
@@ -182,7 +182,7 @@ dump_array(VALUE a, int depth, Out out, bool as_ok) {
182
182
  } else {
183
183
  fill_indent(out, d2);
184
184
  }
185
- oj_dump_compat_val(rb_ary_entry(a, i), d2, out, true);
185
+ oj_dump_compat_val(RARRAY_AREF(a, i), d2, out, true);
186
186
  if (i < cnt) {
187
187
  *out->cur++ = ',';
188
188
  }
data/ext/oj/dump_object.c CHANGED
@@ -157,7 +157,7 @@ static void dump_array_class(VALUE a, VALUE clas, int depth, Out out) {
157
157
  } else {
158
158
  fill_indent(out, d2);
159
159
  }
160
- oj_dump_obj_val(rb_ary_entry(a, i), d2, out);
160
+ oj_dump_obj_val(RARRAY_AREF(a, i), d2, out);
161
161
  if (i < cnt) {
162
162
  *out->cur++ = ',';
163
163
  }
@@ -218,7 +218,7 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
218
218
  int depth = out->depth;
219
219
  long size = depth * out->indent + 1;
220
220
 
221
- if (oj_dump_ignore(out->opts, value)) {
221
+ if (dump_ignore(out->opts, value)) {
222
222
  return ST_CONTINUE;
223
223
  }
224
224
  if (out->omit_nil && Qnil == value) {
@@ -226,47 +226,54 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
226
226
  }
227
227
  assure_size(out, size);
228
228
  fill_indent(out, depth);
229
- if (rb_type(key) == T_STRING) {
229
+ switch (rb_type(key)) {
230
+ case T_STRING:
230
231
  dump_str_class(key, Qundef, depth, out);
231
232
  *out->cur++ = ':';
232
233
  oj_dump_obj_val(value, depth, out);
233
- } else if (rb_type(key) == T_SYMBOL) {
234
+ break;
235
+
236
+ case T_SYMBOL:
234
237
  dump_sym(key, 0, out, false);
235
238
  *out->cur++ = ':';
236
239
  oj_dump_obj_val(value, depth, out);
237
- } else {
238
- int d2 = depth + 1;
239
- long s2 = size + out->indent + 1;
240
- int i;
241
- int started = 0;
242
- uint8_t b;
240
+ break;
243
241
 
244
- assure_size(out, s2 + 15);
245
- *out->cur++ = '"';
246
- *out->cur++ = '^';
247
- *out->cur++ = '#';
248
- out->hash_cnt++;
249
- for (i = 28; 0 <= i; i -= 4) {
250
- b = (uint8_t)((out->hash_cnt >> i) & 0x0000000F);
251
- if ('\0' != b) {
252
- started = 1;
253
- }
254
- if (started) {
255
- *out->cur++ = hex_chars[b];
242
+ default:
243
+ {
244
+ int d2 = depth + 1;
245
+ long s2 = size + out->indent + 1;
246
+ int i;
247
+ int started = 0;
248
+ uint8_t b;
249
+
250
+ assure_size(out, s2 + 15);
251
+ *out->cur++ = '"';
252
+ *out->cur++ = '^';
253
+ *out->cur++ = '#';
254
+ out->hash_cnt++;
255
+ for (i = 28; 0 <= i; i -= 4) {
256
+ b = (uint8_t)((out->hash_cnt >> i) & 0x0000000F);
257
+ if ('\0' != b) {
258
+ started = 1;
259
+ }
260
+ if (started) {
261
+ *out->cur++ = hex_chars[b];
262
+ }
256
263
  }
264
+ *out->cur++ = '"';
265
+ *out->cur++ = ':';
266
+ *out->cur++ = '[';
267
+ fill_indent(out, d2);
268
+ oj_dump_obj_val(key, d2, out);
269
+ assure_size(out, s2);
270
+ *out->cur++ = ',';
271
+ fill_indent(out, d2);
272
+ oj_dump_obj_val(value, d2, out);
273
+ assure_size(out, size);
274
+ fill_indent(out, depth);
275
+ *out->cur++ = ']';
257
276
  }
258
- *out->cur++ = '"';
259
- *out->cur++ = ':';
260
- *out->cur++ = '[';
261
- fill_indent(out, d2);
262
- oj_dump_obj_val(key, d2, out);
263
- assure_size(out, s2);
264
- *out->cur++ = ',';
265
- fill_indent(out, d2);
266
- oj_dump_obj_val(value, d2, out);
267
- assure_size(out, size);
268
- fill_indent(out, depth);
269
- *out->cur++ = ']';
270
277
  }
271
278
  out->depth = depth;
272
279
  *out->cur++ = ',';
@@ -342,7 +349,7 @@ static int dump_attr_cb(ID key, VALUE value, VALUE ov) {
342
349
  size_t size = depth * out->indent + 1;
343
350
  const char *attr = rb_id2name(key);
344
351
 
345
- if (oj_dump_ignore(out->opts, value)) {
352
+ if (dump_ignore(out->opts, value)) {
346
353
  return ST_CONTINUE;
347
354
  }
348
355
  if (out->omit_nil && Qnil == value) {
@@ -605,7 +612,7 @@ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out)
605
612
  }
606
613
  value = rb_ivar_get(obj, vid);
607
614
 
608
- if (oj_dump_ignore(out->opts, value)) {
615
+ if (dump_ignore(out->opts, value)) {
609
616
  continue;
610
617
  }
611
618
  if (out->omit_nil && Qnil == value) {
@@ -694,7 +701,7 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
694
701
 
695
702
  *out->cur++ = '[';
696
703
  for (i = 0; i < cnt; i++) {
697
- volatile VALUE s = rb_sym2str(rb_ary_entry(ma, i));
704
+ volatile VALUE s = rb_sym2str(RARRAY_AREF(ma, i));
698
705
 
699
706
  name = RSTRING_PTR(s);
700
707
  len = (int)RSTRING_LEN(s);
@@ -730,7 +737,7 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
730
737
 
731
738
  for (i = 0; i < cnt; i++) {
732
739
  v = RSTRUCT_GET(obj, i);
733
- if (oj_dump_ignore(out->opts, v)) {
740
+ if (dump_ignore(out->opts, v)) {
734
741
  v = Qnil;
735
742
  }
736
743
  assure_size(out, size);
@@ -748,7 +755,7 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
748
755
  for (i = 0; i < slen; i++) {
749
756
  assure_size(out, size);
750
757
  fill_indent(out, d3);
751
- if (oj_dump_ignore(out->opts, v)) {
758
+ if (dump_ignore(out->opts, v)) {
752
759
  v = Qnil;
753
760
  }
754
761
  oj_dump_obj_val(rb_struct_aref(obj, INT2FIX(i)), d3, out, 0, 0, true);
data/ext/oj/dump_strict.c CHANGED
@@ -153,9 +153,9 @@ static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
153
153
  fill_indent(out, d2);
154
154
  }
155
155
  if (NullMode == out->opts->mode) {
156
- oj_dump_null_val(rb_ary_entry(a, i), d2, out);
156
+ oj_dump_null_val(RARRAY_AREF(a, i), d2, out);
157
157
  } else {
158
- oj_dump_strict_val(rb_ary_entry(a, i), d2, out);
158
+ oj_dump_strict_val(RARRAY_AREF(a, i), d2, out);
159
159
  }
160
160
  if (i < cnt) {
161
161
  *out->cur++ = ',';
data/ext/oj/encoder.c ADDED
@@ -0,0 +1,43 @@
1
+ // Copyright (c) 2011, 2022 Peter Ohler. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file in the project root for license details.
3
+
4
+ #include "oj.h"
5
+
6
+ typedef struct _encoder {
7
+ int indent; // indention for dump, default 2
8
+ char circular; // YesNo
9
+ char escape_mode; // Escape_Mode
10
+ char mode; // Mode
11
+ char time_format; // TimeFormat
12
+ char bigdec_as_num; // YesNo
13
+ char to_hash; // YesNo
14
+ char to_json; // YesNo
15
+ char as_json; // YesNo
16
+ char raw_json; // YesNo
17
+ char trace; // YesNo
18
+ char sec_prec_set; // boolean (0 or 1)
19
+ char ignore_under; // YesNo - ignore attrs starting with _ if true in object and custom modes
20
+ int64_t int_range_min; // dump numbers below as string
21
+ int64_t int_range_max; // dump numbers above as string
22
+ const char* create_id; // 0 or string
23
+ size_t create_id_len; // length of create_id
24
+ int sec_prec; // second precision when dumping time
25
+ char float_prec; // float precision, linked to float_fmt
26
+ char float_fmt[7]; // float format for dumping, if empty use Ruby
27
+ struct _dumpOpts dump_opts;
28
+ struct _rxClass str_rx;
29
+ VALUE* ignore; // Qnil terminated array of classes or NULL
30
+ } * Encoder;
31
+
32
+ /*
33
+ rb_define_module_function(Oj, "encode", encode, -1);
34
+ rb_define_module_function(Oj, "to_file", to_file, -1); // or maybe just write
35
+ rb_define_module_function(Oj, "to_stream", to_stream, -1);
36
+ */
37
+
38
+ // write(to, obj)
39
+ // if to is a string then open file
40
+ // else if stream then write to stream
41
+ // handle non-blocking
42
+
43
+ // should each mode have a different encoder or use delegates like the parser?
data/ext/oj/fast.c CHANGED
@@ -771,7 +771,7 @@ static VALUE parse_json(VALUE clas, char *json, bool given, bool allocated) {
771
771
  pi.doc = doc;
772
772
  #if IS_WINDOWS
773
773
  // assume a 1M stack and give half to ruby
774
- pi.stack_min = (void*)((char*)&pi - (512 * 1024));
774
+ pi.stack_min = (void *)((char *)&pi - (512 * 1024));
775
775
  #else
776
776
  {
777
777
  struct rlimit lim;
@@ -879,6 +879,10 @@ static Leaf get_leaf(Leaf *stack, Leaf *lp, const char *path) {
879
879
  }
880
880
  } else if (NULL == leaf->elements) {
881
881
  leaf = NULL;
882
+ } else if (STR_VAL == leaf->value_type || RUBY_VAL == leaf->value_type) {
883
+ // We are trying to get a children of a leaf, which
884
+ // doesn't exist.
885
+ leaf = NULL;
882
886
  } else if (COL_VAL == leaf->value_type) {
883
887
  Leaf first = leaf->elements->next;
884
888
  Leaf e = first;
@@ -1373,8 +1377,8 @@ static VALUE doc_fetch(int argc, VALUE *argv, VALUE self) {
1373
1377
  * Returns true if the value at the location identified by the path exists.
1374
1378
  * @param [String] path path to the location
1375
1379
  * @example
1376
- * Oj::Doc.open('[1,2]') { |doc| doc.exists('/1') } #=> true
1377
- * Oj::Doc.open('[1,2]') { |doc| doc.exists('/3') } #=> false
1380
+ * Oj::Doc.open('[1,2]') { |doc| doc.exists?('/1') } #=> true
1381
+ * Oj::Doc.open('[1,2]') { |doc| doc.exists?('/3') } #=> false
1378
1382
  */
1379
1383
  static VALUE doc_exists(VALUE self, VALUE str) {
1380
1384
  Doc doc;
@@ -1488,6 +1492,7 @@ static VALUE doc_each_child(int argc, VALUE *argv, VALUE self) {
1488
1492
  Doc doc = self_doc(self);
1489
1493
  const char *path = 0;
1490
1494
  size_t wlen;
1495
+ Leaf * where_orig = doc->where;
1491
1496
 
1492
1497
  wlen = doc->where - doc->where_path;
1493
1498
  if (0 < wlen) {
@@ -1504,9 +1509,13 @@ static VALUE doc_each_child(int argc, VALUE *argv, VALUE self) {
1504
1509
  if (0 < wlen) {
1505
1510
  memcpy(doc->where_path, save_path, sizeof(Leaf) * (wlen + 1));
1506
1511
  }
1512
+ doc->where = where_orig;
1507
1513
  return Qnil;
1508
1514
  }
1509
1515
  }
1516
+ if (NULL == doc->where || NULL == *doc->where) {
1517
+ return Qnil;
1518
+ }
1510
1519
  if (COL_VAL == (*doc->where)->value_type && 0 != (*doc->where)->elements) {
1511
1520
  Leaf first = (*doc->where)->elements->next;
1512
1521
  Leaf e = first;
@@ -1521,6 +1530,7 @@ static VALUE doc_each_child(int argc, VALUE *argv, VALUE self) {
1521
1530
  if (0 < wlen) {
1522
1531
  memcpy(doc->where_path, save_path, sizeof(Leaf) * (wlen + 1));
1523
1532
  }
1533
+ doc->where = where_orig;
1524
1534
  }
1525
1535
  return Qnil;
1526
1536
  }