scout 5.6.7 → 5.6.8.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. data/CHANGELOG.markdown +4 -0
  2. data/lib/scout/version.rb +1 -1
  3. data/vendor/json_pure/.gitignore +12 -0
  4. data/vendor/json_pure/.travis.yml +20 -0
  5. data/vendor/json_pure/CHANGES +120 -0
  6. data/vendor/json_pure/COPYING-json-jruby +57 -0
  7. data/vendor/json_pure/Gemfile +11 -0
  8. data/vendor/json_pure/README-json-jruby.markdown +33 -0
  9. data/vendor/json_pure/{README → README.rdoc} +7 -7
  10. data/vendor/json_pure/Rakefile +305 -185
  11. data/vendor/json_pure/VERSION +1 -1
  12. data/vendor/json_pure/diagrams/.keep +0 -0
  13. data/vendor/json_pure/ext/json/ext/fbuffer/fbuffer.h +181 -0
  14. data/vendor/json_pure/ext/json/ext/generator/depend +1 -0
  15. data/vendor/json_pure/ext/json/ext/generator/extconf.rb +4 -6
  16. data/vendor/json_pure/ext/json/ext/generator/generator.c +463 -369
  17. data/vendor/json_pure/ext/json/ext/generator/generator.h +44 -66
  18. data/vendor/json_pure/ext/json/ext/parser/depend +1 -0
  19. data/vendor/json_pure/ext/json/ext/parser/extconf.rb +3 -5
  20. data/vendor/json_pure/ext/json/ext/parser/parser.c +580 -311
  21. data/vendor/json_pure/ext/json/ext/parser/parser.h +14 -8
  22. data/vendor/json_pure/ext/json/ext/parser/parser.rl +242 -107
  23. data/vendor/json_pure/install.rb +8 -11
  24. data/vendor/json_pure/java/src/json/ext/ByteListTranscoder.java +167 -0
  25. data/vendor/json_pure/java/src/json/ext/Generator.java +444 -0
  26. data/vendor/json_pure/java/src/json/ext/GeneratorMethods.java +232 -0
  27. data/vendor/json_pure/java/src/json/ext/GeneratorService.java +43 -0
  28. data/vendor/json_pure/java/src/json/ext/GeneratorState.java +543 -0
  29. data/vendor/json_pure/java/src/json/ext/OptionsReader.java +114 -0
  30. data/vendor/json_pure/java/src/json/ext/Parser.java +2644 -0
  31. data/vendor/json_pure/java/src/json/ext/Parser.rl +968 -0
  32. data/vendor/json_pure/java/src/json/ext/ParserService.java +35 -0
  33. data/vendor/json_pure/java/src/json/ext/RuntimeInfo.java +121 -0
  34. data/vendor/json_pure/java/src/json/ext/StringDecoder.java +167 -0
  35. data/vendor/json_pure/java/src/json/ext/StringEncoder.java +106 -0
  36. data/vendor/json_pure/java/src/json/ext/Utils.java +89 -0
  37. data/vendor/json_pure/json-java.gemspec +23 -0
  38. data/vendor/json_pure/json.gemspec +37 -0
  39. data/vendor/json_pure/json_pure.gemspec +39 -0
  40. data/vendor/json_pure/lib/json.rb +52 -0
  41. data/vendor/json_pure/lib/json/add/bigdecimal.rb +28 -0
  42. data/vendor/json_pure/lib/json/add/complex.rb +22 -0
  43. data/vendor/json_pure/lib/json/add/core.rb +9 -146
  44. data/vendor/json_pure/lib/json/add/date.rb +34 -0
  45. data/vendor/json_pure/lib/json/add/date_time.rb +50 -0
  46. data/vendor/json_pure/lib/json/add/exception.rb +31 -0
  47. data/vendor/json_pure/lib/json/add/ostruct.rb +31 -0
  48. data/vendor/json_pure/lib/json/add/range.rb +29 -0
  49. data/vendor/json_pure/lib/json/add/rational.rb +22 -0
  50. data/vendor/json_pure/lib/json/add/regexp.rb +30 -0
  51. data/vendor/json_pure/lib/json/add/struct.rb +30 -0
  52. data/vendor/json_pure/lib/json/add/symbol.rb +25 -0
  53. data/vendor/json_pure/lib/json/add/time.rb +38 -0
  54. data/vendor/json_pure/lib/json/common.rb +157 -67
  55. data/vendor/json_pure/lib/json/ext.rb +8 -2
  56. data/vendor/json_pure/lib/json/ext/.keep +0 -0
  57. data/vendor/json_pure/lib/json/generic_object.rb +70 -0
  58. data/vendor/json_pure/lib/json/pure.rb +8 -64
  59. data/vendor/json_pure/lib/json/pure/generator.rb +183 -113
  60. data/vendor/json_pure/lib/json/pure/parser.rb +118 -66
  61. data/vendor/json_pure/lib/json/version.rb +1 -1
  62. data/vendor/json_pure/tests/fixtures/fail18.json +1 -1
  63. data/vendor/json_pure/tests/setup_variant.rb +11 -0
  64. data/vendor/json_pure/tests/test_json.rb +233 -28
  65. data/vendor/json_pure/tests/test_json_addition.rb +68 -34
  66. data/vendor/json_pure/tests/test_json_encoding.rb +11 -14
  67. data/vendor/json_pure/tests/test_json_fixtures.rb +11 -10
  68. data/vendor/json_pure/tests/test_json_generate.rb +207 -7
  69. data/vendor/json_pure/tests/test_json_generic_object.rb +75 -0
  70. data/vendor/json_pure/tests/test_json_string_matching.rb +39 -0
  71. data/vendor/json_pure/tests/test_json_unicode.rb +3 -7
  72. data/vendor/json_pure/tools/fuzz.rb +1 -1
  73. data/vendor/json_pure/tools/server.rb +1 -0
  74. metadata +87 -94
  75. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkComparison.log +0 -52
  76. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast-autocorrelation.dat +0 -1000
  77. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast.dat +0 -1001
  78. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty-autocorrelation.dat +0 -900
  79. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty.dat +0 -901
  80. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe-autocorrelation.dat +0 -1000
  81. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe.dat +0 -1001
  82. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt.log +0 -261
  83. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast-autocorrelation.dat +0 -1000
  84. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast.dat +0 -1001
  85. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty-autocorrelation.dat +0 -1000
  86. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty.dat +0 -1001
  87. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe-autocorrelation.dat +0 -1000
  88. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe.dat +0 -1001
  89. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure.log +0 -262
  90. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator-autocorrelation.dat +0 -1000
  91. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator.dat +0 -1001
  92. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails.log +0 -82
  93. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkComparison.log +0 -34
  94. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser-autocorrelation.dat +0 -900
  95. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser.dat +0 -901
  96. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt.log +0 -81
  97. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser-autocorrelation.dat +0 -1000
  98. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser.dat +0 -1001
  99. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure.log +0 -82
  100. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser-autocorrelation.dat +0 -1000
  101. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser.dat +0 -1001
  102. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails.log +0 -82
  103. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser-autocorrelation.dat +0 -1000
  104. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser.dat +0 -1001
  105. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML.log +0 -82
  106. data/vendor/json_pure/benchmarks/generator2_benchmark.rb +0 -222
  107. data/vendor/json_pure/benchmarks/generator_benchmark.rb +0 -224
  108. data/vendor/json_pure/benchmarks/ohai.json +0 -1216
  109. data/vendor/json_pure/benchmarks/ohai.ruby +0 -1
  110. data/vendor/json_pure/benchmarks/parser2_benchmark.rb +0 -251
  111. data/vendor/json_pure/benchmarks/parser_benchmark.rb +0 -259
  112. data/vendor/json_pure/bin/edit_json.rb +0 -9
  113. data/vendor/json_pure/bin/prettify_json.rb +0 -75
  114. data/vendor/json_pure/lib/json/Array.xpm +0 -21
  115. data/vendor/json_pure/lib/json/FalseClass.xpm +0 -21
  116. data/vendor/json_pure/lib/json/Hash.xpm +0 -21
  117. data/vendor/json_pure/lib/json/Key.xpm +0 -73
  118. data/vendor/json_pure/lib/json/NilClass.xpm +0 -21
  119. data/vendor/json_pure/lib/json/Numeric.xpm +0 -28
  120. data/vendor/json_pure/lib/json/String.xpm +0 -96
  121. data/vendor/json_pure/lib/json/TrueClass.xpm +0 -21
  122. data/vendor/json_pure/lib/json/add/rails.rb +0 -58
  123. data/vendor/json_pure/lib/json/editor.rb +0 -1371
  124. data/vendor/json_pure/lib/json/json.xpm +0 -1499
  125. data/vendor/json_pure/tests/test_json_rails.rb +0 -144
