json_pure 1.1.3 → 1.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/CHANGES +9 -0
  2. data/Rakefile +47 -53
  3. data/VERSION +1 -1
  4. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkComparison.log +52 -0
  5. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast-autocorrelation.dat +1000 -0
  6. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast.dat +1001 -0
  7. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty-autocorrelation.dat +900 -0
  8. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty.dat +901 -0
  9. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe-autocorrelation.dat +1000 -0
  10. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe.dat +1001 -0
  11. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt.log +261 -0
  12. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast-autocorrelation.dat +1000 -0
  13. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast.dat +1001 -0
  14. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty-autocorrelation.dat +1000 -0
  15. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty.dat +1001 -0
  16. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe-autocorrelation.dat +1000 -0
  17. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe.dat +1001 -0
  18. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure.log +262 -0
  19. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator-autocorrelation.dat +1000 -0
  20. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator.dat +1001 -0
  21. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails.log +82 -0
  22. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkComparison.log +34 -0
  23. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser-autocorrelation.dat +900 -0
  24. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser.dat +901 -0
  25. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt.log +81 -0
  26. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser-autocorrelation.dat +1000 -0
  27. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser.dat +1001 -0
  28. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure.log +82 -0
  29. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser-autocorrelation.dat +1000 -0
  30. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser.dat +1001 -0
  31. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails.log +82 -0
  32. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser-autocorrelation.dat +1000 -0
  33. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser.dat +1001 -0
  34. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML.log +82 -0
  35. data/benchmarks/generator_benchmark.rb +162 -0
  36. data/benchmarks/parser_benchmark.rb +193 -0
  37. data/bin/edit_json.rb +0 -1
  38. data/bin/prettify_json.rb +0 -1
  39. data/doc-templates/main.txt +284 -0
  40. data/ext/json/ext/generator/extconf.rb +2 -0
  41. data/ext/json/ext/generator/generator.c +62 -18
  42. data/ext/json/ext/parser/extconf.rb +2 -0
  43. data/ext/json/ext/parser/parser.c +128 -81
  44. data/ext/json/ext/parser/parser.rl +31 -7
  45. data/ext/json/ext/parser/unicode.c +4 -4
  46. data/lib/json/add/core.rb +1 -1
  47. data/lib/json/editor.rb +11 -2
  48. data/lib/json/ext.rb +2 -0
  49. data/lib/json/pure/generator.rb +77 -41
  50. data/lib/json/pure/parser.rb +6 -2
  51. data/lib/json/pure.rb +2 -0
  52. data/lib/json/version.rb +1 -1
  53. data/lib/json.rb +0 -221
  54. data/tests/test_json.rb +7 -4
  55. data/tests/test_json_addition.rb +8 -5
  56. data/tests/test_json_fixtures.rb +6 -2
  57. data/tests/test_json_generate.rb +8 -2
  58. data/tests/test_json_rails.rb +30 -2
  59. data/tests/test_json_unicode.rb +8 -7
  60. data/tools/fuzz.rb +0 -1
  61. data/tools/server.rb +0 -1
  62. metadata +46 -9
  63. data/benchmarks/benchmark.txt +0 -133
  64. data/benchmarks/benchmark_generator.rb +0 -48
  65. data/benchmarks/benchmark_parser.rb +0 -26
  66. data/benchmarks/benchmark_rails.rb +0 -26
  67. data/tests/runner.rb +0 -25
