oj 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of oj might be problematic. Click here for more details.

@@ -0,0 +1,46 @@
1
+ /* cache8.h
2
+ * Copyright (c) 2011, Peter Ohler
3
+ * All rights reserved.
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * - Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * - Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * - Neither the name of Peter Ohler nor the names of its contributors may be
16
+ * used to endorse or promote products derived from this software without
17
+ * specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ */
30
+
31
+ #ifndef __OJ_CACHE8_H__
32
+ #define __OJ_CACHE8_H__
33
+
34
+ #include "ruby.h"
35
+
36
+ typedef struct _Cache8 *Cache8;
37
+ typedef unsigned long slot_t;
38
+
39
+ extern void oj_cache8_new(Cache8 *cache);
40
+ extern void oj_cache8_delete(Cache8 cache);
41
+
42
+ extern slot_t oj_cache8_get(Cache8 cache, VALUE key, slot_t **slot);
43
+
44
+ extern void oj_cache8_print(Cache8 cache);
45
+
46
+ #endif /* __OJ_CACHE8_H__ */
@@ -41,35 +41,20 @@
41
41
  #include "st.h"
42
42
  #endif
43
43
 
44
- typedef unsigned long ulong;
45
-
46
- typedef struct _Str {
47
- const char *str;
48
- size_t len;
49
- } *Str;
44
+ #include "cache8.h"
50
45
 
51
- typedef struct _Element {
52
- struct _Str clas;
53
- struct _Str attr;
54
- unsigned long id;
55
- int indent; // < 0 indicates no \n
56
- int closed;
57
- char type;
58
- } *Element;
46
+ typedef unsigned long ulong;
59
47
 
60
48
  typedef struct _Out {
61
- void (*w_start)(struct _Out *out, Element e);
62
- void (*w_end)(struct _Out *out, Element e);
63
- void (*w_time)(struct _Out *out, VALUE obj);
64
- char *buf;
65
- char *end;
66
- char *cur;
67
- // Cache8 circ_cache;
68
- // unsigned long circ_cnt;
69
- int indent;
70
- int depth; // used by dumpHash
71
- Options opts;
72
- uint32_t hash_cnt;
49
+ char *buf;
50
+ char *end;
51
+ char *cur;
52
+ Cache8 circ_cache;
53
+ slot_t circ_cnt;
54
+ int indent;
55
+ int depth; // used by dump_hash
56
+ Options opts;
57
+ uint32_t hash_cnt;
73
58
  } *Out;
74
59
 
75
60
  static void dump_obj_to_json(VALUE obj, Options copts, Out out);
@@ -81,7 +66,7 @@ static void dump_false(Out out);
81
66
  static void dump_fixnum(VALUE obj, Out out);
82
67
  static void dump_bignum(VALUE obj, Out out);
83
68
  static void dump_float(VALUE obj, Out out);
84
- static void dump_cstr(const char *str, size_t cnt, int is_sym, Out out);
69
+ static void dump_cstr(const char *str, size_t cnt, int is_sym, int escape1, Out out);
85
70
  static void dump_hex(u_char c, Out out);
86
71
  static void dump_str_comp(VALUE obj, Out out);
87
72
  static void dump_str_obj(VALUE obj, Out out);
@@ -98,8 +83,10 @@ static void dump_data_comp(VALUE obj, Out out);
98
83
  static void dump_data_obj(VALUE obj, Out out);
99
84
  static void dump_obj_comp(VALUE obj, int depth, Out out);
100
85
  static void dump_obj_obj(VALUE obj, int depth, Out out);
86
+ static void dump_struct_comp(VALUE obj, int depth, Out out);
87
+ static void dump_struct_obj(VALUE obj, int depth, Out out);
101
88
  static int dump_attr_cb(ID key, VALUE value, Out out);
102
- static void dump_obj_attrs(VALUE obj, int with_class, int depth, Out out);
89
+ static void dump_obj_attrs(VALUE obj, int with_class, slot_t id, int depth, Out out);
103
90
 
104
91
  static void grow(Out out, size_t len);
105
92
  static int is_json_friendly(const u_char *str, size_t len);
@@ -154,6 +141,39 @@ fill_indent(Out out, int cnt) {
154
141
  }
155
142
  }
156
143
 