@@ -1 +1 @@
1
- 1.4.2
1
+ 1.8.0
File without changes
@@ -0,0 +1,181 @@
1
+
2
+ #ifndef _FBUFFER_H_
3
+ #define _FBUFFER_H_
4
+
5
+ #include "ruby.h"
6
+
7
+ #ifndef RHASH_SIZE
8
+ #define RHASH_SIZE(hsh) (RHASH(hsh)->tbl->num_entries)
9
+ #endif
10
+
11
+ #ifndef RFLOAT_VALUE
12
+ #define RFLOAT_VALUE(val) (RFLOAT(val)->value)
13
+ #endif
14
+
15
+ #ifndef RARRAY_PTR
16
+ #define RARRAY_PTR(ARRAY) RARRAY(ARRAY)->ptr
17
+ #endif
18
+ #ifndef RARRAY_LEN
19
+ #define RARRAY_LEN(ARRAY) RARRAY(ARRAY)->len
20
+ #endif
21
+ #ifndef RSTRING_PTR
22
+ #define RSTRING_PTR(string) RSTRING(string)->ptr
23
+ #endif
24
+ #ifndef RSTRING_LEN
25
+ #define RSTRING_LEN(string) RSTRING(string)->len
26
+ #endif
27
+
28
+ #ifdef HAVE_RUBY_ENCODING_H
29
+ #include "ruby/encoding.h"
30
+ #define FORCE_UTF8(obj) rb_enc_associate((obj), rb_utf8_encoding())
31
+ #else
32
+ #define FORCE_UTF8(obj)
33
+ #endif
34
+
35
+ /* We don't need to guard objects for rbx, so let's do nothing at all. */
36
+ #ifndef RB_GC_GUARD
37
+ #define RB_GC_GUARD(object)
38
+ #endif
39
+
40
+ typedef struct FBufferStruct {
41
+ unsigned long initial_length;
42
+ char *ptr;
43
+ unsigned long len;
44
+ unsigned long capa;
45
+ } FBuffer;
46
+
47
+ #define FBUFFER_INITIAL_LENGTH_DEFAULT 1024
48
+
49
+ #define FBUFFER_PTR(fb) (fb->ptr)
50
+ #define FBUFFER_LEN(fb) (fb->len)
51
+ #define FBUFFER_CAPA(fb) (fb->capa)
52
+ #define FBUFFER_PAIR(fb) FBUFFER_PTR(fb), FBUFFER_LEN(fb)
53
+
54
+ static FBuffer *fbuffer_alloc(unsigned long initial_length);
55
+ static void fbuffer_free(FBuffer *fb);
56
+ static void fbuffer_clear(FBuffer *fb);
57
+ static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len);
58
+ #ifdef JSON_GENERATOR
59
+ static void fbuffer_append_long(FBuffer *fb, long number);
60
+ #endif
61
+ static void fbuffer_append_char(FBuffer *fb, char newchr);
62
+ #ifdef JSON_GENERATOR
63
+ static FBuffer *fbuffer_dup(FBuffer *fb);
64
+ static VALUE fbuffer_to_s(FBuffer *fb);
65
+ #endif
66
+
67
+ static FBuffer *fbuffer_alloc(unsigned long initial_length)
68
+ {
69
+ FBuffer *fb;
70
+ if (initial_length <= 0) initial_length = FBUFFER_INITIAL_LENGTH_DEFAULT;
71
+ fb = ALLOC(FBuffer);
72
+ memset((void *) fb, 0, sizeof(FBuffer));
73
+ fb->initial_length = initial_length;
74
+ return fb;
75
+ }
76
+
77
+ static void fbuffer_free(FBuffer *fb)
78
+ {
79
+ if (fb->ptr) ruby_xfree(fb->ptr);
80
+ ruby_xfree(fb);
81
+ }
82
+
83
+ static void fbuffer_clear(FBuffer *fb)
84
+ {
85
+ fb->len = 0;
86
+ }
87
+
88
+ static void fbuffer_inc_capa(FBuffer *fb, unsigned long requested)
89
+ {
90
+ unsigned long required;
91
+
92
+ if (!fb->ptr) {
93
+ fb->ptr = ALLOC_N(char, fb->initial_length);
94
+ fb->capa = fb->initial_length;
95
+ }
96
+
97
+ for (required = fb->capa; requested > required - fb->len; required <<= 1);
98
+
99
+ if (required > fb->capa) {
100
+ REALLOC_N(fb->ptr, char, required);
101
+ fb->capa = required;
102
+ }
103
+ }
104
+
105
+ static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len)
106
+ {
107
+ if (len > 0) {
108
+ fbuffer_inc_capa(fb, len);
109
+ MEMCPY(fb->ptr + fb->len, newstr, char, len);
110
+ fb->len += len;
111
+ }
112
+ }
113
+
114
+ #ifdef JSON_GENERATOR
115
+ static void fbuffer_append_str(FBuffer *fb, VALUE str)
116
+ {
117
+ const char *newstr = StringValuePtr(str);
118
+ unsigned long len = RSTRING_LEN(str);
119
+
120
+ RB_GC_GUARD(str);
121
+
122
+ fbuffer_append(fb, newstr, len);
123
+ }
124
+ #endif
125
+
126
+ static void fbuffer_append_char(FBuffer *fb, char newchr)
127
+ {
128
+ fbuffer_inc_capa(fb, 1);
129
+ *(fb->ptr + fb->len) = newchr;
130
+ fb->len++;
131
+ }
132
+
133
+ #ifdef JSON_GENERATOR
134
+ static void freverse(char *start, char *end)
135
+ {
136
+ char c;
137
+
138
+ while (end > start) {
139
+ c = *end, *end-- = *start, *start++ = c;
140
+ }
141
+ }
142
+
143
+ static long fltoa(long number, char *buf)
144
+ {
145
+ static char digits[] = "0123456789";
146
+ long sign = number;
147
+ char* tmp = buf;
148
+
149
+ if (sign < 0) number = -number;
150
+ do *tmp++ = digits[number % 10]; while (number /= 10);
151
+ if (sign < 0) *tmp++ = '-';
152
+ freverse(buf, tmp - 1);
153
+ return tmp - buf;
154
+ }
155
+
156
+ static void fbuffer_append_long(FBuffer *fb, long number)
157
+ {
158
+ char buf[20];
159
+ unsigned long len = fltoa(number, buf);
160
+ fbuffer_append(fb, buf, len);
161
+ }
162
+
163
+ static FBuffer *fbuffer_dup(FBuffer *fb)
164
+ {
165
+ unsigned long len = fb->len;
166
+ FBuffer *result;
167
+
168
+ result = fbuffer_alloc(len);
169
+ fbuffer_append(result, FBUFFER_PAIR(fb));
170
+ return result;
171
+ }
172
+
173
+ static VALUE fbuffer_to_s(FBuffer *fb)
174
+ {
175
+ VALUE result = rb_str_new(FBUFFER_PAIR(fb));
176
+ fbuffer_free(fb);
177
+ FORCE_UTF8(result);
178
+ return result;
179
+ }
180
+ #endif
181
+ #endif
@@ -0,0 +1 @@
1
+ generator.o: generator.c generator.h $(srcdir)/../fbuffer/fbuffer.h
@@ -1,16 +1,14 @@
1
1
  require 'mkmf'
2
- require 'rbconfig'
3
2
 
4
3
  unless $CFLAGS.gsub!(/ -O[\dsz]?/, ' -O3')
5
4
  $CFLAGS << ' -O3'
6
5
  end
7
6
  if CONFIG['CC'] =~ /gcc/
8
7
  $CFLAGS << ' -Wall'
9
- #unless $CFLAGS.gsub!(/ -O[\dsz]?/, ' -O0 -ggdb')
10
- # $CFLAGS << ' -O0 -ggdb'
11
- #end
8
+ unless $DEBUG && !$CFLAGS.gsub!(/ -O[\dsz]?/, ' -O0 -ggdb')
9
+ $CFLAGS << ' -O0 -ggdb'
10
+ end
12
11
  end
13
12
 
14
- have_header("ruby/re.h") || have_header("re.h")
15
- have_header("ruby/encoding.h")
13
+ $defs << "-DJSON_GENERATOR"
16
14
  create_makefile 'json/ext/generator'
@@ -1,3 +1,4 @@
1
+ #include "../fbuffer/fbuffer.h"
1
2
  #include "generator.h"
2
3
 
3
4
  #ifdef HAVE_RUBY_ENCODING_H
@@ -6,20 +7,22 @@ static ID i_encoding, i_encode;
6
7
  #endif
7
8
 
8
9
  static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject,
9
- mHash, mArray, mInteger, mFloat, mString, mString_Extend,
10
+ mHash, mArray, mFixnum, mBignum, mFloat, mString, mString_Extend,
10
11
  mTrueClass, mFalseClass, mNilClass, eGeneratorError,
11
- eNestingError, CRegexp_MULTILINE, CJSON_SAFE_STATE_PROTOTYPE;
12
+ eNestingError, CRegexp_MULTILINE, CJSON_SAFE_STATE_PROTOTYPE,
13
+ i_SAFE_STATE_PROTOTYPE;
12
14
 
13
15
  static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
14
16
  i_object_nl, i_array_nl, i_max_nesting, i_allow_nan, i_ascii_only,
15
- i_pack, i_unpack, i_create_id, i_extend, i_key_p, i_aref, i_send,
16
- i_respond_to_p, i_match;
17
+ i_quirks_mode, i_pack, i_unpack, i_create_id, i_extend, i_key_p,
18
+ i_aref, i_send, i_respond_to_p, i_match, i_keys, i_depth,
19
+ i_buffer_initial_length, i_dup;
17
20
 