@@ -0,0 +1,284 @@
1
+ # = json - JSON for Ruby
2
+ #
3
+ # == Description
4
+ #
5
+ # This is a implementation of the JSON specification according to RFC 4627
6
+ # (http://www.ietf.org/rfc/rfc4627.txt). Starting from version 1.0.0 on there
7
+ # will be two variants available:
8
+ #
9
+ # * A pure ruby variant, that relies on the iconv and the stringscan
10
+ # extensions, which are both part of the ruby standard library.
11
+ # * The quite a bit faster C extension variant, which is in parts implemented
12
+ # in C and comes with its own unicode conversion functions and a parser
13
+ # generated by the ragel state machine compiler
14
+ # (http://www.cs.queensu.ca/~thurston/ragel).
15
+ #
16
+ # Both variants of the JSON generator escape all non-ASCII an control
17
+ # characters with \uXXXX escape sequences, and support UTF-16 surrogate pairs
18
+ # in order to be able to generate the whole range of unicode code points. This
19
+ # means that generated JSON text is encoded as UTF-8 (because ASCII is a subset
20
+ # of UTF-8) and at the same time avoids decoding problems for receiving
21
+ # endpoints, that don't expect UTF-8 encoded texts. On the negative side this
22
+ # may lead to a bit longer strings than necessarry.
23
+ #
24
+ # All strings, that are to be encoded as JSON strings, should be UTF-8 byte
25
+ # sequences on the Ruby side. To encode raw binary strings, that aren't UTF-8
26
+ # encoded, please use the to_json_raw_object method of String (which produces
27
+ # an object, that contains a byte array) and decode the result on the receiving
28
+ # endpoint.
29
+ #
30
+ # == Author
31
+ #
32
+ # Florian Frank <mailto:flori@ping.de>
33
+ #
34
+ # == License
35
+ #
36
+ # This software is distributed under the same license as Ruby itself, see
37
+ # http://www.ruby-lang.org/en/LICENSE.txt.
38
+ #
39
+ # == Download
40
+ #
41
+ # The latest version of this library can be downloaded at
42
+ #
43
+ # * http://rubyforge.org/frs?group_id=953
44
+ #
45
+ # Online Documentation should be located at
46
+ #
47
+ # * http://json.rubyforge.org
48
+ #
49
+ # == Usage
50
+ #
51
+ # To use JSON you can
52
+ # require 'json'
53
+ # to load the installed variant (either the extension 'json' or the pure
54
+ # variant 'json_pure'). If you have installed the extension variant, you can
55
+ # pick either the extension variant or the pure variant by typing
56
+ # require 'json/ext'
57
+ # or
58
+ # require 'json/pure'
59
+ #
60
+ # You can choose to load a set of common additions to ruby core's objects if
61
+ # you
62
+ # require 'json/add/core'
63
+ #
64
+ # After requiring this you can, e. g., serialise/deserialise Ruby ranges:
65
+ #
66
+ # JSON JSON(1..10) # => 1..10
67
+ #
68
+ # To find out how to add JSON support to other or your own classes, read the
69
+ # Examples section below.
70
+ #
71
+ # To get the best compatibility to rails' JSON implementation, you can
72
+ # require 'json/add/rails'
73
+ #
74
+ # Both of the additions attempt to require 'json' (like above) first, if it has
75
+ # not been required yet.
76
+ #
77
+ # == Speed Comparisons
78
+ #
79
+ # I have created some benchmark results on on ruby 1.8.6 (2008-08-11
80
+ # patchlevel 287) [i686-linux] (see the benchmarks/data-p4-3Ghz-ruby18
81
+ # subdir of the package) for the JSON-parser to estimate the speed up in the C
82
+ # extension:
83
+ #
84
+ # Comparing times (call_time_mean):
85
+ # 1 ParserBenchmarkExt#parser 900 repeats:
86
+ # 553.922304770 ( real) -> 21.500x
87
+ # 0.001805307
88
+ # 2 ParserBenchmarkYAML#parser 1000 repeats:
89
+ # 224.513358139 ( real) -> 8.714x
90
+ # 0.004454078
91
+ # 3 ParserBenchmarkPure#parser 1000 repeats:
92
+ # 26.755020642 ( real) -> 1.038x
93
+ # 0.037376163
94
+ # 4 ParserBenchmarkRails#parser 1000 repeats:
95
+ # 25.763381731 ( real) -> 1.000x
96
+ # 0.038814780
97
+ # calls/sec ( time) -> speed covers
98
+ # secs/call
99
+ #
100
+ # In the table above 1 is JSON::Ext::Parser, 2 is YAML.load with YAML
101
+ # compatbile JSON document, 3 is is JSON::Pure::Parser, and 4 is
102
+ # ActiveSupport::JSON.decode. The ActiveSupport JSON-decoder converts the
103
+ # input first to YAML and then uses the YAML-parser, the conversion seems to
104
+ # slow it down so much that it is only as fast as the JSON::Pure::Parser!
105
+ #
106
+ # If you look at the benchmark data you can see that this is mostly caused by
107
+ # the frequent high outliers - the median of the Rails-parser runs is still
108
+ # overall smaller than the median of the JSON::Pure::Parser runs:
109
+ #
110
+ # Comparing times (call_time_median):
111
+ # 1 ParserBenchmarkExt#parser 900 repeats:
112
+ # 800.592479481 ( real) -> 26.936x
113
+ # 0.001249075
114
+ # 2 ParserBenchmarkYAML#parser 1000 repeats:
115
+ # 271.002390644 ( real) -> 9.118x
116
+ # 0.003690004
117
+ # 3 ParserBenchmarkRails#parser 1000 repeats:
118
+ # 30.227910865 ( real) -> 1.017x
119
+ # 0.033082008
120
+ # 4 ParserBenchmarkPure#parser 1000 repeats:
121
+ # 29.722384421 ( real) -> 1.000x
122
+ # 0.033644676
123
+ # calls/sec ( time) -> speed covers
124
+ # secs/call
125
+ #
126
+ # I have benchmarked the JSON-Generator as well. This generated a few more
127
+ # values, because there are different modes that also influence the achieved
128
+ # speed:
129
+ #
130
+ # Comparing times (call_time_mean):
131
+ # 1 GeneratorBenchmarkExt#generator_fast 1000 repeats:
132
+ # 547.354332608 ( real) -> 15.090x
133
+ # 0.001826970
134
+ # 2 GeneratorBenchmarkExt#generator_safe 1000 repeats:
135
+ # 443.968212317 ( real) -> 12.240x
136
+ # 0.002252414
137
+ # 3 GeneratorBenchmarkExt#generator_pretty 900 repeats:
138
+ # 375.104545883 ( real) -> 10.341x
139
+ # 0.002665923
140
+ # 4 GeneratorBenchmarkPure#generator_fast 1000 repeats:
141
+ # 49.978706968 ( real) -> 1.378x
142
+ # 0.020008521
143
+ # 5 GeneratorBenchmarkRails#generator 1000 repeats:
144
+ # 38.531868759 ( real) -> 1.062x
145
+ # 0.025952543
146
+ # 6 GeneratorBenchmarkPure#generator_safe 1000 repeats:
147
+ # 36.927649925 ( real) -> 1.018x 7 (>=3859)
148
+ # 0.027079979
149
+ # 7 GeneratorBenchmarkPure#generator_pretty 1000 repeats:
150
+ # 36.272134441 ( real) -> 1.000x 6 (>=3859)
151
+ # 0.027569373
152
+ # calls/sec ( time) -> speed covers
153
+ # secs/call
154
+ #
155
+ # In the table above 1-3 are JSON::Ext::Generator methods. 4, 6, and 7 are
156
+ # JSON::Pure::Generator methods and 5 is the Rails JSON generator. It is now a
157
+ # bit faster than the generator_safe and generator_pretty methods of the pure
158
+ # variant but slower than the others.
159
+ #
160
+ # To achieve the fastest JSON text output, you can use the fast_generate
161
+ # method. Beware, that this will disable the checking for circular Ruby data
162
+ # structures, which may cause JSON to go into an infinite loop.
163
+ #
164
+ # Here are the median comparisons for completeness' sake:
165
+ #
166
+ # Comparing times (call_time_median):
167
+ # 1 GeneratorBenchmarkExt#generator_fast 1000 repeats:
168
+ # 708.258020939 ( real) -> 16.547x
169
+ # 0.001411915
170
+ # 2 GeneratorBenchmarkExt#generator_safe 1000 repeats:
171
+ # 569.105020353 ( real) -> 13.296x
172
+ # 0.001757145
173
+ # 3 GeneratorBenchmarkExt#generator_pretty 900 repeats:
174
+ # 482.825371244 ( real) -> 11.280x
175
+ # 0.002071142
176
+ # 4 GeneratorBenchmarkPure#generator_fast 1000 repeats:
177
+ # 62.717626652 ( real) -> 1.465x
178
+ # 0.015944481
179
+ # 5 GeneratorBenchmarkRails#generator 1000 repeats:
180
+ # 43.965681162 ( real) -> 1.027x
181
+ # 0.022745013
182
+ # 6 GeneratorBenchmarkPure#generator_safe 1000 repeats:
183
+ # 43.929073409 ( real) -> 1.026x 7 (>=3859)
184
+ # 0.022763968
185
+ # 7 GeneratorBenchmarkPure#generator_pretty 1000 repeats:
186
+ # 42.802514491 ( real) -> 1.000x 6 (>=3859)
187
+ # 0.023363113
188
+ # calls/sec ( time) -> speed covers
189
+ # secs/call
190
+ #
191
+ # == Examples
192
+ #
193
+ # To create a JSON text from a ruby data structure, you can call JSON.generate
194
+ # like that:
195
+ #
196
+ # json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
197
+ # # => "[1,2,{\"a\":3.141},false,true,null,\"4..10\"]"
198
+ #
199
+ # To create a valid JSON text you have to make sure, that the output is
200
+ # embedded in either a JSON array [] or a JSON object {}. The easiest way to do
201
+ # this, is by putting your values in a Ruby Array or Hash instance.
202
+ #
203
+ # To get back a ruby data structure from a JSON text, you have to call
204
+ # JSON.parse on it:
205
+ #
206
+ # JSON.parse json
207
+ # # => [1, 2, {"a"=>3.141}, false, true, nil, "4..10"]
208
+ #
209
+ # Note, that the range from the original data structure is a simple
210
+ # string now. The reason for this is, that JSON doesn't support ranges
211
+ # or arbitrary classes. In this case the json library falls back to call
212
+ # Object#to_json, which is the same as #to_s.to_json.
213
+ #
214
+ # It's possible to add JSON support serialization to arbitrary classes by
215
+ # simply implementing a more specialized version of the #to_json method, that
216
+ # should return a JSON object (a hash converted to JSON with #to_json) like
217
+ # this (don't forget the *a for all the arguments):
218
+ #
219
+ # class Range
220
+ # def to_json(*a)
221
+ # {
222
+ # 'json_class' => self.class.name, # = 'Range'
223
+ # 'data' => [ first, last, exclude_end? ]
224
+ # }.to_json(*a)
225
+ # end
226
+ # end
227
+ #
228
+ # The hash key 'json_class' is the class, that will be asked to deserialise the
229
+ # JSON representation later. In this case it's 'Range', but any namespace of
230
+ # the form 'A::B' or '::A::B' will do. All other keys are arbitrary and can be
231
+ # used to store the necessary data to configure the object to be deserialised.
232
+ #
233
+ # If a the key 'json_class' is found in a JSON object, the JSON parser checks
234
+ # if the given class responds to the json_create class method. If so, it is
235
+ # called with the JSON object converted to a Ruby hash. So a range can
236
+ # be deserialised by implementing Range.json_create like this:
237
+ #
238
+ # class Range
239
+ # def self.json_create(o)
240
+ # new(*o['data'])
241
+ # end
242
+ # end
243
+ #
244
+ # Now it possible to serialise/deserialise ranges as well:
245
+ #
246
+ # json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
247
+ # # => "[1,2,{\"a\":3.141},false,true,null,{\"json_class\":\"Range\",\"data\":[4,10,false]}]"
248
+ # JSON.parse json
249
+ # # => [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
250
+ #
251
+ # JSON.generate always creates the shortest possible string representation of a
252
+ # ruby data structure in one line. This good for data storage or network
253
+ # protocols, but not so good for humans to read. Fortunately there's also
254
+ # JSON.pretty_generate (or JSON.pretty_generate) that creates a more
255
+ # readable output:
256
+ #
257
+ # puts JSON.pretty_generate([1, 2, {"a"=>3.141}, false, true, nil, 4..10])
258
+ # [
259
+ # 1,
260
+ # 2,
261
+ # {
262
+ # "a": 3.141
263
+ # },
264
+ # false,
265
+ # true,
266
+ # null,
267
+ # {
268
+ # "json_class": "Range",
269
+ # "data": [
270
+ # 4,
271
+ # 10,
272
+ # false
273
+ # ]
274
+ # }
275
+ # ]
276
+ #
277
+ # There are also the methods Kernel#j for generate, and Kernel#jj for
278
+ # pretty_generate output to the console, that work analogous to Core Ruby's p
279
+ # and the pp library's pp methods.
280
+ #
281
+ # The script tools/server.rb contains a small example if you want to test, how
282
+ # receiving a JSON object from a webrick server in your browser with the
283
+ # javasript prototype library (http://www.prototypejs.org) works.
284
+ #
@@ -6,4 +6,6 @@ if CONFIG['CC'] =~ /gcc/
6
6
  #$CFLAGS += ' -O0 -ggdb'
