oj 3.13.9 → 3.16.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (161) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +101 -0
  3. data/README.md +13 -2
  4. data/ext/oj/buf.h +11 -6
  5. data/ext/oj/cache.c +25 -24
  6. data/ext/oj/cache8.c +10 -9
  7. data/ext/oj/circarray.c +8 -6
  8. data/ext/oj/circarray.h +2 -2
  9. data/ext/oj/code.c +19 -33
  10. data/ext/oj/code.h +2 -2
  11. data/ext/oj/compat.c +20 -60
  12. data/ext/oj/custom.c +76 -155
  13. data/ext/oj/debug.c +3 -9
  14. data/ext/oj/dump.c +203 -213
  15. data/ext/oj/dump.h +26 -12
  16. data/ext/oj/dump_compat.c +565 -642
  17. data/ext/oj/dump_leaf.c +17 -63
  18. data/ext/oj/dump_object.c +59 -181
  19. data/ext/oj/dump_strict.c +24 -48
  20. data/ext/oj/encoder.c +43 -0
  21. data/ext/oj/err.c +2 -13
  22. data/ext/oj/err.h +9 -12
  23. data/ext/oj/extconf.rb +18 -7
  24. data/ext/oj/fast.c +83 -108
  25. data/ext/oj/intern.c +52 -50
  26. data/ext/oj/intern.h +4 -8
  27. data/ext/oj/mem.c +318 -0
  28. data/ext/oj/mem.h +53 -0
  29. data/ext/oj/mimic_json.c +104 -81
  30. data/ext/oj/object.c +50 -67
  31. data/ext/oj/odd.c +89 -67
  32. data/ext/oj/odd.h +15 -15
  33. data/ext/oj/oj.c +171 -106
  34. data/ext/oj/oj.h +96 -74
  35. data/ext/oj/parse.c +169 -189
  36. data/ext/oj/parse.h +23 -24
  37. data/ext/oj/parser.c +89 -34
  38. data/ext/oj/parser.h +20 -9
  39. data/ext/oj/rails.c +86 -151
  40. data/ext/oj/rails.h +1 -1
  41. data/ext/oj/reader.c +12 -15
  42. data/ext/oj/reader.h +4 -2
  43. data/ext/oj/resolve.c +3 -4
  44. data/ext/oj/rxclass.c +6 -5
  45. data/ext/oj/rxclass.h +1 -1
  46. data/ext/oj/saj.c +21 -32
  47. data/ext/oj/saj2.c +329 -93
  48. data/ext/oj/saj2.h +23 -0
  49. data/ext/oj/scp.c +3 -14
  50. data/ext/oj/sparse.c +26 -70
  51. data/ext/oj/stream_writer.c +12 -22
  52. data/ext/oj/strict.c +20 -52
  53. data/ext/oj/string_writer.c +21 -22
  54. data/ext/oj/trace.h +31 -4
  55. data/ext/oj/usual.c +105 -150
  56. data/ext/oj/usual.h +68 -0
  57. data/ext/oj/util.h +1 -1
  58. data/ext/oj/val_stack.c +1 -1
  59. data/ext/oj/val_stack.h +8 -7
  60. data/ext/oj/validate.c +21 -26
  61. data/ext/oj/wab.c +32 -69
  62. data/lib/oj/active_support_helper.rb +1 -3
  63. data/lib/oj/bag.rb +7 -1
  64. data/lib/oj/easy_hash.rb +4 -5
  65. data/lib/oj/error.rb +0 -1
  66. data/lib/oj/json.rb +162 -150
  67. data/lib/oj/mimic.rb +6 -2
  68. data/lib/oj/saj.rb +20 -6
  69. data/lib/oj/state.rb +9 -6
  70. data/lib/oj/version.rb +1 -2
  71. data/lib/oj.rb +2 -0
  72. data/pages/Compatibility.md +1 -1
  73. data/pages/InstallOptions.md +20 -0
  74. data/pages/JsonGem.md +15 -0
  75. data/pages/Modes.md +6 -3
  76. data/pages/Options.md +10 -0
  77. data/pages/Rails.md +12 -0
  78. data/test/_test_active.rb +8 -9
  79. data/test/_test_active_mimic.rb +7 -8
  80. data/test/_test_mimic_rails.rb +17 -20
  81. data/test/activerecord/result_test.rb +5 -6
  82. data/test/{activesupport5 → activesupport7}/abstract_unit.rb +16 -12
  83. data/test/{activesupport5 → activesupport7}/decoding_test.rb +2 -10
  84. data/test/{activesupport5 → activesupport7}/encoding_test.rb +20 -34
  85. data/test/{activesupport5 → activesupport7}/encoding_test_cases.rb +6 -0
  86. data/test/{activesupport5 → activesupport7}/time_zone_test_helpers.rb +8 -0
  87. data/test/files.rb +15 -15
  88. data/test/foo.rb +15 -15
  89. data/test/helper.rb +11 -8
  90. data/test/isolated/shared.rb +3 -2
  91. data/test/json_gem/json_addition_test.rb +2 -2
  92. data/test/json_gem/json_common_interface_test.rb +8 -6
  93. data/test/json_gem/json_encoding_test.rb +0 -0
  94. data/test/json_gem/json_ext_parser_test.rb +1 -0
  95. data/test/json_gem/json_fixtures_test.rb +3 -2
  96. data/test/json_gem/json_generator_test.rb +49 -37
  97. data/test/json_gem/json_generic_object_test.rb +11 -11
  98. data/test/json_gem/json_parser_test.rb +54 -47
  99. data/test/json_gem/json_string_matching_test.rb +9 -9
  100. data/test/json_gem/test_helper.rb +7 -3
  101. data/test/mem.rb +13 -12
  102. data/test/perf.rb +21 -26
  103. data/test/perf_compat.rb +31 -33
  104. data/test/perf_dump.rb +50 -0
  105. data/test/perf_fast.rb +80 -82
  106. data/test/perf_file.rb +27 -29
  107. data/test/perf_object.rb +65 -69
  108. data/test/perf_once.rb +12 -11
  109. data/test/perf_parser.rb +42 -48
  110. data/test/perf_saj.rb +46 -54
  111. data/test/perf_scp.rb +57 -69
  112. data/test/perf_simple.rb +41 -39
  113. data/test/perf_strict.rb +68 -70
  114. data/test/perf_wab.rb +67 -69
  115. data/test/prec.rb +3 -3
  116. data/test/sample/change.rb +0 -1
  117. data/test/sample/dir.rb +0 -1
  118. data/test/sample/doc.rb +0 -1
  119. data/test/sample/file.rb +0 -1
  120. data/test/sample/group.rb +0 -1
  121. data/test/sample/hasprops.rb +0 -1
  122. data/test/sample/layer.rb +0 -1
  123. data/test/sample/rect.rb +0 -1
  124. data/test/sample/shape.rb +0 -1
  125. data/test/sample/text.rb +0 -1
  126. data/test/sample.rb +16 -16
  127. data/test/sample_json.rb +8 -8
  128. data/test/test_compat.rb +95 -43
  129. data/test/test_custom.rb +72 -51
  130. data/test/test_debian.rb +7 -10
  131. data/test/test_fast.rb +102 -87
  132. data/test/test_file.rb +41 -30
  133. data/test/test_gc.rb +16 -5
  134. data/test/test_generate.rb +5 -5
  135. data/test/test_hash.rb +4 -4
  136. data/test/test_integer_range.rb +9 -9
  137. data/test/test_null.rb +20 -20
  138. data/test/test_object.rb +85 -96
  139. data/test/test_parser.rb +6 -22
  140. data/test/test_parser_debug.rb +27 -0
  141. data/test/test_parser_saj.rb +115 -23
  142. data/test/test_parser_usual.rb +6 -6
  143. data/test/test_rails.rb +2 -2
  144. data/test/test_saj.rb +10 -8
  145. data/test/test_scp.rb +37 -39
  146. data/test/test_strict.rb +40 -32
  147. data/test/test_various.rb +163 -84
  148. data/test/test_wab.rb +48 -44
  149. data/test/test_writer.rb +47 -47
  150. data/test/tests.rb +13 -5
  151. data/test/tests_mimic.rb +12 -3
  152. data/test/tests_mimic_addition.rb +12 -3
  153. metadata +34 -144
  154. data/test/activesupport4/decoding_test.rb +0 -108
  155. data/test/activesupport4/encoding_test.rb +0 -531
  156. data/test/activesupport4/test_helper.rb +0 -41
  157. data/test/activesupport5/test_helper.rb +0 -72
  158. data/test/bar.rb +0 -16
  159. data/test/baz.rb +0 -16
  160. data/test/bug.rb +0 -16
  161. data/test/zoo.rb +0 -13