18
21
  /*
19
22
  * Copyright 2001-2004 Unicode, Inc.
20
- *
23
+ *
21
24
  * Disclaimer
22
- *
25
+ *
23
26
  * This source code is provided as is by Unicode, Inc. No claims are
24
27
  * made as to fitness for any particular purpose. No warranties of any
25
28
  * kind are expressed or implied. The recipient agrees to determine
@@ -27,9 +30,9 @@ static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
27
30
  * purchased on magnetic or optical media from Unicode, Inc., the
28
31
  * sole remedy for any claim will be exchange of defective media
29
32
  * within 90 days of receipt.
30
- *
33
+ *
31
34
  * Limitations on Rights to Redistribute This Code
32
- *
35
+ *
33
36
  * Unicode, Inc. hereby grants the right to freely use the information
34
37
  * supplied in this file in the creation of products supporting the
35
38
  * Unicode Standard, and to make copies of this file in any form
@@ -60,8 +63,8 @@ static const char trailingBytesForUTF8[256] = {
60
63
  * This table contains as many values as there might be trailing bytes
61
64
  * in a UTF-8 sequence.
62
65
  */
63
- static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
64
- 0x03C82080UL, 0xFA082080UL, 0x82082080UL };
66
+ static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
67
+ 0x03C82080UL, 0xFA082080UL, 0x82082080UL };
65
68
 
66
69
  /*
67
70
  * Utility routine to tell whether a sequence of bytes is legal UTF-8.
@@ -73,7 +76,7 @@ static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080
73
76
  * If presented with a length > 4, this returns 0. The Unicode
74
77
  * definition of UTF-8 goes up to 4-byte sequences.
75
78
  */
76
- static unsigned char isLegalUTF8(const UTF8 *source, int length)
79
+ static unsigned char isLegalUTF8(const UTF8 *source, unsigned long length)
77
80
  {
78
81
  UTF8 a;
79
82
  const UTF8 *srcptr = source+length;
@@ -111,7 +114,7 @@ static void unicode_escape(char *buf, UTF16 character)
111
114
  }
112
115
 
113
116
  /* Escapes the UTF16 character and stores the result in the buffer buf, then
114
- * the buffer buf іs appended to the FBuffer buffer. */
117
+ * the buffer buf is appended to the FBuffer buffer. */
115
118
  static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16
116
119
  character)
117
120
  {
@@ -222,7 +225,7 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
222
225
  static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
223
226
  {
224
227
  const char *ptr = RSTRING_PTR(string), *p;
225
- int len = RSTRING_LEN(string), start = 0, end = 0;
228
+ unsigned long len = RSTRING_LEN(string), start = 0, end = 0;
226
229
  const char *escape = NULL;
227
230
  int escape_len;
228
231
  unsigned char c;
@@ -270,7 +273,18 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
270
273
  escape_len = 2;
271
274
  break;
272
275
  default:
273
- end++;
276
+ {
277
+ unsigned short clen = trailingBytesForUTF8[c] + 1;
278
+ if (end + clen > len) {
279
+ rb_raise(rb_path2class("JSON::GeneratorError"),
280
+ "partial character in source, but hit end");
281
+ }
282
+ if (!isLegalUTF8((UTF8 *) p, clen)) {
283
+ rb_raise(rb_path2class("JSON::GeneratorError"),
284
+ "source sequence is illegal/malformed utf-8");
285
+ }
286
+ end += clen;
287
+ }
274
288
  continue;
275
289
  break;
276
290
  }
@@ -283,7 +297,7 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
283
297
  fbuffer_append(buffer, ptr + start, end - start);
284
298
  }
285
299
 
286
- static char *fstrndup(const char *ptr, int len) {
300
+ static char *fstrndup(const char *ptr, unsigned long len) {
287
301
  char *result;
288
302
  if (len <= 0) return NULL;
289
303
  result = ALLOC_N(char, len);
@@ -291,119 +305,7 @@ static char *fstrndup(const char *ptr, int len) {
291
305
  return result;
292
306
  }
293
307
 
294
- /* fbuffer implementation */
295
-
296
- static FBuffer *fbuffer_alloc()
297
- {
298
- FBuffer *fb = ALLOC(FBuffer);
299
- memset((void *) fb, 0, sizeof(FBuffer));
300
- fb->initial_length = FBUFFER_INITIAL_LENGTH;
301
- return fb;
302
- }
303
-
304
- static FBuffer *fbuffer_alloc_with_length(unsigned int initial_length)
305
- {
306
- FBuffer *fb;
307
- assert(initial_length > 0);
308
- fb = ALLOC(FBuffer);
309
- memset((void *) fb, 0, sizeof(FBuffer));
310
- fb->initial_length = initial_length;
311
- return fb;
312
- }
313
-
314
- static void fbuffer_free(FBuffer *fb)
315
- {
316
- if (fb->ptr) ruby_xfree(fb->ptr);
317
- ruby_xfree(fb);
318
- }
319
-
320
- static void fbuffer_free_only_buffer(FBuffer *fb)
321
- {
322
- ruby_xfree(fb);
323
- }
324
-
325
- static void fbuffer_clear(FBuffer *fb)
326
- {
327
- fb->len = 0;
328
- }
329
-
330
- static void fbuffer_inc_capa(FBuffer *fb, unsigned int requested)
331
- {
332
- unsigned int required;
333
-
334
- if (!fb->ptr) {
335
- fb->ptr = ALLOC_N(char, fb->initial_length);
336
- fb->capa = fb->initial_length;
337
- }
338
-
339
- for (required = fb->capa; requested > required - fb->len; required <<= 1);
340
-
341
- if (required > fb->capa) {
342
- fb->ptr = (char *) REALLOC_N((long*) fb->ptr, char, required);
343
- fb->capa = required;
344
- }
345
- }
346
-
347
- static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned int len)
348
- {
349
- if (len > 0) {
350
- fbuffer_inc_capa(fb, len);
351
- MEMCPY(fb->ptr + fb->len, newstr, char, len);
352
- fb->len += len;
353
- }
354
- }
355
-
356
- static void fbuffer_append_char(FBuffer *fb, char newchr)
357
- {
358
- fbuffer_inc_capa(fb, 1);
359
- *(fb->ptr + fb->len) = newchr;
360
- fb->len++;
361
- }
362
-
363
- static void freverse(char *start, char *end)
364
- {
365
- char c;
366
-
367
- while (end > start) {
368
- c = *end, *end-- = *start, *start++ = c;
369
- }
370
- }
371
-
372
- static int fltoa(long number, char *buf)
373
- {
374
- static char digits[] = "0123456789";
375
- long sign = number;
376
- char* tmp = buf;
377
-
378
- if (sign < 0) number = -number;
379
- do *tmp++ = digits[number % 10]; while (number /= 10);
380
- if (sign < 0) *tmp++ = '-';
381
- freverse(buf, tmp - 1);
382
- return tmp - buf;
383
- }
384
-
385
- static void fbuffer_append_long(FBuffer *fb, long number)
386
- {
387
- char buf[20];
388
- int len = fltoa(number, buf);
389
- fbuffer_append(fb, buf, len);
390
- }
391
-
392
- static FBuffer *fbuffer_dup(FBuffer *fb)
393
- {
394
- int len = fb->len;
395
- FBuffer *result;
396
-
397
- if (len > 0) {
398
- result = fbuffer_alloc_with_length(len);
399
- fbuffer_append(result, FBUFFER_PAIR(fb));
400
- } else {
401
- result = fbuffer_alloc();
402
- }
403
- return result;
404
- }
405
-
406
- /*
308
+ /*
407
309
  * Document-module: JSON::Ext::Generator
408
310
  *
409
311
  * This is the JSON generator implemented as a C extension. It can be
@@ -416,37 +318,28 @@ static FBuffer *fbuffer_dup(FBuffer *fb)
416
318
  */
417
319
 
418
320
  /*
419
- * call-seq: to_json(state = nil, depth = 0)
321
+ * call-seq: to_json(state = nil)
420
322
  *
421
323
  * Returns a JSON string containing a JSON object, that is generated from
422
324
  * this Hash instance.
423
325
  * _state_ is a JSON::State object, that can also be used to configure the
424
326
  * produced JSON string output further.
425
- * _depth_ is used to find out nesting depth, to indent accordingly.
426
327
  */
427
328
  static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
428
329
  {
429
- VALUE state, depth;
430
-
431
- rb_scan_args(argc, argv, "02", &state, &depth);
432
- state = cState_from_state_s(cState, state);
433
- return cState_partial_generate(state, self, depth);
330
+ GENERATE_JSON(object);
434
331
  }
435
332
 
436
333
  /*
437
- * call-seq: to_json(state = nil, depth = 0)
334
+ * call-seq: to_json(state = nil)
438
335
  *
439
336
  * Returns a JSON string containing a JSON array, that is generated from
440
337
  * this Array instance.
441
338
  * _state_ is a JSON::State object, that can also be used to configure the
442
339
  * produced JSON string output further.
443
- * _depth_ is used to find out nesting depth, to indent accordingly.
444
340
  */
445
341
  static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
446
- VALUE state, depth;
447
- rb_scan_args(argc, argv, "02", &state, &depth);
448
- state = cState_from_state_s(cState, state);
449
- return cState_partial_generate(state, self, depth);
342
+ GENERATE_JSON(array);
450
343
  }
451
344
 
452
345
  /*
@@ -454,12 +347,19 @@ static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
454
347
  *
455
348
  * Returns a JSON string representation for this Integer number.
456
349
  */