7
7
  end
8
8
 
9
+ have_header("ruby/st.h") || have_header("st.h")
10
+ have_header("ruby/encoding.h")
9
11
  create_makefile 'generator'
@@ -1,9 +1,33 @@
1
1
  #include <string.h>
2
2
  #include "ruby.h"
3
+ #if HAVE_RUBY_ST_H
4
+ #include "ruby/st.h"
5
+ #endif
6
+ #if HAVE_ST_H
3
7
  #include "st.h"
8
+ #endif
4
9
  #include "unicode.h"
5
10
  #include <math.h>
6
11
 
12
+ #ifndef RHASH_TBL
13
+ #define RHASH_TBL(hsh) (RHASH(hsh)->tbl)
14
+ #endif
15
+
16
+ #ifndef RHASH_SIZE
17
+ #define RHASH_SIZE(hsh) (RHASH(hsh)->tbl->num_entries)
18
+ #endif
19
+
20
+ #ifndef RFLOAT_VALUE
21
+ #define RFLOAT_VALUE(val) (RFLOAT(val)->value)
22
+ #endif
23
+
24
+ #ifdef HAVE_RUBY_ENCODING_H
25
+ #include "ruby/encoding.h"
26
+ #define FORCE_UTF8(obj) rb_enc_associate((obj), rb_utf8_encoding())
27
+ #else
28
+ #define FORCE_UTF8(obj)
29
+ #endif
30
+
7
31
  #define check_max_nesting(state, depth) do { \