data/ext/oj/fast.c CHANGED
@@ -11,13 +11,15 @@
11
11
  #include <stdlib.h>
12
12
  #include <string.h>
13
13
 
14
+ #include "dump.h"
14
15
  #include "encode.h"
16
+ #include "mem.h"
15
17
  #include "oj.h"
16
18
 
17
19
  // maximum to allocate on the stack, arbitrary limit
18
20
  #define SMALL_JSON 65536
19
21
  #define MAX_STACK 100
20
- //#define BATCH_SIZE (4096 / sizeof(struct _leaf) - 1)
22
+ // #define BATCH_SIZE (4096 / sizeof(struct _leaf) - 1)
21
23
  #define BATCH_SIZE 100
22
24
 
23
25
  // Support for compaction
@@ -31,25 +33,25 @@ typedef struct _batch {
31
33
  struct _batch *next;
32
34
  int next_avail;
33
35
  struct _leaf leaves[BATCH_SIZE];
34
- } * Batch;
36
+ } *Batch;
35
37
 
36
38
  typedef struct _doc {
37
39
  Leaf data;
38
- Leaf * where; // points to current location
40
+ Leaf *where; // points to current location
39
41
  Leaf where_path[MAX_STACK]; // points to head of path
40
- char * json;
41
- unsigned long size; // number of leaves/branches in the doc
42
+ char *json;
43
+ unsigned long size; // number of leaves/branches in the doc
42
44
  VALUE self;
43
45
  Batch batches;
44
46
  struct _batch batch0;
45
- } * Doc;
47
+ } *Doc;
46
48
 