457
- static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
350
+ static VALUE mFixnum_to_json(int argc, VALUE *argv, VALUE self)
458
351
  {
459
- VALUE state, depth;
460
- rb_scan_args(argc, argv, "02", &state, &depth);
461
- state = cState_from_state_s(cState, state);
462
- return cState_partial_generate(state, self, depth);
352
+ GENERATE_JSON(fixnum);
353
+ }
354
+
355
+ /*
356
+ * call-seq: to_json(*)
357
+ *
358
+ * Returns a JSON string representation for this Integer number.
359
+ */
360
+ static VALUE mBignum_to_json(int argc, VALUE *argv, VALUE self)
361
+ {
362
+ GENERATE_JSON(bignum);
463
363
  }
464
364
 
465
365
  /*
@@ -469,10 +369,7 @@ static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
469
369
  */
470
370
  static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
471
371
  {
472
- VALUE state, depth;
473
- rb_scan_args(argc, argv, "02", &state, &depth);
474
- state = cState_from_state_s(cState, state);
475
- return cState_partial_generate(state, self, depth);
372
+ GENERATE_JSON(float);
476
373
  }
477
374
 
478
375
  /*
@@ -494,10 +391,7 @@ static VALUE mString_included_s(VALUE self, VALUE modul) {
494
391
  */
495
392
  static VALUE mString_to_json(int argc, VALUE *argv, VALUE self)
496
393
  {
497
- VALUE state, depth;
498
- rb_scan_args(argc, argv, "02", &state, &depth);
499
- state = cState_from_state_s(cState, state);
500
- return cState_partial_generate(state, self, depth);
394
+ GENERATE_JSON(string);
501
395
  }
502
396
 
503
397
  /*
@@ -552,10 +446,7 @@ static VALUE mString_Extend_json_create(VALUE self, VALUE o)
552
446
  */
553
447
  static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
554
448
  {
555
- VALUE state, depth;
556
- rb_scan_args(argc, argv, "02", &state, &depth);
557
- state = cState_from_state_s(cState, state);
558
- return cState_partial_generate(state, self, depth);
449
+ GENERATE_JSON(true);
559
450
  }
560
451
 
561
452
  /*
@@ -565,22 +456,17 @@ static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
565
456
  */
566
457
  static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self)
567
458
  {
568
- VALUE state, depth;
569
- rb_scan_args(argc, argv, "02", &state, &depth);
570
- state = cState_from_state_s(cState, state);
571
- return cState_partial_generate(state, self, depth);
459
+ GENERATE_JSON(false);
572
460
  }
573
461
 
574
462
  /*
575
463
  * call-seq: to_json(*)
576
464
  *
465
+ * Returns a JSON string for nil: 'null'.
577
466
  */
578
467
  static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self)
579
468
  {
580
- VALUE state, depth;
581
- rb_scan_args(argc, argv, "02", &state, &depth);
582
- state = cState_from_state_s(cState, state);
583
- return cState_partial_generate(state, self, depth);
469
+ GENERATE_JSON(null);
584
470
  }
585
471
 
586
472
  /*
@@ -592,12 +478,12 @@ static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self)
592
478
  */
593
479
  static VALUE mObject_to_json(int argc, VALUE *argv, VALUE self)
594
480
  {
595
- VALUE state, depth;
481
+ VALUE state;
596
482
  VALUE string = rb_funcall(self, i_to_s, 0);
597
- rb_scan_args(argc, argv, "02", &state, &depth);
483
+ rb_scan_args(argc, argv, "01", &state);
598
484
  Check_Type(string, T_STRING);
599
485
  state = cState_from_state_s(cState, state);
600
- return cState_partial_generate(state, string, depth);
486
+ return cState_partial_generate(state, string);
601
487
  }
602
488
 
603
489
  static void State_free(JSON_Generator_State *state)
@@ -616,6 +502,7 @@ static void State_free(JSON_Generator_State *state)
616
502
  static JSON_Generator_State *State_allocate()
617
503
  {
618
504
  JSON_Generator_State *state = ALLOC(JSON_Generator_State);
505
+ MEMZERO(state, JSON_Generator_State, 1);
619
506
  return state;
620
507
  }
621
508
 
@@ -635,54 +522,51 @@ static VALUE cState_configure(VALUE self, VALUE opts)
635
522
  {
636
523
  VALUE tmp;
637
524
  GET_STATE(self);
638
- tmp = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
525
+ tmp = rb_check_convert_type(opts, T_HASH, "Hash", "to_hash");
639
526
  if (NIL_P(tmp)) tmp = rb_convert_type(opts, T_HASH, "Hash", "to_h");
640
- if (NIL_P(tmp)) {
641
- rb_raise(rb_eArgError, "opts has to be hash like or convertable into a hash");
642
- }
643
527
  opts = tmp;
644
528
  tmp = rb_hash_aref(opts, ID2SYM(i_indent));
645
529
  if (RTEST(tmp)) {
646
- int len;
530
+ unsigned long len;
647
531
  Check_Type(tmp, T_STRING);
648
532
  len = RSTRING_LEN(tmp);
649
- state->indent = fstrndup(RSTRING_PTR(tmp), len);
533
+ state->indent = fstrndup(RSTRING_PTR(tmp), len + 1);
650
534
  state->indent_len = len;
651
535
  }
652
536
  tmp = rb_hash_aref(opts, ID2SYM(i_space));
653
537
  if (RTEST(tmp)) {
654
- int len;
538
+ unsigned long len;
655
539
  Check_Type(tmp, T_STRING);
656
540
  len = RSTRING_LEN(tmp);
657
- state->space = fstrndup(RSTRING_PTR(tmp), len);
541
+ state->space = fstrndup(RSTRING_PTR(tmp), len + 1);
658
542
  state->space_len = len;
659
543
  }
660
544
  tmp = rb_hash_aref(opts, ID2SYM(i_space_before));
661
545
  if (RTEST(tmp)) {
662
- int len;
546
+ unsigned long len;
663
547
  Check_Type(tmp, T_STRING);
664
548
  len = RSTRING_LEN(tmp);
665
- state->space_before = fstrndup(RSTRING_PTR(tmp), len);
549
+ state->space_before = fstrndup(RSTRING_PTR(tmp), len + 1);
666
550
  state->space_before_len = len;
667
551
  }
668
552
  tmp = rb_hash_aref(opts, ID2SYM(i_array_nl));
669
553
  if (RTEST(tmp)) {
670
- int len;
554
+ unsigned long len;
671
555
  Check_Type(tmp, T_STRING);
672
556
  len = RSTRING_LEN(tmp);
673
- state->array_nl = fstrndup(RSTRING_PTR(tmp), len);
557
+ state->array_nl = fstrndup(RSTRING_PTR(tmp), len + 1);
674
558
  state->array_nl_len = len;
675
559
  }
676
560
  tmp = rb_hash_aref(opts, ID2SYM(i_object_nl));
677
561
  if (RTEST(tmp)) {
678
- int len;
562
+ unsigned long len;
679
563
  Check_Type(tmp, T_STRING);
680
564
  len = RSTRING_LEN(tmp);
681
- state->object_nl = fstrndup(RSTRING_PTR(tmp), len);
565
+ state->object_nl = fstrndup(RSTRING_PTR(tmp), len + 1);
682
566
  state->object_nl_len = len;
683
567
  }
684
568
  tmp = ID2SYM(i_max_nesting);
685
- state->max_nesting = 19;
569
+ state->max_nesting = 100;
686
570
  if (option_given_p(opts, tmp)) {
687
571
  VALUE max_nesting = rb_hash_aref(opts, tmp);
688
572
  if (RTEST(max_nesting)) {
@@ -692,13 +576,48 @@ static VALUE cState_configure(VALUE self, VALUE opts)
692
576
  state->max_nesting = 0;
693
577
  }
694
578
  }
579
+ tmp = ID2SYM(i_depth);
580
+ state->depth = 0;
581
+ if (option_given_p(opts, tmp)) {
582
+ VALUE depth = rb_hash_aref(opts, tmp);
583
+ if (RTEST(depth)) {
584
+ Check_Type(depth, T_FIXNUM);
585
+ state->depth = FIX2LONG(depth);
586
+ } else {
587
+ state->depth = 0;
588
+ }
589
+ }
590
+ tmp = ID2SYM(i_buffer_initial_length);
591
+ if (option_given_p(opts, tmp)) {
592
+ VALUE buffer_initial_length = rb_hash_aref(opts, tmp);
593
+ if (RTEST(buffer_initial_length)) {
594
+ long initial_length;
595
+ Check_Type(buffer_initial_length, T_FIXNUM);
596
+ initial_length = FIX2LONG(buffer_initial_length);
597
+ if (initial_length > 0) state->buffer_initial_length = initial_length;
598
+ }
599
+ }
695
600
  tmp = rb_hash_aref(opts, ID2SYM(i_allow_nan));
696
601
  state->allow_nan = RTEST(tmp);
697
602
  tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
698
603
  state->ascii_only = RTEST(tmp);
604
+ tmp = rb_hash_aref(opts, ID2SYM(i_quirks_mode));
605
+ state->quirks_mode = RTEST(tmp);
699
606
  return self;
700
607
  }
701
608
 