8
32
  long current_nesting = 1 + depth; \
9
33
  if (state->max_nesting != 0 && current_nesting > state->max_nesting) \
@@ -86,7 +110,7 @@ static int hash_to_json_state_i(VALUE key, VALUE value, VALUE Vstate)
86
110
  }
87
111
 
88
112
  inline static VALUE mHash_json_transfrom(VALUE self, VALUE Vstate, VALUE Vdepth) {
89
- long depth, len = RHASH(self)->tbl->num_entries;
113
+ long depth, len = RHASH_SIZE(self);
90
114
  VALUE result;
91
115
  GET_STATE(Vstate);
92
116
 
@@ -142,7 +166,7 @@ static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
142
166
  rb_scan_args(argc, argv, "02", &Vstate, &Vdepth);
143
167
  depth = NIL_P(Vdepth) ? 0 : FIX2LONG(Vdepth);
144
168
  if (NIL_P(Vstate)) {
145
- long len = RHASH(self)->tbl->num_entries;
169
+ long len = RHASH_SIZE(self);
146
170
  result = rb_str_buf_new(len);
147
171
  rb_str_buf_cat2(result, "{");
148
172
  rb_hash_foreach(self, hash_to_json_i, result);
@@ -164,6 +188,7 @@ static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
164
188
  }
165
189
  }