144
+ inline static const char*
145
+ ulong2str(uint32_t num, char *end) {
146
+ char *b;
147
+
148
+ *end-- = '\0';
149
+ for (b = end; 0 < num || b == end; num /= 10, b--) {
150
+ *b = (num % 10) + '0';
151
+ }
152
+ b++;
153
+
154
+ return b;
155
+ }
156
+
157
+ inline static void
158
+ dump_ulong(unsigned long num, Out out) {
159
+ char buf[32];
160
+ char *b = buf + sizeof(buf) - 1;
161
+
162
+ *b-- = '\0';
163
+ if (0 < num) {
164
+ for (; 0 < num; num /= 10, b--) {
165
+ *b = (num % 10) + '0';
166
+ }
167
+ b++;
168
+ } else {
169
+ *b = '0';
170
+ }
171
+ for (; '\0' != *b; b++) {
172
+ *out->cur++ = *b;
173
+ }
174
+ *out->cur = '\0';
175
+ }
176
+
157
177
  static void
158
178
  grow(Out out, size_t len) {
159
179
  size_t size = out->end - out->buf;
@@ -181,6 +201,34 @@ dump_hex(u_char c, Out out) {
181
201
  *out->cur++ = hex_chars[d];
182
202
  }
183
203
 
204
+ // returns 0 if not using circular references, -1 if not further writing is
205
+ // needed (duplicate), and a positive value if the object was added to the cache.
206
+ static long
207
+ check_circular(VALUE obj, Out out) {
208
+ slot_t id = 0;
209
+ slot_t *slot;
210
+
211
+ if (ObjectMode == out->opts->mode && Yes == out->opts->circular) {
212
+ if (0 == (id = oj_cache8_get(out->circ_cache, obj, &slot))) {
213
+ out->circ_cnt++;
214
+ id = out->circ_cnt;
215
+ *slot = id;
216
+ } else {
217
+ if (out->end - out->cur <= 18) {
218
+ grow(out, 18);
219
+ }
220
+ *out->cur++ = '"';
221
+ *out->cur++ = '^';
222
+ *out->cur++ = 'r';
223
+ dump_ulong(id, out);
224
+ *out->cur++ = '"';
225
+
226
+ return -1;
227
+ }
228
+ }
229
+ return (long)id;
230
+ }
231
+
184
232
  static void
185
233
  dump_nil(Out out) {
186
234
  size_t size = 4;
@@ -286,15 +334,25 @@ dump_float(VALUE obj, Out out) {
286
334
  }
287
335
 
288
336
  static void
289
- dump_cstr(const char *str, size_t cnt, int is_sym, Out out) {
337
+ dump_cstr(const char *str, size_t cnt, int is_sym, int escape1, Out out) {
290
338
  size_t size = json_friendly_size((u_char*)str, cnt);
291
339
 
340
+ if (out->end - out->cur <= (long)size + 10) { // extra 10 for escaped first char, quotes, and sym
341
+ grow(out, size + 10);
342
+ }
343
+ *out->cur++ = '"';
344
+ if (escape1) {
345
+ *out->cur++ = '\\';
346
+ *out->cur++ = 'u';
347
+ *out->cur++ = '0';
348
+ *out->cur++ = '0';
349
+ dump_hex((u_char)*str, out);
350
+ cnt--;
351
+ size--;
352
+ str++;
353
+ is_sym = 0; // just to make sure
354
+ }
292
355
  if (cnt == size) {
293
- cnt += 2 + is_sym;
294
- if (out->end - out->cur <= (long)cnt) {
295
- grow(out, cnt);
296
- }
297
- *out->cur++ = '"';
298
356
  if (is_sym) {
299
357
  *out->cur++ = ':';
300
358
  }
@@ -303,11 +361,6 @@ dump_cstr(const char *str, size_t cnt, int is_sym, Out out) {
303
361
  }
304
362
  *out->cur++ = '"';
305
363
  } else {
306
- size += 2;
307
- if (out->end - out->cur <= (long)size) {
308
- grow(out, size);
309
- }
310
- *out->cur++ = '"';
311
364
  if (is_sym) {
312
365
  *out->cur++ = ':';
313
366
  }
@@ -352,37 +405,23 @@ dump_cstr(const char *str, size_t cnt, int is_sym, Out out) {
352
405
 
353
406
  static void
354
407
  dump_str_comp(VALUE obj, Out out) {
355
- dump_cstr(StringValuePtr(obj), RSTRING_LEN(obj), 0, out);
408
+ dump_cstr(StringValuePtr(obj), RSTRING_LEN(obj), 0, 0, out);
356
409
  }
357
410
 
358
411
  static void
359
412
  dump_str_obj(VALUE obj, Out out) {
360
413
  const char *s = StringValuePtr(obj);
361
414
  size_t len = RSTRING_LEN(obj);
362
-
363
- if (':' == *s) {
364
- if (out->end - out->cur <= 6) {
365
- grow(out, 6);
366
- }
367
- *out->cur++ = '{';
368
- *out->cur++ = '"';
369
- *out->cur++ = '^';
370
- *out->cur++ = 's';
371
- *out->cur++ = '"';
372
- *out->cur++ = ':';
373
- dump_cstr(s, len, 0, out);
374
- *out->cur++ = '}';
375
- *out->cur = '\0';
376
- } else {
377
- dump_cstr(s, len, 0, out);
378
- }
415
+ char s1 = s[1];
416
+
417
+ dump_cstr(s, len, 0, (':' == *s || ('^' == *s && ('r' == s1 || 'i' == s1))), out);
379
418
  }
380
419
 
381
420
  static void
382
421
  dump_sym_comp(VALUE obj, Out out) {
383
422
  const char *sym = rb_id2name(SYM2ID(obj));
384
423
 
385
- dump_cstr(sym, strlen(sym), 0, out);
424
+ dump_cstr(sym, strlen(sym), 0, 0, out);
386
425
  }
387
426
 
388
427
  static void
@@ -390,29 +429,14 @@ dump_sym_obj(VALUE obj, Out out) {
390
429
  const char *sym = rb_id2name(SYM2ID(obj));
391
430
  size_t len = strlen(sym);
392
431
 
393
- if (':' == *sym) {
394
- if (out->end - out->cur <= 6) {
395
- grow(out, 6);
396
- }
397
- *out->cur++ = '{';
398
- *out->cur++ = '"';
399
- *out->cur++ = '^';
400
- *out->cur++ = 'm';
401
- *out->cur++ = '"';
402
- *out->cur++ = ':';
403
- dump_cstr(sym, len, 0, out);
404
- *out->cur++ = '}';
405
- *out->cur = '\0';
406
- } else {
407
- dump_cstr(sym, len, 1, out);
408
- }
432
+ dump_cstr(sym, len, 1, 0, out);
409
433
  }
410
434
 
411
435
  static void
412
436
  dump_class_comp(VALUE obj, Out out) {
413
437
  const char *s = rb_class2name(obj);
414
438
 
415
- dump_cstr(s, strlen(s), 0, out);
439
+ dump_cstr(s, strlen(s), 0, 0, out);
416
440
  }
417
441
 
418
442
  static void
@@ -429,25 +453,47 @@ dump_class_obj(VALUE obj, Out out) {
429
453
  *out->cur++ = 'c';
430
454
  *out->cur++ = '"';
431
455
  *out->cur++ = ':';
432
- dump_cstr(s, len, 0, out);
456
+ dump_cstr(s, len, 0, 0, out);
433
457
  *out->cur++ = '}';
434
458
  *out->cur = '\0';
435
459
  }
436
460
 
437
461
  static void
438
462
  dump_array(VALUE a, int depth, Out out) {
439
- VALUE *np = RARRAY_PTR(a);
440
- size_t size = 2;
441
- int cnt = (int)RARRAY_LEN(a);
463
+ VALUE *np;
464
+ size_t size;
465
+ int cnt;
442
466
  int d2 = depth + 1;
443
-
467
+ long id = check_circular(a, out);
468
+
469
+ if (id < 0) {
470
+ return;
471
+ }
472
+ np = RARRAY_PTR(a);
473
+ cnt = (int)RARRAY_LEN(a);
474
+ *out->cur++ = '[';
475
+ if (0 < id) {
476
+ size = d2 * out->indent + 16;
477
+ if (out->end - out->cur <= (long)size) {
478
+ grow(out, size);
479
+ }
480
+ fill_indent(out, d2);
481
+ *out->cur++ = '"';
482
+ *out->cur++ = '^';
483
+ *out->cur++ = 'i';
484
+ dump_ulong(id, out);
485
+ *out->cur++ = '"';
486
+ }
487
+ size = 2;
444
488
  if (out->end - out->cur <= (long)size) {
445
489
  grow(out, size);
446
490
  }
447
- *out->cur++ = '[';
448
491
  if (0 == cnt) {
449
492
  *out->cur++ = ']';
450
493
  } else {
494
+ if (0 < id) {
495
+ *out->cur++ = ',';
496
+ }
451
497
  size = d2 * out->indent + 2;
452
498
  for (; 0 < cnt; cnt--, np++) {
453
499
  if (out->end - out->cur <= (long)size) {
@@ -456,7 +502,6 @@ dump_array(VALUE a, int depth, Out out) {
456
502
  fill_indent(out, d2);
457
503
  dump_val(*np, d2, out);
458
504
  if (1 < cnt) {
459
- // TBD check size?
460
505
  *out->cur++ = ',';
461
506
  }
462
507
  }
@@ -501,7 +546,6 @@ hash_cb_object(VALUE key, VALUE value, Out out) {
501
546
  grow(out, size);
502
547
  }
503
548
  fill_indent(out, depth);
504
- // TBD if key is a string else dump with unique key for and entry array
505
549
  if (rb_type(key) == T_STRING) {
506
550
  dump_str_obj(key, out);
507
551
  *out->cur++ = ':';
@@ -558,17 +602,35 @@ hash_cb_object(VALUE key, VALUE value, Out out) {
558
602
 
559
603
  static void
560
604
  dump_hash(VALUE obj, int depth, int mode, Out out) {
561
- int cnt = (int)RHASH_SIZE(obj);
605
+ int cnt = (int)RHASH_SIZE(obj);
606
+ size_t size = depth * out->indent + 2;
562
607
 
563
608
  if (out->end - out->cur <= 2) {
564
609
  grow(out, 2);
565
610
  }
566
- *out->cur++ = '{';
567
611
  if (0 == cnt) {
612
+ *out->cur++ = '{';
568
613
  *out->cur++ = '}';
569
614
  } else {
570
- size_t size = depth * out->indent + 2;
615
+ long id = check_circular(obj, out);
571
616
 
617
+ if (0 > id) {
618
+ return;
619
+ }
620
+ *out->cur++ = '{';
621
+ if (0 < id) {
622
+ if (out->end - out->cur <= (long)size + 16) {
623
+ grow(out, size + 16);
624
+ }
625
+ fill_indent(out, depth + 1);
626
+ *out->cur++ = '"';
627
+ *out->cur++ = '^';
628
+ *out->cur++ = 'i';
629
+ *out->cur++ = '"';
630
+ *out->cur++ = ':';
631
+ dump_ulong(id, out);
632
+ *out->cur++ = ',';
633
+ }
572
634
  out->depth = depth + 1;
573
635
  if (ObjectMode == mode) {
574
636
  rb_hash_foreach(obj, hash_cb_object, (VALUE)out);
@@ -656,6 +718,13 @@ dump_obj_comp(VALUE obj, int depth, Out out) {
656
718
  rb_raise(rb_eTypeError, "%s.to_hash() did not return a Hash.\n", rb_class2name(rb_obj_class(obj)));
657
719
  }
658
720
  dump_hash(h, depth, out->opts->mode, out);
721
+ } else if (rb_respond_to(obj, oj_as_json_id)) {
722
+ VALUE h = rb_funcall(obj, oj_as_json_id, 0);
723
+
724
+ if (T_HASH != rb_type(h)) {
725
+ rb_raise(rb_eTypeError, "%s.as_json() did not return a Hash.\n", rb_class2name(rb_obj_class(obj)));
726
+ }
727
+ dump_hash(h, depth, out->opts->mode, out);
659
728
  } else if (rb_respond_to(obj, oj_to_json_id)) {
660
729
  VALUE rs = rb_funcall(obj, oj_to_json_id, 0);
661
730
  const char *s = StringValuePtr(rs);
@@ -667,14 +736,18 @@ dump_obj_comp(VALUE obj, int depth, Out out) {
667
736
  memcpy(out->cur, s, len);
668
737
  out->cur += len;
669
738
  } else {
670
- dump_obj_attrs(obj, 0, depth, out);
739
+ dump_obj_attrs(obj, 0, 0, depth, out);
671
740
  }
672
741
  *out->cur = '\0';
673
742
  }
674
743
 
675
744
  inline static void
676
745
  dump_obj_obj(VALUE obj, int depth, Out out) {
677
- dump_obj_attrs(obj, 1, depth, out);
746
+ long id = check_circular(obj, out);
747
+
748
+ if (0 <= id) {
749
+ dump_obj_attrs(obj, 1, id, depth, out);
750
+ }
678
751
  }
679
752
 
680
753
  static int
@@ -689,14 +762,14 @@ dump_attr_cb(ID key, VALUE value, Out out) {
689
762
  fill_indent(out, depth);
690
763
  if ('@' == *attr) {
691
764
  attr++;
692
- dump_cstr(attr, strlen(attr), 0, out);
765
+ dump_cstr(attr, strlen(attr), 0, 0, out);
693
766
  } else {
694
767
  char buf[32];
695
768
 
696
769
  *buf = '~';
697
770
  strncpy(buf + 1, attr, sizeof(buf) - 2);
698
771
  buf[sizeof(buf) - 1] = '\0';
699
- dump_cstr(buf, strlen(buf), 0, out);
772
+ dump_cstr(buf, strlen(buf), 0, 0, out);
700
773
  }
701
774
  *out->cur++ = ':';
702
775
  dump_val(value, depth, out);
@@ -707,7 +780,7 @@ dump_attr_cb(ID key, VALUE value, Out out) {
707
780
  }
708
781
 
709
782
  static void
710
- dump_obj_attrs(VALUE obj, int with_class, int depth, Out out) {
783
+ dump_obj_attrs(VALUE obj, int with_class, slot_t id, int depth, Out out) {
711
784
  size_t size;
712
785
  int d2 = depth + 1;
713
786
 
@@ -729,7 +802,21 @@ dump_obj_attrs(VALUE obj, int with_class, int depth, Out out) {
729
802
  *out->cur++ = 'o';
730
803
  *out->cur++ = '"';
731
804
  *out->cur++ = ':';
732
- dump_cstr(class_name, clen, 0, out);
805
+ dump_cstr(class_name, clen, 0, 0, out);
806
+ }
807
+ if (0 < id) {
808
+ size = d2 * out->indent + 16;
809
+ if (out->end - out->cur <= (long)size) {
810
+ grow(out, size);
811
+ }
812
+ *out->cur++ = ',';
813
+ fill_indent(out, d2);
814
+ *out->cur++ = '"';
815
+ *out->cur++ = '^';
816
+ *out->cur++ = 'i';
817
+ *out->cur++ = '"';
818
+ *out->cur++ = ':';
819
+ dump_ulong(id, out);
733
820
  }
734
821
  {
735
822
  int cnt;
@@ -763,14 +850,14 @@ dump_obj_attrs(VALUE obj, int with_class, int depth, Out out) {
763
850
  attr = rb_id2name(vid);
764
851
  if ('@' == *attr) {
765
852
  attr++;
766
- dump_cstr(attr, strlen(attr), 0, out);
853
+ dump_cstr(attr, strlen(attr), 0, 0, out);
767
854
  } else {
768
855
  char buf[32];
769
856
 
770
857
  *buf = '~';
771
858
  strncpy(buf + 1, attr, sizeof(buf) - 2);
772
859
  buf[sizeof(buf) - 1] = '\0';
773
- dump_cstr(buf, strlen(attr) + 1, 0, out);
860
+ dump_cstr(buf, strlen(attr) + 1, 0, 0, out);
774
861
  }
775
862
  *out->cur++ = ':';
776
863
  dump_val(rb_ivar_get(obj, vid), d2, out);
@@ -788,6 +875,73 @@ dump_obj_attrs(VALUE obj, int with_class, int depth, Out out) {
788
875
  *out->cur = '\0';
789
876
  }
790
877
 
878
+ static void
879
+ dump_struct_comp(VALUE obj, int depth, Out out) {
880
+ if (rb_respond_to(obj, oj_to_hash_id)) {
881
+ VALUE h = rb_funcall(obj, oj_to_hash_id, 0);
882
+
883
+ if (T_HASH != rb_type(h)) {
884
+ rb_raise(rb_eTypeError, "%s.to_hash() did not return a Hash.\n", rb_class2name(rb_obj_class(obj)));
885
+ }
886
+ dump_hash(h, depth, out->opts->mode, out);
887
+ } else if (rb_respond_to(obj, oj_to_json_id)) {
888
+ VALUE rs = rb_funcall(obj, oj_to_json_id, 0);
889
+ const char *s = StringValuePtr(rs);
890
+ int len = (int)RSTRING_LEN(rs);
891
+
892
+ if (out->end - out->cur <= len) {
893
+ grow(out, len);
894
+ }
895
+ memcpy(out->cur, s, len);
896
+ out->cur += len;
897
+ } else {
898
+ dump_struct_obj(obj, depth, out);
899
+ }
900
+ }
901
+
902
+ static void
903
+ dump_struct_obj(VALUE obj, int depth, Out out) {
904
+ VALUE clas = rb_obj_class(obj);
905
+ const char *class_name = rb_class2name(clas);
906
+ VALUE *vp;
907
+ int i;
908
+ int d2 = depth + 1;
909
+ int d3 = d2 + 1;
910
+ size_t len = strlen(class_name);
911
+ size_t size = d2 * out->indent + d3 * out->indent + 10 + len;
912
+
913
+ if (out->end - out->cur <= (long)size) {
914
+ grow(out, size);
915
+ }
916
+ *out->cur++ = '{';
917
+ fill_indent(out, d2);
918
+ *out->cur++ = '"';
919
+ *out->cur++ = '^';
920
+ *out->cur++ = 'u';
921
+ *out->cur++ = '"';
922
+ *out->cur++ = ':';
923
+ *out->cur++ = '[';
924
+ fill_indent(out, d3);
925
+ *out->cur++ = '"';
926
+ memcpy(out->cur, class_name, len);
927
+ out->cur += len;
928
+ *out->cur++ = '"';
929
+ *out->cur++ = ',';
930
+ size = d3 * out->indent + 2;
931
+ for (i = (int)RSTRUCT_LEN(obj), vp = RSTRUCT_PTR(obj); 0 < i; i--, vp++) {
932
+ if (out->end - out->cur <= (long)size) {
933
+ grow(out, size);
934
+ }
935
+ fill_indent(out, d3);
936
+ dump_val(*vp, d3, out);
937
+ *out->cur++ = ',';
938
+ }
939
+ out->cur--;
940
+ *out->cur++ = ']';
941
+ *out->cur++ = '}';
942
+ *out->cur = '\0';
943
+ }
944
+
791
945
  static void
792
946
  raise_strict(VALUE obj) {
793
947
  rb_raise(rb_eTypeError, "Failed to dump %s Object to JSON in strict mode.\n", rb_class2name(rb_obj_class(obj)));
@@ -850,6 +1004,14 @@ dump_val(VALUE obj, int depth, Out out) {
850
1004
  }
851
1005
  break;
852
1006
  case T_STRUCT: // for Range
1007
+ switch (out->opts->mode) {
1008
+ case StrictMode: raise_strict(obj); break;
1009
+ case NullMode: dump_nil(out); break;
1010
+ case CompatMode: dump_struct_comp(obj, depth, out); break;
1011
+ case ObjectMode:
1012
+ default: dump_struct_obj(obj, depth, out); break;
1013
+ }
1014
+ break;
853
1015
  #if (defined T_COMPLEX && defined RCOMPLEX)
854
1016
  case T_COMPLEX:
855
1017
  #endif
@@ -857,9 +1019,13 @@ dump_val(VALUE obj, int depth, Out out) {
857
1019
  case T_RATIONAL:
858
1020
  #endif
859
1021
  case T_REGEXP:
860
- // TBD
861
- rb_raise(rb_eNotImpError, "Failed to dump '%s' Object (%02x)\n",
862
- rb_class2name(rb_obj_class(obj)), rb_type(obj));
1022
+ switch (out->opts->mode) {
1023
+ case StrictMode: raise_strict(obj); break;
1024
+ case NullMode: dump_nil(out); break;
1025
+ case CompatMode:
1026
+ case ObjectMode:
1027
+ default: dump_obj_comp(obj, depth, out); break;
1028
+ }
863
1029
  break;
864
1030
  default:
865
1031
  rb_raise(rb_eNotImpError, "Failed to dump '%s' Object (%02x)\n",
@@ -873,19 +1039,17 @@ dump_obj_to_json(VALUE obj, Options copts, Out out) {
873
1039
  out->buf = (char*)malloc(65336);
874
1040
  out->end = out->buf + 65325; // 1 less than end plus extra for possible errors
875
1041
  out->cur = out->buf;
876
- // out->circ_cache = 0;
877
- // out->circ_cnt = 0;
1042
+ out->circ_cnt = 0;
878
1043
  out->opts = copts;
879
1044
  out->hash_cnt = 0;
880
- /* if (Yes == copts->circular) {
881
- ox_cache8_new(&out->circ_cache);
882
- }*/
1045
+ if (Yes == copts->circular) {
1046
+ oj_cache8_new(&out->circ_cache);
1047
+ }
883
1048
  out->indent = copts->indent;
884
1049
  dump_val(obj, 0, out);
885
-
886
- /* if (Yes == copts->circular) {
887
- ox_cache8_delete(out->circ_cache);
888
- }*/
1050
+ if (Yes == copts->circular) {
1051
+ oj_cache8_delete(out->circ_cache);
1052
+ }
889
1053
  }
890
1054
 
891
1055
  char*