609
+ static void set_state_ivars(VALUE hash, VALUE state)
610
+ {
611
+ VALUE ivars = rb_obj_instance_variables(state);
612
+ int i = 0;
613
+ for (i = 0; i < RARRAY_LEN(ivars); i++) {
614
+ VALUE key = rb_funcall(rb_ary_entry(ivars, i), i_to_s, 0);
615
+ long key_len = RSTRING_LEN(key);
616
+ VALUE value = rb_iv_get(state, StringValueCStr(key));
617
+ rb_hash_aset(hash, rb_str_intern(rb_str_substr(key, 1, key_len - 1)), value);
618
+ }
619
+ }
620
+
702
621
  /*
703
622
  * call-seq: to_h
704
623
  *
@@ -709,6 +628,7 @@ static VALUE cState_to_h(VALUE self)
709
628
  {
710
629
  VALUE result = rb_hash_new();
711
630
  GET_STATE(self);
631
+ set_state_ivars(result, self);
712
632
  rb_hash_aset(result, ID2SYM(i_indent), rb_str_new(state->indent, state->indent_len));
713
633
  rb_hash_aset(result, ID2SYM(i_space), rb_str_new(state->space, state->space_len));
714
634
  rb_hash_aset(result, ID2SYM(i_space_before), rb_str_new(state->space_before, state->space_before_len));
@@ -716,7 +636,10 @@ static VALUE cState_to_h(VALUE self)
716
636
  rb_hash_aset(result, ID2SYM(i_array_nl), rb_str_new(state->array_nl, state->array_nl_len));
717
637
  rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse);
718
638
  rb_hash_aset(result, ID2SYM(i_ascii_only), state->ascii_only ? Qtrue : Qfalse);
639
+ rb_hash_aset(result, ID2SYM(i_quirks_mode), state->quirks_mode ? Qtrue : Qfalse);
719
640
  rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
641
+ rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth));
642
+ rb_hash_aset(result, ID2SYM(i_buffer_initial_length), LONG2FIX(state->buffer_initial_length));
720
643
  return result;
721
644
  }
722
645
 
@@ -727,186 +650,226 @@ static VALUE cState_to_h(VALUE self)
727
650
  */
728
651
  static VALUE cState_aref(VALUE self, VALUE name)
729
652
  {
730
- GET_STATE(self);
653
+ name = rb_funcall(name, i_to_s, 0);
731
654
  if (RTEST(rb_funcall(self, i_respond_to_p, 1, name))) {
732
655
  return rb_funcall(self, i_send, 1, name);
733
656
  } else {
734
- return Qnil;
657
+ return rb_ivar_get(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)));
735
658
  }
736
659
  }
737
660
 