166
190
  OBJ_INFECT(result, self);
191
+ FORCE_UTF8(result);
167
192
  return result;
168
193
  }
169
194
 
@@ -261,6 +286,7 @@ static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
261
286
  result = mArray_json_transfrom(self, Vstate, Vdepth);
262
287
  }
263
288
  OBJ_INFECT(result, self);
289
+ FORCE_UTF8(result);
264
290
  return result;
265
291
  }
266
292
 
@@ -271,7 +297,9 @@ static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
271
297
  */
272
298
  static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
273
299
  {
274
- return rb_funcall(self, i_to_s, 0);
300
+ VALUE result = rb_funcall(self, i_to_s, 0);
301
+ FORCE_UTF8(result);
302
+ return result;
275
303
  }
276
304
 
277
305
  /*
@@ -282,27 +310,29 @@ static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
282
310
  static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
283
311
  {
284
312
  JSON_Generator_State *state = NULL;
285
- VALUE Vstate, rest, tmp;
286
- double value = RFLOAT(self)->value;
313
+ VALUE Vstate, rest, tmp, result;
314
+ double value = RFLOAT_VALUE(self);
287
315
  rb_scan_args(argc, argv, "01*", &Vstate, &rest);
288
316
  if (!NIL_P(Vstate)) Data_Get_Struct(Vstate, JSON_Generator_State, state);
289
317
  if (isinf(value)) {
290
318
  if (!state || state->allow_nan) {
291
- return rb_funcall(self, i_to_s, 0);
319
+ result = rb_funcall(self, i_to_s, 0);
292
320
  } else {
293
321
  tmp = rb_funcall(self, i_to_s, 0);
294
322
  rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
295
323
  }
296
324
  } else if (isnan(value)) {
297
325
  if (!state || state->allow_nan) {
298
- return rb_funcall(self, i_to_s, 0);
326
+ result = rb_funcall(self, i_to_s, 0);
299
327
  } else {
300
328
  tmp = rb_funcall(self, i_to_s, 0);
301
329
  rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
302
330
  }
303
331
  } else {
304
- return rb_funcall(self, i_to_s, 0);
332
+ result = rb_funcall(self, i_to_s, 0);
305
333
  }
334
+ FORCE_UTF8(result);
335
+ return result;
306
336
  }
307
337
 
308
338
  /*
@@ -311,7 +341,9 @@ static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
311
341
  * Extends _modul_ with the String::Extend module.
312
342
  */