47
49
  typedef struct _parseInfo {
48
50
  char *str; // buffer being read from
49
51
  char *s; // current position in buffer
50
52
  Doc doc;
51
53
  void *stack_min;
52
- } * ParseInfo;
54
+ } *ParseInfo;
53
55
 
54
56
  static void leaf_init(Leaf leaf, int type);
55
57
  static Leaf leaf_new(Doc doc, int type);
@@ -73,7 +75,7 @@ static char *read_quoted_value(ParseInfo pi);
73
75
  static void skip_comment(ParseInfo pi);
74
76
 
75
77
  static VALUE protect_open_proc(VALUE x);
76
- static VALUE parse_json(VALUE clas, char *json, bool given, bool allocated);
78
+ static VALUE parse_json(VALUE clas, char *json, bool given);
77
79
  static void each_leaf(Doc doc, VALUE self);
78
80
  static int move_step(Doc doc, const char *path, int loc);
79
81
  static Leaf get_doc_leaf(Doc doc, const char *path);
@@ -112,10 +114,7 @@ inline static char *ulong_fill(char *s, size_t num) {
112
114
  char *b = buf + sizeof(buf) - 1;
113
115
 
114
116
  *b-- = '\0';
115
- for (; 0 < num; num /= 10, b--) {
116
- *b = (num % 10) + '0';
117
- }
118
- b++;
117
+ b = oj_longlong_to_string((long long)num, false, b);
119
118
  if ('\0' == *b) {
120
119
  b--;
121
120
  *b = '0';
@@ -159,7 +158,7 @@ inline static Leaf leaf_new(Doc doc, int type) {
159
158
  Leaf leaf;
160
159
 
161
160
  if (0 == doc->batches || BATCH_SIZE == doc->batches->next_avail) {
162
- Batch b = ALLOC(struct _batch);
161
+ Batch b = OJ_R_ALLOC(struct _batch);
163
162
 
164
163
  // Initializes all leaves with a NO_VAL value_type
165
164
  memset(b, 0, sizeof(struct _batch));
@@ -249,7 +248,7 @@ static void skip_comment(ParseInfo pi) {
249
248
  #endif
250
249
 
251
250
  static void leaf_fixnum_value(Leaf leaf) {
252
- char * s = leaf->str;
251
+ char *s = leaf->str;
253
252
  int64_t n = 0;
254
253
  int neg = 0;
255
254
  int big = 0;
@@ -355,7 +354,7 @@ static Leaf read_next(ParseInfo pi) {
355
354
 
356
355
  static Leaf read_obj(ParseInfo pi) {
357
356
  Leaf h = leaf_new(pi->doc, T_HASH);
358
- char * end;
357
+ char *end;
359
358
  const char *key = 0;
360
359
  Leaf val = 0;
361
360
 
@@ -574,7 +573,7 @@ static char *read_quoted_value(ParseInfo pi) {
574
573
  char *h = pi->s; // head
575
574
  char *t = h; // tail
576
575
 
577
- h++; // skip quote character
576
+ h++; // skip quote character
578
577
  t++;
579
578
  value = h;
580
579
  for (; '"' != *h; h++, t++) {
@@ -647,10 +646,11 @@ static void doc_free(Doc doc) {
647
646
  while (0 != (b = doc->batches)) {
648
647
  doc->batches = doc->batches->next;
649
648
  if (&doc->batch0 != b) {
650
- xfree(b);
649
+ OJ_R_FREE(b);
651
650
  }
652
651
  }
653
- // xfree(f);
652
+ OJ_R_FREE(doc->json);
653
+ OJ_R_FREE(doc);
654
654
  }
655
655
  }
656
656
 
@@ -670,27 +670,28 @@ static void free_doc_cb(void *x) {
670
670
  Doc doc = (Doc)x;
671
671
 
672
672
  if (0 != doc) {
673
- xfree(doc->json);
674
673
  doc_free(doc);
675
674
  }
676
675
  }
677
676
 
678
677
  static void mark_leaf(Leaf leaf) {
679
- switch (leaf->value_type) {
680
- case COL_VAL:
681
- if (NULL != leaf->elements) {
682
- Leaf first = leaf->elements->next;
683
- Leaf e = first;
678
+ if (NULL != leaf) {
679
+ switch (leaf->value_type) {
680
+ case COL_VAL:
681
+ if (NULL != leaf->elements) {
682
+ Leaf first = leaf->elements->next;
683
+ Leaf e = first;
684
684
 
685
- do {
686
- mark_leaf(e);
687
- e = e->next;
688
- } while (e != first);
689
- }
690
- break;
691
- case RUBY_VAL: mark(leaf->value); break;
685
+ do {
686
+ mark_leaf(e);
687
+ e = e->next;
688
+ } while (e != first);
689
+ }
690
+ break;
691
+ case RUBY_VAL: mark(leaf->value); break;
692
692
 
693
- default: break;
693
+ default: break;
694
+ }
694
695
  }
695
696
  }
696
697
 
@@ -746,20 +747,15 @@ static const rb_data_type_t oj_doc_type = {
746
747
  0,
747
748
  };
748
749
 
749
- static VALUE parse_json(VALUE clas, char *json, bool given, bool allocated) {
750
+ static VALUE parse_json(VALUE clas, char *json, bool given) {
750
751
  struct _parseInfo pi;
751
752
  volatile VALUE result = Qnil;
752
753
  Doc doc;
753
754
  int ex = 0;
754
755
  volatile VALUE self;
755
756
 
756
- // TBD are both needed? is stack allocation ever needed?
757
+ doc = OJ_R_ALLOC_N(struct _doc, 1);
757
758
 
758
- if (given) {
759
- doc = ALLOCA_N(struct _doc, 1);
760
- } else {
761
- doc = ALLOC(struct _doc);
762
- }
763
759
  // skip UTF-8 BOM if present
764
760
  if (0xEF == (uint8_t)*json && 0xBB == (uint8_t)json[1] && 0xBF == (uint8_t)json[2]) {
765
761
  pi.str = json + 3;
@@ -771,7 +767,7 @@ static VALUE parse_json(VALUE clas, char *json, bool given, bool allocated) {
771
767
  pi.doc = doc;
772
768
  #if IS_WINDOWS
773
769
  // assume a 1M stack and give half to ruby
774
- pi.stack_min = (void*)((char*)&pi - (512 * 1024));
770
+ pi.stack_min = (void *)((char *)&pi - (512L * 1024L));
775
771
  #else
776
772
  {
777
773
  struct rlimit lim;
@@ -784,18 +780,20 @@ static VALUE parse_json(VALUE clas, char *json, bool given, bool allocated) {
784
780
  }
785
781
  }
786
782
  #endif
783
+ doc->json = json;
787
784
  self = TypedData_Wrap_Struct(clas, &oj_doc_type, doc);
788
785
  doc->self = self;
789
- doc->json = json;
790
786
  DATA_PTR(doc->self) = doc;
791
787
  result = rb_protect(protect_open_proc, (VALUE)&pi, &ex);
792
788
  if (given || 0 != ex) {
793
789
  DATA_PTR(doc->self) = NULL;
790
+ // TBD is this needed?
791
+ /*
794
792
  doc_free(pi.doc);
795
- if (allocated && 0 != ex) { // will jump so caller will not free
796
- xfree(json);
793
+ if (0 != ex) { // will jump so caller will not free
794
+ OJ_R_FREE(json);
797
795
  }
798
- rb_gc_enable();
796
+ */
799
797
  } else {
800
798
  result = doc->self;
801
799
  }
@@ -1085,31 +1083,23 @@ static void each_value(Doc doc, Leaf leaf) {
1085
1083
  * doc.close()
1086
1084
  */
1087
1085
  static VALUE doc_open(VALUE clas, VALUE str) {
1088
- char * json;
1086
+ char *json;
1089
1087
  size_t len;
1090
1088
  volatile VALUE obj;
1091
1089
  int given = rb_block_given_p();
1092
- int allocate;
1093
1090
 
1094
1091
  Check_Type(str, T_STRING);
1095
- len = (int)RSTRING_LEN(str) + 1;
1096
- allocate = (SMALL_JSON < len || !given);
1097
- if (allocate) {
1098
- json = ALLOC_N(char, len);
1099
- } else {
1100
- json = ALLOCA_N(char, len);
1101
- }
1102
- // It should not be necessaary to stop GC but if it is not stopped and a
1103
- // large string is parsed that string is corrupted or freed during
1104
- // parsing. I'm not sure what is going on exactly but disabling GC avoids
1105
- // the issue.
1106
- rb_gc_disable();
1092
+ len = (int)RSTRING_LEN(str) + 1;
1093
+ json = OJ_R_ALLOC_N(char, len);
1094
+
1107
1095
  memcpy(json, StringValuePtr(str), len);
1108
- obj = parse_json(clas, json, given, allocate);
1109
- rb_gc_enable();
1110
- if (given && allocate) {
1111
- xfree(json);
1096
+ obj = parse_json(clas, json, given);
1097
+ // TBD is this needed
1098
+ /*
1099
+ if (given) {
1100
+ OJ_R_FREE(json);
1112
1101
  }
1102
+ */
1113
1103
  return obj;
1114
1104
  }
1115
1105
 
@@ -1133,27 +1123,21 @@ static VALUE doc_open(VALUE clas, VALUE str) {
1133
1123
  * doc.close()
1134
1124
  */
1135
1125
  static VALUE doc_open_file(VALUE clas, VALUE filename) {
1136
- char * path;
1137
- char * json;
1138
- FILE * f;
1126
+ char *path;
1127
+ char *json;
1128
+ FILE *f;
1139
1129
  size_t len;
1140
1130
  volatile VALUE obj;
1141
1131
  int given = rb_block_given_p();
1142
- int allocate;
1143
1132
 
1144
- Check_Type(filename, T_STRING);
1145
1133
  path = StringValuePtr(filename);
1146
1134
  if (0 == (f = fopen(path, "r"))) {
1147
1135
  rb_raise(rb_eIOError, "%s", strerror(errno));
1148
1136
  }
1149
1137
  fseek(f, 0, SEEK_END);
1150
- len = ftell(f);
1151
- allocate = (SMALL_JSON < len || !given);
1152
- if (allocate) {
1153
- json = ALLOC_N(char, len + 1);
1154
- } else {
1155
- json = ALLOCA_N(char, len + 1);
1156
- }
1138
+ len = ftell(f);
1139
+ json = OJ_R_ALLOC_N(char, len + 1);
1140
+
1157
1141
  fseek(f, 0, SEEK_SET);
1158
1142
  if (len != fread(json, 1, len, f)) {
1159
1143
  fclose(f);
@@ -1164,12 +1148,13 @@ static VALUE doc_open_file(VALUE clas, VALUE filename) {
1164
1148
  }
1165
1149
  fclose(f);
1166
1150
  json[len] = '\0';
1167
- rb_gc_disable();
1168
- obj = parse_json(clas, json, given, allocate);
1169
- rb_gc_enable();
1170
- if (given && allocate) {
1171
- xfree(json);
1151
+ obj = parse_json(clas, json, given);
1152
+ // TBD is this needed
1153
+ /*
1154
+ if (given) {
1155
+ OJ_R_FREE(json);
1172
1156
  }
1157
+ */
1173
1158
  return obj;
1174
1159
  }
1175
1160
 
@@ -1209,11 +1194,11 @@ static VALUE doc_where(VALUE self) {
1209
1194
  if (0 == *doc->where_path || doc->where == doc->where_path) {
1210
1195
  return oj_slash_string;
1211
1196
  } else {
1212
- Leaf * lp;
1197
+ Leaf *lp;
1213
1198
  Leaf leaf;
1214
1199
  size_t size = 3; // leading / and terminating \0
1215
- char * path;
1216
- char * p;
1200
+ char *path;
1201
+ char *p;
1217
1202
 
1218
1203
  for (lp = doc->where_path; lp <= doc->where; lp++) {
1219
1204
  leaf = *lp;
@@ -1316,7 +1301,6 @@ static VALUE doc_type(int argc, VALUE *argv, VALUE self) {
1316
1301
  VALUE type = Qnil;
1317
1302
 
1318
1303
  if (1 <= argc) {
1319
- Check_Type(*argv, T_STRING);
1320
1304
  path = StringValuePtr(*argv);
1321
1305
  }
1322
1306
  if (0 != (leaf = get_doc_leaf(doc, path))) {
@@ -1325,11 +1309,7 @@ static VALUE doc_type(int argc, VALUE *argv, VALUE self) {
1325
1309
  case T_TRUE: type = rb_cTrueClass; break;
1326
1310
  case T_FALSE: type = rb_cFalseClass; break;
1327
1311
  case T_STRING: type = rb_cString; break;
1328
- #ifdef RUBY_INTEGER_UNIFICATION
1329
1312
  case T_FIXNUM: type = rb_cInteger; break;
1330
- #else
1331
- case T_FIXNUM: type = rb_cFixnum; break;
1332
- #endif
1333
1313
  case T_FLOAT: type = rb_cFloat; break;
1334
1314
  case T_ARRAY: type = rb_cArray; break;
1335
1315
  case T_HASH: type = rb_cHash; break;
@@ -1356,11 +1336,10 @@ static VALUE doc_fetch(int argc, VALUE *argv, VALUE self) {
1356
1336
  Doc doc;
1357
1337
  Leaf leaf;
1358
1338
  volatile VALUE val = Qnil;
1359
- const char * path = 0;
1339
+ const char *path = 0;
1360
1340
 
1361
1341
  doc = self_doc(self);
1362
1342
  if (1 <= argc) {
1363
- Check_Type(*argv, T_STRING);
1364
1343
  path = StringValuePtr(*argv);
1365
1344
  if (2 == argc) {
1366
1345
  val = argv[1];
@@ -1385,7 +1364,6 @@ static VALUE doc_exists(VALUE self, VALUE str) {
1385
1364
  Leaf leaf;
1386
1365
 
1387
1366
  doc = self_doc(self);
1388
- Check_Type(str, T_STRING);
1389
1367
  if (0 != (leaf = get_doc_leaf(doc, StringValuePtr(str)))) {
1390
1368
  if (NULL != leaf) {
1391
1369
  return Qtrue;
@@ -1422,7 +1400,6 @@ static VALUE doc_each_leaf(int argc, VALUE *argv, VALUE self) {
1422
1400
  memcpy(save_path, doc->where_path, sizeof(Leaf) * (wlen + 1));
1423
1401
  }
1424
1402
  if (1 <= argc) {
1425
- Check_Type(*argv, T_STRING);
1426
1403
  path = StringValuePtr(*argv);
1427
1404
  if ('/' == *path) {
1428
1405
  doc->where = doc->where_path;
@@ -1457,7 +1434,6 @@ static VALUE doc_move(VALUE self, VALUE str) {
1457
1434
  const char *path;
1458
1435
  int loc;
1459
1436
 
1460
- Check_Type(str, T_STRING);
1461
1437
  path = StringValuePtr(str);
1462
1438
  if ('/' == *path) {
1463
1439
  doc->where = doc->where_path;
@@ -1492,13 +1468,13 @@ static VALUE doc_each_child(int argc, VALUE *argv, VALUE self) {
1492
1468
  Doc doc = self_doc(self);
1493
1469
  const char *path = 0;
1494
1470
  size_t wlen;
1471
+ Leaf *where_orig = doc->where;
1495
1472
 
1496
1473
  wlen = doc->where - doc->where_path;
1497
1474
  if (0 < wlen) {
1498
1475
  memcpy(save_path, doc->where_path, sizeof(Leaf) * (wlen + 1));
1499
1476
  }
1500
1477
  if (1 <= argc) {
1501
- Check_Type(*argv, T_STRING);
1502
1478
  path = StringValuePtr(*argv);
1503
1479
  if ('/' == *path) {
1504
1480
  doc->where = doc->where_path;
@@ -1508,9 +1484,13 @@ static VALUE doc_each_child(int argc, VALUE *argv, VALUE self) {
1508
1484
  if (0 < wlen) {
1509
1485
  memcpy(doc->where_path, save_path, sizeof(Leaf) * (wlen + 1));
1510
1486
  }
1487
+ doc->where = where_orig;
1511
1488
  return Qnil;
1512
1489
  }
1513
1490
  }
1491
+ if (NULL == doc->where || NULL == *doc->where) {
1492
+ return Qnil;
1493
+ }
1514
1494
  if (COL_VAL == (*doc->where)->value_type && 0 != (*doc->where)->elements) {
1515
1495
  Leaf first = (*doc->where)->elements->next;
1516
1496
  Leaf e = first;
@@ -1525,6 +1505,7 @@ static VALUE doc_each_child(int argc, VALUE *argv, VALUE self) {
1525
1505
  if (0 < wlen) {
1526
1506
  memcpy(doc->where_path, save_path, sizeof(Leaf) * (wlen + 1));
1527
1507
  }
1508
+ doc->where = where_orig;
1528
1509
  }
1529
1510
  return Qnil;
1530
1511
  }
@@ -1560,7 +1541,6 @@ static VALUE doc_each_value(int argc, VALUE *argv, VALUE self) {
1560
1541
  Leaf leaf;
1561
1542
 
1562
1543
  if (1 <= argc) {
1563
- Check_Type(*argv, T_STRING);
1564
1544
  path = StringValuePtr(*argv);
1565
1545
  }
1566
1546
  if (0 != (leaf = get_doc_leaf(doc, path))) {
@@ -1592,11 +1572,9 @@ static VALUE doc_dump(int argc, VALUE *argv, VALUE self) {
1592
1572
 
1593
1573
  if (1 <= argc) {
1594
1574
  if (Qnil != *argv) {
1595
- Check_Type(*argv, T_STRING);
1596
1575
  path = StringValuePtr(*argv);
1597
1576
  }
1598
1577
  if (2 <= argc) {
1599
- Check_Type(argv[1], T_STRING);
1600
1578
  filename = StringValuePtr(argv[1]);
1601
1579
  }
1602
1580
  }
@@ -1604,18 +1582,15 @@ static VALUE doc_dump(int argc, VALUE *argv, VALUE self) {
1604
1582
  volatile VALUE rjson;
1605
1583
 
1606
1584
  if (0 == filename) {
1607
- char buf[4096];
1608
1585
  struct _out out;
1609
1586
 
1610
- out.buf = buf;
1611
- out.end = buf + sizeof(buf) - 10;
1612
- out.allocated = false;
1613
- out.omit_nil = oj_default_options.dump_opts.omit_nil;
1587
+ oj_out_init(&out);
1588
+
1589
+ out.omit_nil = oj_default_options.dump_opts.omit_nil;
1614
1590
  oj_dump_leaf_to_json(leaf, &oj_default_options, &out);
1615
1591
  rjson = rb_str_new2(out.buf);
1616
- if (out.allocated) {
1617
- xfree(out.buf);
1618
- }
1592
+
1593
+ oj_out_free(&out);
1619
1594
  } else {
1620
1595
  oj_write_leaf_to_file(leaf, filename, &oj_default_options);
1621
1596
  rjson = Qnil;
@@ -1650,11 +1625,9 @@ static VALUE doc_close(VALUE self) {
1650
1625
  Doc doc = self_doc(self);
1651
1626
 
1652
1627
  rb_gc_unregister_address(&doc->self);
1653
- DATA_PTR(doc->self) = 0;
1628
+ DATA_PTR(doc->self) = NULL;
1654
1629
  if (0 != doc) {
1655
- xfree(doc->json);
1656
1630
  doc_free(doc);
1657
- xfree(doc);
1658
1631
  }
1659
1632
  return Qnil;
1660
1633
  }
@@ -1711,8 +1684,10 @@ static VALUE doc_not_implemented(VALUE self) {
1711
1684
  * # Now try again using a path to Oj::Doc.fetch() directly and not using a
1712
1685
  * block. doc = Oj::Doc.open(json) doc.fetch('/2/three') #=> 3 doc.close()
1713
1686
  */
1714
- void oj_init_doc() {
1687
+ void oj_init_doc(void) {
1715
1688
  oj_doc_class = rb_define_class_under(Oj, "Doc", rb_cObject);
1689
+ rb_gc_register_address(&oj_doc_class);
1690
+ rb_undef_alloc_func(oj_doc_class);
1716
1691
  rb_define_singleton_method(oj_doc_class, "open", doc_open, 1);
1717
1692
  rb_define_singleton_method(oj_doc_class, "open_file", doc_open_file, 1);
1718
1693
  rb_define_singleton_method(oj_doc_class, "parse", doc_open, 1);