738
- static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj, long depth)
661
+ /*
662
+ * call-seq: []=(name, value)
663
+ *
664
+ * Set the attribute name to value.
665
+ */
666
+ static VALUE cState_aset(VALUE self, VALUE name, VALUE value)
739
667
  {
740
- VALUE tmp;
741
- switch (TYPE(obj)) {
742
- case T_HASH:
743
- {
744
- char *object_nl = state->object_nl;
745
- long object_nl_len = state->object_nl_len;
746
- char *indent = state->indent;
747
- long indent_len = state->indent_len;
748
- long max_nesting = state->max_nesting;
749
- char *delim = FBUFFER_PTR(state->object_delim);
750
- long delim_len = FBUFFER_LEN(state->object_delim);
751
- char *delim2 = FBUFFER_PTR(state->object_delim2);
752
- long delim2_len = FBUFFER_LEN(state->object_delim2);
753
- int i, j;
754
- VALUE key, key_to_s, keys;
755
- depth++;
756
- if (max_nesting != 0 && depth > max_nesting) {
757
- fbuffer_free(buffer);
758
- rb_raise(eNestingError, "nesting of %ld is too deep", depth);
759
- }
760
- fbuffer_append_char(buffer, '{');
761
- keys = rb_funcall(obj, rb_intern("keys"), 0);
762
- for(i = 0; i < RARRAY_LEN(keys); i++) {
763
- if (i > 0) fbuffer_append(buffer, delim, delim_len);
764
- if (object_nl) {
765
- fbuffer_append(buffer, object_nl, object_nl_len);
766
- }
767
- if (indent) {
768
- for (j = 0; j < depth; j++) {
769
- fbuffer_append(buffer, indent, indent_len);
770
- }
771
- }
772
- key = rb_ary_entry(keys, i);
773
- key_to_s = rb_funcall(key, i_to_s, 0);
774
- Check_Type(key_to_s, T_STRING);
775
- generate_json(buffer, Vstate, state, key_to_s, depth);
776
- fbuffer_append(buffer, delim2, delim2_len);
777
- generate_json(buffer, Vstate, state, rb_hash_aref(obj, key), depth);
778
- }
779
- depth--;
780
- if (object_nl) {
781
- fbuffer_append(buffer, object_nl, object_nl_len);
782
- if (indent) {
783
- for (j = 0; j < depth; j++) {
784
- fbuffer_append(buffer, indent, indent_len);
785
- }
786
- }
787
- }
788
- fbuffer_append_char(buffer, '}');
789
- }
790
- break;
791
- case T_ARRAY:
792
- {
793
- char *array_nl = state->array_nl;
794
- long array_nl_len = state->array_nl_len;
795
- char *indent = state->indent;
796
- long indent_len = state->indent_len;
797
- long max_nesting = state->max_nesting;
798
- char *delim = FBUFFER_PTR(state->array_delim);
799
- long delim_len = FBUFFER_LEN(state->array_delim);
800
- int i, j;
801
- depth++;
802
- if (max_nesting != 0 && depth > max_nesting) {
803
- fbuffer_free(buffer);
804
- rb_raise(eNestingError, "nesting of %ld is too deep", depth);
805
- }
806
- fbuffer_append_char(buffer, '[');
807
- if (array_nl) fbuffer_append(buffer, array_nl, array_nl_len);
808
- for(i = 0; i < RARRAY_LEN(obj); i++) {
809
- if (i > 0) fbuffer_append(buffer, delim, delim_len);
810
- if (indent) {
811
- for (j = 0; j < depth; j++) {
812
- fbuffer_append(buffer, indent, indent_len);
813
- }
814
- }
815
- generate_json(buffer, Vstate, state, rb_ary_entry(obj, i), depth);
816
- }
817
- depth--;
818
- if (array_nl) {
819
- fbuffer_append(buffer, array_nl, array_nl_len);
820
- if (indent) {
821
- for (j = 0; j < depth; j++) {
822
- fbuffer_append(buffer, indent, indent_len);
823
- }
824
- }
825
- }
826
- fbuffer_append_char(buffer, ']');
668
+ VALUE name_writer;
669
+
670
+ name = rb_funcall(name, i_to_s, 0);
671
+ name_writer = rb_str_cat2(rb_str_dup(name), "=");
672
+ if (RTEST(rb_funcall(self, i_respond_to_p, 1, name_writer))) {
673
+ return rb_funcall(self, i_send, 2, name_writer, value);
674
+ } else {
675
+ rb_ivar_set(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)), value);
676
+ }
677
+ return Qnil;
678
+ }
679
+
680
+ static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
681
+ {
682
+ char *object_nl = state->object_nl;
683
+ long object_nl_len = state->object_nl_len;
684
+ char *indent = state->indent;
685
+ long indent_len = state->indent_len;
686
+ long max_nesting = state->max_nesting;
687
+ char *delim = FBUFFER_PTR(state->object_delim);
688
+ long delim_len = FBUFFER_LEN(state->object_delim);
689
+ char *delim2 = FBUFFER_PTR(state->object_delim2);
690
+ long delim2_len = FBUFFER_LEN(state->object_delim2);
691
+ long depth = ++state->depth;
692
+ int i, j;
693
+ VALUE key, key_to_s, keys;
694
+ if (max_nesting != 0 && depth > max_nesting) {
695
+ fbuffer_free(buffer);
696
+ rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
697
+ }
698
+ fbuffer_append_char(buffer, '{');
699
+ keys = rb_funcall(obj, i_keys, 0);
700
+ for(i = 0; i < RARRAY_LEN(keys); i++) {
701
+ if (i > 0) fbuffer_append(buffer, delim, delim_len);
702
+ if (object_nl) {
703
+ fbuffer_append(buffer, object_nl, object_nl_len);
704
+ }
705
+ if (indent) {
706
+ for (j = 0; j < depth; j++) {
707
+ fbuffer_append(buffer, indent, indent_len);
827
708
  }
828
- break;
829
- case T_STRING:
830
- fbuffer_append_char(buffer, '"');
831
- #ifdef HAVE_RUBY_ENCODING_H
832
- obj = rb_funcall(obj, i_encode, 1, CEncoding_UTF_8);
833
- #endif
834
- if (state->ascii_only) {
835
- convert_UTF8_to_JSON_ASCII(buffer, obj);
836
- } else {
837
- convert_UTF8_to_JSON(buffer, obj);
709
+ }
710
+ key = rb_ary_entry(keys, i);
711
+ key_to_s = rb_funcall(key, i_to_s, 0);
712
+ Check_Type(key_to_s, T_STRING);
713
+ generate_json(buffer, Vstate, state, key_to_s);
714
+ fbuffer_append(buffer, delim2, delim2_len);
715
+ generate_json(buffer, Vstate, state, rb_hash_aref(obj, key));
716
+ }
717
+ depth = --state->depth;
718
+ if (object_nl) {
719
+ fbuffer_append(buffer, object_nl, object_nl_len);
720
+ if (indent) {
721
+ for (j = 0; j < depth; j++) {
722
+ fbuffer_append(buffer, indent, indent_len);
838
723
  }
839
- fbuffer_append_char(buffer, '"');
840
- break;
841
- case T_NIL:
842
- fbuffer_append(buffer, "null", 4);
843
- break;
844
- case T_FALSE:
845
- fbuffer_append(buffer, "false", 5);
846
- break;
847
- case T_TRUE:
848
- fbuffer_append(buffer, "true", 4);
849
- break;
850
- case T_FIXNUM:
851
- fbuffer_append_long(buffer, FIX2LONG(obj));
852
- break;
853
- case T_BIGNUM:
854
- tmp = rb_funcall(obj, i_to_s, 0);
855
- fbuffer_append(buffer, RSTRING_PAIR(tmp));
856
- break;
857
- case T_FLOAT:
858
- {
859
- double value = RFLOAT_VALUE(obj);
860
- char allow_nan = state->allow_nan;
861
- tmp = rb_funcall(obj, i_to_s, 0);
862
- if (!allow_nan) {
863
- if (isinf(value)) {
864
- fbuffer_free(buffer);
865
- rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
866
- } else if (isnan(value)) {
867
- fbuffer_free(buffer);
868
- rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
869
- }
870
- }
871
- fbuffer_append(buffer, RSTRING_PAIR(tmp));
724
+ }
725
+ }
726
+ fbuffer_append_char(buffer, '}');
727
+ }
728
+
729
+ static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
730
+ {
731
+ char *array_nl = state->array_nl;
732
+ long array_nl_len = state->array_nl_len;
733
+ char *indent = state->indent;
734
+ long indent_len = state->indent_len;
735
+ long max_nesting = state->max_nesting;
736
+ char *delim = FBUFFER_PTR(state->array_delim);
737
+ long delim_len = FBUFFER_LEN(state->array_delim);
738
+ long depth = ++state->depth;
739
+ int i, j;
740
+ if (max_nesting != 0 && depth > max_nesting) {
741
+ fbuffer_free(buffer);
742
+ rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
743
+ }
744
+ fbuffer_append_char(buffer, '[');
745
+ if (array_nl) fbuffer_append(buffer, array_nl, array_nl_len);
746
+ for(i = 0; i < RARRAY_LEN(obj); i++) {
747
+ if (i > 0) fbuffer_append(buffer, delim, delim_len);
748
+ if (indent) {
749
+ for (j = 0; j < depth; j++) {
750
+ fbuffer_append(buffer, indent, indent_len);
872
751
  }
873
- break;
874
- default:
875
- if (rb_respond_to(obj, i_to_json)) {
876
- tmp = rb_funcall(obj, i_to_json, 2, Vstate, INT2FIX(depth + 1));
877
- Check_Type(tmp, T_STRING);
878
- fbuffer_append(buffer, RSTRING_PAIR(tmp));
879
- } else {
880
- tmp = rb_funcall(obj, i_to_s, 0);
881
- Check_Type(tmp, T_STRING);
882
- generate_json(buffer, Vstate, state, tmp, depth + 1);
752
+ }
753
+ generate_json(buffer, Vstate, state, rb_ary_entry(obj, i));
754
+ }
755
+ state->depth = --depth;
756
+ if (array_nl) {
757
+ fbuffer_append(buffer, array_nl, array_nl_len);
758
+ if (indent) {
759
+ for (j = 0; j < depth; j++) {
760
+ fbuffer_append(buffer, indent, indent_len);
883
761
  }
884
- break;
762
+ }
885
763
  }
764
+ fbuffer_append_char(buffer, ']');
886
765
  }
887
766
 
888
- /*
889
- * call-seq: partial_generate(obj)
890
- *
891
- * Generates a part of a JSON document from object +obj+ and returns the
892
- * result.
893
- */
894
- static VALUE cState_partial_generate(VALUE self, VALUE obj, VALUE depth)
767
+ static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
768
+ {
769
+ fbuffer_append_char(buffer, '"');
770
+ #ifdef HAVE_RUBY_ENCODING_H
771
+ obj = rb_funcall(obj, i_encode, 1, CEncoding_UTF_8);
772
+ #endif
773
+ if (state->ascii_only) {
774
+ convert_UTF8_to_JSON_ASCII(buffer, obj);
775
+ } else {
776
+ convert_UTF8_to_JSON(buffer, obj);
777
+ }
778
+ fbuffer_append_char(buffer, '"');
779
+ }
780
+
781
+ static void generate_json_null(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
782
+ {
783
+ fbuffer_append(buffer, "null", 4);
784
+ }
785
+
786
+ static void generate_json_false(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
787
+ {
788
+ fbuffer_append(buffer, "false", 5);
789
+ }
790
+
791
+ static void generate_json_true(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
792
+ {
793
+ fbuffer_append(buffer, "true", 4);
794
+ }
795
+
796
+ static void generate_json_fixnum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
797
+ {
798
+ fbuffer_append_long(buffer, FIX2LONG(obj));
799
+ }
800
+
801
+ static void generate_json_bignum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
802
+ {
803
+ VALUE tmp = rb_funcall(obj, i_to_s, 0);
804
+ fbuffer_append_str(buffer, tmp);
805
+ }
806
+
807
+ static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
808
+ {
809
+ double value = RFLOAT_VALUE(obj);
810
+ char allow_nan = state->allow_nan;
811
+ VALUE tmp = rb_funcall(obj, i_to_s, 0);
812
+ if (!allow_nan) {
813
+ if (isinf(value)) {
814
+ fbuffer_free(buffer);
815
+ rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
816
+ } else if (isnan(value)) {
817
+ fbuffer_free(buffer);
818
+ rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
819
+ }
820
+ }
821
+ fbuffer_append_str(buffer, tmp);
822
+ }
823
+
824
+ static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
895
825
  {
896
- VALUE result;
897
- FBuffer *buffer = fbuffer_alloc();
826
+ VALUE tmp;
827
+ VALUE klass = CLASS_OF(obj);
828
+ if (klass == rb_cHash) {
829
+ generate_json_object(buffer, Vstate, state, obj);
830
+ } else if (klass == rb_cArray) {
831
+ generate_json_array(buffer, Vstate, state, obj);
832
+ } else if (klass == rb_cString) {
833
+ generate_json_string(buffer, Vstate, state, obj);
834
+ } else if (obj == Qnil) {
835
+ generate_json_null(buffer, Vstate, state, obj);
836
+ } else if (obj == Qfalse) {
837
+ generate_json_false(buffer, Vstate, state, obj);
838
+ } else if (obj == Qtrue) {
839
+ generate_json_true(buffer, Vstate, state, obj);
840
+ } else if (klass == rb_cFixnum) {
841
+ generate_json_fixnum(buffer, Vstate, state, obj);
842
+ } else if (klass == rb_cBignum) {
843
+ generate_json_bignum(buffer, Vstate, state, obj);
844
+ } else if (klass == rb_cFloat) {
845
+ generate_json_float(buffer, Vstate, state, obj);
846
+ } else if (rb_respond_to(obj, i_to_json)) {
847
+ tmp = rb_funcall(obj, i_to_json, 1, Vstate);
848
+ Check_Type(tmp, T_STRING);
849
+ fbuffer_append_str(buffer, tmp);
850
+ } else {
851
+ tmp = rb_funcall(obj, i_to_s, 0);
852
+ Check_Type(tmp, T_STRING);
853
+ generate_json(buffer, Vstate, state, tmp);
854
+ }
855
+ }
856
+
857
+ static FBuffer *cState_prepare_buffer(VALUE self)
858
+ {
859
+ FBuffer *buffer;
898
860
  GET_STATE(self);
861
+ buffer = fbuffer_alloc(state->buffer_initial_length);
899
862
 
900
863
  if (state->object_delim) {
901
864
  fbuffer_clear(state->object_delim);
902
865
  } else {
903
- state->object_delim = fbuffer_alloc_with_length(16);
866
+ state->object_delim = fbuffer_alloc(16);
904
867
  }
905
868
  fbuffer_append_char(state->object_delim, ',');
906
869
  if (state->object_delim2) {
907
870
  fbuffer_clear(state->object_delim2);
908
871
  } else {
909
- state->object_delim2 = fbuffer_alloc_with_length(16);
872
+ state->object_delim2 = fbuffer_alloc(16);
910
873
  }
911
874
  fbuffer_append_char(state->object_delim2, ':');
912
875
  if (state->space) fbuffer_append(state->object_delim2, state->space, state->space_len);
@@ -914,16 +877,34 @@ static VALUE cState_partial_generate(VALUE self, VALUE obj, VALUE depth)
914
877
  if (state->array_delim) {
915
878
  fbuffer_clear(state->array_delim);
916
879
  } else {
917
- state->array_delim = fbuffer_alloc_with_length(16);
880
+ state->array_delim = fbuffer_alloc(16);
918
881
  }
919
882
  fbuffer_append_char(state->array_delim, ',');
920
883
  if (state->array_nl) fbuffer_append(state->array_delim, state->array_nl, state->array_nl_len);
884
+ return buffer;
885
+ }
921
886
 
922
- generate_json(buffer, self, state, obj, NIL_P(depth) ? 0 : FIX2INT(depth));
923
- result = rb_str_new(FBUFFER_PAIR(buffer));
924
- fbuffer_free(buffer);
925
- FORCE_UTF8(result);
926
- return result;
887
+ static VALUE cState_partial_generate(VALUE self, VALUE obj)
888
+ {
889
+ FBuffer *buffer = cState_prepare_buffer(self);
890
+ GET_STATE(self);
891
+ generate_json(buffer, self, state, obj);
892
+ return fbuffer_to_s(buffer);
893
+ }
894
+
895
+ /*
896
+ * This function returns true if string is either a JSON array or JSON object.
897
+ * It might suffer from false positives, e. g. syntactically incorrect JSON in
898
+ * the string or certain UTF-8 characters on the right hand side.
899
+ */
900
+ static int isArrayOrObject(VALUE string)
901
+ {
902
+ long string_len = RSTRING_LEN(string);
903
+ char *p = RSTRING_PTR(string), *q = p + string_len - 1;
904
+ if (string_len < 2) return 0;
905
+ for (; p < q && isspace((unsigned char)*p); p++);
906
+ for (; q > p && isspace((unsigned char)*q); q--);
907
+ return (*p == '[' && *q == ']') || (*p == '{' && *q == '}');
927
908
  }
928
909
 
929
910
  /*
@@ -935,12 +916,9 @@ static VALUE cState_partial_generate(VALUE self, VALUE obj, VALUE depth)
935
916
  */
936
917
  static VALUE cState_generate(VALUE self, VALUE obj)
937
918
  {
938
- VALUE result = cState_partial_generate(self, obj, Qnil);
939
- VALUE re, args[2];
940
- args[0] = rb_str_new2("\\A\\s*(?:\\[.*\\]|\\{.*\\})\\s*\\Z");
941
- args[1] = CRegexp_MULTILINE;
942
- re = rb_class_new_instance(2, args, rb_cRegexp);
943
- if (NIL_P(rb_funcall(re, i_match, 1, result))) {
919
+ VALUE result = cState_partial_generate(self, obj);
920
+ GET_STATE(self);
921
+ if (!state->quirks_mode && !isArrayOrObject(result)) {
944
922
  rb_raise(eGeneratorError, "only generation of JSON objects or arrays allowed");
945
923
  }
946
924
  return result;
@@ -956,18 +934,22 @@ static VALUE cState_generate(VALUE self, VALUE obj)
956
934
  * * *indent*: a string used to indent levels (default: ''),
957
935
  * * *space*: a string that is put after, a : or , delimiter (default: ''),
958
936
  * * *space_before*: a string that is put before a : pair delimiter (default: ''),
959
- * * *object_nl*: a string that is put at the end of a JSON object (default: ''),
937
+ * * *object_nl*: a string that is put at the end of a JSON object (default: ''),
960
938
  * * *array_nl*: a string that is put at the end of a JSON array (default: ''),
961
939
  * * *allow_nan*: true if NaN, Infinity, and -Infinity should be
962
940
  * generated, otherwise an exception is thrown, if these values are
963
941
  * encountered. This options defaults to false.
942
+ * * *quirks_mode*: Enables quirks_mode for parser, that is for example
943
+ * generating single JSON values instead of documents is possible.
944
+ * * *buffer_initial_length*: sets the initial length of the generator's
945
+ * internal buffer.
964
946
  */
965
947
  static VALUE cState_initialize(int argc, VALUE *argv, VALUE self)
966
948
  {
967
949
  VALUE opts;
968
950
  GET_STATE(self);
969
- MEMZERO(state, JSON_Generator_State, 1);
970
- state->max_nesting = 19;
951
+ state->max_nesting = 100;
952
+ state->buffer_initial_length = FBUFFER_INITIAL_LENGTH_DEFAULT;
971
953
  rb_scan_args(argc, argv, "01", &opts);
972
954
  if (!NIL_P(opts)) cState_configure(self, opts);
973
955
  return self;
@@ -1014,9 +996,9 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts)
1014
996
  return rb_funcall(self, i_new, 1, opts);
1015
997
  } else {
1016
998
  if (NIL_P(CJSON_SAFE_STATE_PROTOTYPE)) {
1017
- CJSON_SAFE_STATE_PROTOTYPE = rb_const_get(mJSON, rb_intern("SAFE_STATE_PROTOTYPE"));
999
+ CJSON_SAFE_STATE_PROTOTYPE = rb_const_get(mJSON, i_SAFE_STATE_PROTOTYPE);
1018
1000
  }
1019
- return CJSON_SAFE_STATE_PROTOTYPE;
1001
+ return rb_funcall(CJSON_SAFE_STATE_PROTOTYPE, i_dup, 0);
1020
1002
  }
1021
1003
  }
1022
1004
 
@@ -1028,7 +1010,7 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts)
1028
1010
  static VALUE cState_indent(VALUE self)
1029
1011
  {
1030
1012
  GET_STATE(self);
1031
- return state->indent ? rb_str_new2(state->indent) : rb_str_new2("");
1013
+ return state->indent ? rb_str_new(state->indent, state->indent_len) : rb_str_new2("");
1032
1014
  }
1033
1015
 
1034
1016
  /*
@@ -1038,16 +1020,20 @@ static VALUE cState_indent(VALUE self)
1038
1020
  */
1039
1021
  static VALUE cState_indent_set(VALUE self, VALUE indent)
1040
1022
  {
1023
+ unsigned long len;
1041
1024
  GET_STATE(self);
1042
1025
  Check_Type(indent, T_STRING);
1043
- if (RSTRING_LEN(indent) == 0) {
1026
+ len = RSTRING_LEN(indent);
1027
+ if (len == 0) {
1044
1028
  if (state->indent) {
1045
1029
  ruby_xfree(state->indent);
1046
1030
  state->indent = NULL;
1031
+ state->indent_len = 0;
1047
1032
  }
1048
1033
  } else {
1049
1034
  if (state->indent) ruby_xfree(state->indent);
1050
1035
  state->indent = strdup(RSTRING_PTR(indent));
1036
+ state->indent_len = len;
1051
1037
  }
1052
1038
  return Qnil;
1053
1039
  }
@@ -1061,7 +1047,7 @@ static VALUE cState_indent_set(VALUE self, VALUE indent)
1061
1047
  static VALUE cState_space(VALUE self)
1062
1048
  {
1063
1049
  GET_STATE(self);
1064
- return state->space ? rb_str_new2(state->space) : rb_str_new2("");
1050
+ return state->space ? rb_str_new(state->space, state->space_len) : rb_str_new2("");
1065
1051
  }
1066
1052
 
1067
1053
  /*
@@ -1072,16 +1058,20 @@ static VALUE cState_space(VALUE self)
1072
1058
  */
1073
1059
  static VALUE cState_space_set(VALUE self, VALUE space)
1074
1060
  {
1061
+ unsigned long len;
1075
1062
  GET_STATE(self);
1076
1063
  Check_Type(space, T_STRING);
1077
- if (RSTRING_LEN(space) == 0) {
1064
+ len = RSTRING_LEN(space);
1065
+ if (len == 0) {
1078
1066
  if (state->space) {
1079
1067
  ruby_xfree(state->space);
1080
1068
  state->space = NULL;
1069
+ state->space_len = 0;
1081
1070
  }
1082
1071
  } else {
1083
1072
  if (state->space) ruby_xfree(state->space);
1084
1073
  state->space = strdup(RSTRING_PTR(space));
1074
+ state->space_len = len;
1085
1075
  }
1086
1076
  return Qnil;
1087
1077
  }
@@ -1094,7 +1084,7 @@ static VALUE cState_space_set(VALUE self, VALUE space)
1094
1084
  static VALUE cState_space_before(VALUE self)
1095
1085
  {
1096
1086
  GET_STATE(self);
1097
- return state->space_before ? rb_str_new2(state->space_before) : rb_str_new2("");
1087
+ return state->space_before ? rb_str_new(state->space_before, state->space_before_len) : rb_str_new2("");
1098
1088
  }
1099
1089
 
1100
1090
  /*
@@ -1104,16 +1094,20 @@ static VALUE cState_space_before(VALUE self)
1104
1094
  */
1105
1095
  static VALUE cState_space_before_set(VALUE self, VALUE space_before)
1106
1096
  {
1097
+ unsigned long len;
1107
1098
  GET_STATE(self);
1108
1099
  Check_Type(space_before, T_STRING);
1109
- if (RSTRING_LEN(space_before) == 0) {
1100
+ len = RSTRING_LEN(space_before);
1101
+ if (len == 0) {
1110
1102
  if (state->space_before) {
1111
1103
  ruby_xfree(state->space_before);
1112
1104
  state->space_before = NULL;
1105
+ state->space_before_len = 0;
1113
1106
  }
1114
1107
  } else {
1115
1108
  if (state->space_before) ruby_xfree(state->space_before);
1116
1109
  state->space_before = strdup(RSTRING_PTR(space_before));
1110
+ state->space_before_len = len;
1117
1111
  }
1118
1112
  return Qnil;
1119
1113
  }
@@ -1127,7 +1121,7 @@ static VALUE cState_space_before_set(VALUE self, VALUE space_before)
1127
1121
  static VALUE cState_object_nl(VALUE self)
1128
1122
  {
1129
1123
  GET_STATE(self);
1130
- return state->object_nl ? rb_str_new2(state->object_nl) : rb_str_new2("");
1124
+ return state->object_nl ? rb_str_new(state->object_nl, state->object_nl_len) : rb_str_new2("");
1131
1125
  }
1132
1126
 
1133
1127
  /*
@@ -1138,9 +1132,11 @@ static VALUE cState_object_nl(VALUE self)
1138
1132
  */
1139
1133
  static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
1140
1134
  {
1135
+ unsigned long len;
1141
1136
  GET_STATE(self);
1142
1137
  Check_Type(object_nl, T_STRING);
1143
- if (RSTRING_LEN(object_nl) == 0) {
1138
+ len = RSTRING_LEN(object_nl);
1139
+ if (len == 0) {
1144
1140
  if (state->object_nl) {
1145
1141
  ruby_xfree(state->object_nl);
1146
1142
  state->object_nl = NULL;
@@ -1148,6 +1144,7 @@ static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
1148
1144
  } else {
1149
1145
  if (state->object_nl) ruby_xfree(state->object_nl);
1150
1146
  state->object_nl = strdup(RSTRING_PTR(object_nl));
1147
+ state->object_nl_len = len;
1151
1148
  }
1152
1149
  return Qnil;
1153
1150
  }
@@ -1160,7 +1157,7 @@ static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
1160
1157
  static VALUE cState_array_nl(VALUE self)
1161
1158
  {
1162
1159
  GET_STATE(self);
1163
- return state->array_nl ? rb_str_new2(state->array_nl) : rb_str_new2("");
1160
+ return state->array_nl ? rb_str_new(state->array_nl, state->array_nl_len) : rb_str_new2("");
1164
1161
  }
1165
1162
 
1166
1163
  /*
@@ -1170,9 +1167,11 @@ static VALUE cState_array_nl(VALUE self)
1170
1167
  */
1171
1168
  static VALUE cState_array_nl_set(VALUE self, VALUE array_nl)
1172
1169
  {
1170
+ unsigned long len;
1173
1171
  GET_STATE(self);
1174
1172
  Check_Type(array_nl, T_STRING);
1175
- if (RSTRING_LEN(array_nl) == 0) {
1173
+ len = RSTRING_LEN(array_nl);
1174
+ if (len == 0) {
1176
1175
  if (state->array_nl) {
1177
1176
  ruby_xfree(state->array_nl);
1178
1177
  state->array_nl = NULL;
@@ -1180,6 +1179,7 @@ static VALUE cState_array_nl_set(VALUE self, VALUE array_nl)
1180
1179
  } else {
1181
1180
  if (state->array_nl) ruby_xfree(state->array_nl);
1182
1181
  state->array_nl = strdup(RSTRING_PTR(array_nl));
1182
+ state->array_nl_len = len;
1183
1183
  }
1184
1184
  return Qnil;
1185
1185
  }
@@ -1246,6 +1246,83 @@ static VALUE cState_ascii_only_p(VALUE self)
1246
1246
  return state->ascii_only ? Qtrue : Qfalse;
1247
1247
  }
1248
1248
 
1249
+ /*
1250
+ * call-seq: quirks_mode?
1251
+ *
1252
+ * Returns true, if quirks mode is enabled. Otherwise returns false.
1253
+ */
1254
+ static VALUE cState_quirks_mode_p(VALUE self)
1255
+ {
1256
+ GET_STATE(self);
1257
+ return state->quirks_mode ? Qtrue : Qfalse;
1258
+ }
1259
+
1260
+ /*
1261
+ * call-seq: quirks_mode=(enable)
1262
+ *
1263
+ * If set to true, enables the quirks_mode mode.
1264
+ */
1265
+ static VALUE cState_quirks_mode_set(VALUE self, VALUE enable)
1266
+ {
1267
+ GET_STATE(self);
1268
+ state->quirks_mode = RTEST(enable);
1269
+ return Qnil;
1270
+ }
1271
+
1272
+ /*
1273
+ * call-seq: depth
1274
+ *
1275
+ * This integer returns the current depth of data structure nesting.
1276
+ */
1277
+ static VALUE cState_depth(VALUE self)
1278
+ {
1279
+ GET_STATE(self);
1280
+ return LONG2FIX(state->depth);
1281
+ }
1282
+
1283
+ /*
1284
+ * call-seq: depth=(depth)
1285
+ *
1286
+ * This sets the maximum level of data structure nesting in the generated JSON
1287
+ * to the integer depth, max_nesting = 0 if no maximum should be checked.
1288
+ */
1289
+ static VALUE cState_depth_set(VALUE self, VALUE depth)
1290
+ {
1291
+ GET_STATE(self);
1292
+ Check_Type(depth, T_FIXNUM);
1293
+ state->depth = FIX2LONG(depth);
1294
+ return Qnil;
1295
+ }
1296
+
1297
+ /*
1298
+ * call-seq: buffer_initial_length
1299
+ *
1300
+ * This integer returns the current inital length of the buffer.
1301
+ */
1302
+ static VALUE cState_buffer_initial_length(VALUE self)
1303
+ {
1304
+ GET_STATE(self);
1305
+ return LONG2FIX(state->buffer_initial_length);
1306
+ }
1307
+
1308
+ /*
1309
+ * call-seq: buffer_initial_length=(length)
1310
+ *
1311
+ * This sets the initial length of the buffer to +length+, if +length+ > 0,
1312
+ * otherwise its value isn't changed.
1313
+ */
1314
+ static VALUE cState_buffer_initial_length_set(VALUE self, VALUE buffer_initial_length)
1315
+ {
1316
+ long initial_length;
1317
+ GET_STATE(self);
1318
+ Check_Type(buffer_initial_length, T_FIXNUM);
1319
+ initial_length = FIX2LONG(buffer_initial_length);
1320
+ if (initial_length > 0) {
1321
+ state->buffer_initial_length = initial_length;
1322
+ }
1323
+ return Qnil;
1324
+ }
1325
+
1249
1326
  /*
1250
1327
  *
1251
1328
  */
@@ -1280,11 +1357,20 @@ void Init_generator()
1280
1357
  rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
1281
1358
  rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
1282
1359
  rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
1360
+ rb_define_method(cState, "quirks_mode?", cState_quirks_mode_p, 0);
1361
+ rb_define_method(cState, "quirks_mode", cState_quirks_mode_p, 0);
1362
+ rb_define_method(cState, "quirks_mode=", cState_quirks_mode_set, 1);
1363
+ rb_define_method(cState, "depth", cState_depth, 0);
1364
+ rb_define_method(cState, "depth=", cState_depth_set, 1);
1365
+ rb_define_method(cState, "buffer_initial_length", cState_buffer_initial_length, 0);
1366
+ rb_define_method(cState, "buffer_initial_length=", cState_buffer_initial_length_set, 1);
1283
1367
  rb_define_method(cState, "configure", cState_configure, 1);
1368
+ rb_define_alias(cState, "merge", "configure");
1284
1369
  rb_define_method(cState, "to_h", cState_to_h, 0);
1370
+ rb_define_alias(cState, "to_hash", "to_h");
1285
1371
  rb_define_method(cState, "[]", cState_aref, 1);
1372
+ rb_define_method(cState, "[]=", cState_aset, 2);
1286
1373
  rb_define_method(cState, "generate", cState_generate, 1);
1287
- rb_define_method(cState, "partial_generate", cState_partial_generate, 1);
1288
1374
 
1289
1375
  mGeneratorMethods = rb_define_module_under(mGenerator, "GeneratorMethods");
1290
1376
  mObject = rb_define_module_under(mGeneratorMethods, "Object");
@@ -1293,8 +1379,10 @@ void Init_generator()
1293
1379
  rb_define_method(mHash, "to_json", mHash_to_json, -1);
1294
1380
  mArray = rb_define_module_under(mGeneratorMethods, "Array");
1295
1381
  rb_define_method(mArray, "to_json", mArray_to_json, -1);
1296
- mInteger = rb_define_module_under(mGeneratorMethods, "Integer");
1297
- rb_define_method(mInteger, "to_json", mInteger_to_json, -1);
1382
+ mFixnum = rb_define_module_under(mGeneratorMethods, "Fixnum");
1383
+ rb_define_method(mFixnum, "to_json", mFixnum_to_json, -1);
1384
+ mBignum = rb_define_module_under(mGeneratorMethods, "Bignum");
1385
+ rb_define_method(mBignum, "to_json", mBignum_to_json, -1);
1298
1386
  mFloat = rb_define_module_under(mGeneratorMethods, "Float");
1299
1387
  rb_define_method(mFloat, "to_json", mFloat_to_json, -1);
1300
1388
  mString = rb_define_module_under(mGeneratorMethods, "String");
@@ -1323,6 +1411,9 @@ void Init_generator()
1323
1411
  i_max_nesting = rb_intern("max_nesting");
1324
1412
  i_allow_nan = rb_intern("allow_nan");
1325
1413
  i_ascii_only = rb_intern("ascii_only");
1414
+ i_quirks_mode = rb_intern("quirks_mode");
1415
+ i_depth = rb_intern("depth");
1416
+ i_buffer_initial_length = rb_intern("buffer_initial_length");
1326
1417
  i_pack = rb_intern("pack");
1327
1418
  i_unpack = rb_intern("unpack");
1328
1419
  i_create_id = rb_intern("create_id");
@@ -1332,10 +1423,13 @@ void Init_generator()
1332
1423
  i_send = rb_intern("__send__");
1333
1424
  i_respond_to_p = rb_intern("respond_to?");
1334
1425
  i_match = rb_intern("match");
1426
+ i_keys = rb_intern("keys");
1427
+ i_dup = rb_intern("dup");
1335
1428
  #ifdef HAVE_RUBY_ENCODING_H
1336
1429
  CEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8"));
1337
1430
  i_encoding = rb_intern("encoding");
1338
1431
  i_encode = rb_intern("encode");
1339
1432
  #endif
1433
+ i_SAFE_STATE_PROTOTYPE = rb_intern("SAFE_STATE_PROTOTYPE");
1340
1434
  CJSON_SAFE_STATE_PROTOTYPE = Qnil;
1341
1435
  }