313
343
  static VALUE mString_included_s(VALUE self, VALUE modul) {
314
- return rb_funcall(modul, i_extend, 1, mString_Extend);
344
+ VALUE result = rb_funcall(modul, i_extend, 1, mString_Extend);
345
+ FORCE_UTF8(result);
346
+ return result;
315
347
  }
316
348
 
317
349
  /*
@@ -327,6 +359,7 @@ static VALUE mString_to_json(int argc, VALUE *argv, VALUE self)
327
359
  rb_str_buf_cat2(result, "\"");
328
360
  JSON_convert_UTF8_to_JSON(result, self, strictConversion);
329
361
  rb_str_buf_cat2(result, "\"");
362
+ FORCE_UTF8(result);
330
363
  return result;
331
364
  }
332
365
 
@@ -344,6 +377,7 @@ static VALUE mString_to_json_raw_object(VALUE self) {
344
377
  rb_hash_aset(result, rb_funcall(mJSON, i_create_id, 0), rb_class_name(rb_obj_class(self)));
345
378
  ary = rb_funcall(self, i_unpack, 1, rb_str_new2("C*"));
346
379
  rb_hash_aset(result, rb_str_new2("raw"), ary);
380
+ FORCE_UTF8(result);
347
381
  return result;
348
382
  }
349
383
 
@@ -354,9 +388,11 @@ static VALUE mString_to_json_raw_object(VALUE self) {
354
388
  * to_json_raw_object of this String.
355
389
  */
356
390
  static VALUE mString_to_json_raw(int argc, VALUE *argv, VALUE self) {
357
- VALUE obj = mString_to_json_raw_object(self);
391
+ VALUE result, obj = mString_to_json_raw_object(self);
358
392
  Check_Type(obj, T_HASH);
359
- return mHash_to_json(argc, argv, obj);
393
+ result = mHash_to_json(argc, argv, obj);
394
+ FORCE_UTF8(result);
395
+ return result;
360
396
  }
361
397
 
362
398
  /*
@@ -379,7 +415,9 @@ static VALUE mString_Extend_json_create(VALUE self, VALUE o) {
379
415
  */
380
416
  static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
381
417
  {
382
- return rb_str_new2("true");
418
+ VALUE result = rb_str_new2("true");
419
+ FORCE_UTF8(result);
420
+ return result;
383
421
  }
384
422
 
385
423
  /*
@@ -389,7 +427,9 @@ static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
389
427
  */
390
428
  static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self)
391
429
  {
392
- return rb_str_new2("false");
430
+ VALUE result = rb_str_new2("false");
431
+ FORCE_UTF8(result);
432
+ return result;
393
433
  }
394
434
 
395
435
  /*
@@ -398,7 +438,9 @@ static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self)
398
438
  */
399
439
  static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self)
400
440
  {
401
- return rb_str_new2("null");
441
+ VALUE result = rb_str_new2("null");
442
+ FORCE_UTF8(result);
443
+ return result;
402
444
  }
403
445
 
404
446
  /*
@@ -410,9 +452,11 @@ static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self)
410
452
  */
411
453
  static VALUE mObject_to_json(int argc, VALUE *argv, VALUE self)
412
454
  {
413
- VALUE string = rb_funcall(self, i_to_s, 0);
455
+ VALUE result, string = rb_funcall(self, i_to_s, 0);
414
456
  Check_Type(string, T_STRING);
415
- return mString_to_json(argc, argv, string);
457
+ result = mString_to_json(argc, argv, string);
458
+ FORCE_UTF8(result);
459
+ return result;
416
460
  }
417
461
 
418
462
  /*
@@ -488,7 +532,7 @@ static inline VALUE cState_configure(VALUE self, VALUE opts)
488
532
  state->object_nl = tmp;
489
533
  }
490
534
  tmp = ID2SYM(i_check_circular);
491
- if (st_lookup(RHASH(opts)->tbl, tmp, 0)) {
535
+ if (st_lookup(RHASH_TBL(opts), tmp, 0)) {
492
536
  tmp = rb_hash_aref(opts, ID2SYM(i_check_circular));
493
537
  state->check_circular = RTEST(tmp);
494
538
  } else {
@@ -496,7 +540,7 @@ static inline VALUE cState_configure(VALUE self, VALUE opts)
496
540
  }
497
541
  tmp = ID2SYM(i_max_nesting);
498
542
  state->max_nesting = 19;
499
- if (st_lookup(RHASH(opts)->tbl, tmp, 0)) {
543
+ if (st_lookup(RHASH_TBL(opts), tmp, 0)) {
500
544
  VALUE max_nesting = rb_hash_aref(opts, tmp);
501
545
  if (RTEST(max_nesting)) {
502
546
  Check_Type(max_nesting, T_FIXNUM);
@@ -6,4 +6,6 @@ if CONFIG['CC'] =~ /gcc/
6
6
  #$CFLAGS += ' -O0 -ggdb'
7
7
  end
8
8
 
9
+ have_header("ruby/st.h") || have_header("st.h")
10
+ have_header("re.h")
9
11
  create_makefile 'parser'