summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbenchmarks/generator2_benchmark.rb8
-rwxr-xr-xbenchmarks/generator_benchmark.rb8
-rwxr-xr-xbenchmarks/parser_benchmark.rb12
-rw-r--r--ext/json/ext/generator/generator.c54
-rw-r--r--ext/json/ext/generator/unicode.c87
-rw-r--r--ext/json/ext/generator/unicode.h1
-rw-r--r--lib/json/pure/generator.rb46
-rw-r--r--tests/test_json_encoding.rb7
-rwxr-xr-xtests/test_json_unicode.rb26
9 files changed, 197 insertions, 52 deletions
diff --git a/benchmarks/generator2_benchmark.rb b/benchmarks/generator2_benchmark.rb
index 10cf711..38653cb 100755
--- a/benchmarks/generator2_benchmark.rb
+++ b/benchmarks/generator2_benchmark.rb
@@ -53,6 +53,12 @@ module JSONGeneratorCommon
end
alias reset_benchmark_generator_pretty generic_reset_method
+
+ def benchmark_generator_ascii
+ @result = JSON.generate(@big, :ascii_only => true)
+ end
+
+ alias reset_benchmark_generator_ascii generic_reset_method
end
class Generator2BenchmarkExt < Bullshit::RepeatCase
@@ -193,9 +199,11 @@ if $0 == __FILE__
benchmark Generator2BenchmarkExt, :generator_fast, :load => yes
benchmark Generator2BenchmarkExt, :generator_safe, :load => yes
benchmark Generator2BenchmarkExt, :generator_pretty, :load => yes
+ benchmark Generator2BenchmarkExt, :generator_ascii, :load => yes
benchmark Generator2BenchmarkPure, :generator_fast, :load => yes
benchmark Generator2BenchmarkPure, :generator_safe, :load => yes
benchmark Generator2BenchmarkPure, :generator_pretty, :load => yes
+ benchmark Generator2BenchmarkPure, :generator_ascii, :load => yes
benchmark Generator2BenchmarkRails, :generator, :load => yes
benchmark Generator2BenchmarkYajl, :generator, :load => yes
end
diff --git a/benchmarks/generator_benchmark.rb b/benchmarks/generator_benchmark.rb
index 539fb91..79ac4d8 100755
--- a/benchmarks/generator_benchmark.rb
+++ b/benchmarks/generator_benchmark.rb
@@ -55,6 +55,12 @@ module JSONGeneratorCommon
end
alias reset_benchmark_generator_pretty generic_reset_method
+
+ def benchmark_generator_ascii
+ @result = JSON.generate(@big, :ascii_only => true)
+ end
+
+ alias reset_benchmark_generator_ascii generic_reset_method
end
class GeneratorBenchmarkExt < Bullshit::RepeatCase
@@ -195,9 +201,11 @@ if $0 == __FILE__
benchmark GeneratorBenchmarkExt, :generator_fast, :load => yes
benchmark GeneratorBenchmarkExt, :generator_safe, :load => yes
benchmark GeneratorBenchmarkExt, :generator_pretty, :load => yes
+ benchmark GeneratorBenchmarkExt, :generator_ascii, :load => yes
benchmark GeneratorBenchmarkPure, :generator_fast, :load => yes
benchmark GeneratorBenchmarkPure, :generator_safe, :load => yes
benchmark GeneratorBenchmarkPure, :generator_pretty, :load => yes
+ benchmark GeneratorBenchmarkPure, :generator_ascii, :load => yes
benchmark GeneratorBenchmarkRails, :generator, :load => yes
benchmark GeneratorBenchmarkYajl, :generator, :load => yes
end
diff --git a/benchmarks/parser_benchmark.rb b/benchmarks/parser_benchmark.rb
index 7ac027e..2dbad2a 100755
--- a/benchmarks/parser_benchmark.rb
+++ b/benchmarks/parser_benchmark.rb
@@ -221,9 +221,9 @@ if $0 == __FILE__
ParserBenchmarkYajl.run
else
system "#{RAKE_PATH} clean"
- #system "#{RUBY_PATH} #$0 yaml"
- #system "#{RUBY_PATH} #$0 rails"
- #system "#{RUBY_PATH} #$0 pure"
+ system "#{RUBY_PATH} #$0 yaml"
+ system "#{RUBY_PATH} #$0 rails"
+ system "#{RUBY_PATH} #$0 pure"
system "#{RAKE_PATH} compile_ext"
system "#{RUBY_PATH} #$0 ext"
system "#{RUBY_PATH} #$0 yajl"
@@ -231,9 +231,9 @@ if $0 == __FILE__
output_filename File.join(File.dirname(__FILE__), 'data', 'ParserBenchmarkComparison.log')
benchmark ParserBenchmarkExt, :parser, :load => yes
- #benchmark ParserBenchmarkPure, :parser, :load => yes
- #benchmark ParserBenchmarkYAML, :parser, :load => yes
- #benchmark ParserBenchmarkRails, :parser, :load => yes
+ benchmark ParserBenchmarkPure, :parser, :load => yes
+ benchmark ParserBenchmarkYAML, :parser, :load => yes
+ benchmark ParserBenchmarkRails, :parser, :load => yes
benchmark ParserBenchmarkYajl, :parser, :load => yes
end
end
diff --git a/ext/json/ext/generator/generator.c b/ext/json/ext/generator/generator.c
index 36580ad..dce6fef 100644
--- a/ext/json/ext/generator/generator.c
+++ b/ext/json/ext/generator/generator.c
@@ -16,6 +16,7 @@
#endif
inline static VALUE cState_partial_generate(VALUE self, VALUE obj, VALUE depth);
+inline static VALUE cState_from_state_s(VALUE self, VALUE opts);
#ifndef RHASH_TBL
#define RHASH_TBL(hsh) (RHASH(hsh)->tbl)
@@ -45,7 +46,7 @@ static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject,
static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
i_object_nl, i_array_nl, i_max_nesting,
- i_allow_nan, i_pack, i_unpack, i_create_id, i_extend;
+ i_allow_nan, i_ascii_only, i_pack, i_unpack, i_create_id, i_extend;
typedef struct JSON_Generator_StateStruct {
VALUE indent;
@@ -56,8 +57,8 @@ typedef struct JSON_Generator_StateStruct {
FBuffer *delim;
FBuffer *delim2;
long max_nesting;
- int flag;
- int allow_nan;
+ char allow_nan;
+ char ascii_only;
} JSON_Generator_State;
#define GET_STATE(self) \
@@ -92,7 +93,7 @@ static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
VALUE state, depth;
rb_scan_args(argc, argv, "02", &state, &depth);
- if (NIL_P(state)) state = rb_class_new_instance(0, NULL, cState);
+ state = cState_from_state_s(cState, state);
return cState_partial_generate(state, self, depth);
}
@@ -108,7 +109,7 @@ static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
VALUE state, depth;
rb_scan_args(argc, argv, "02", &state, &depth);
- if (NIL_P(state)) state = rb_class_new_instance(0, NULL, cState);
+ state = cState_from_state_s(cState, state);
return cState_partial_generate(state, self, depth);
}
@@ -121,7 +122,7 @@ static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
{
VALUE state, depth;
rb_scan_args(argc, argv, "02", &state, &depth);
- if (NIL_P(state)) state = rb_class_new_instance(0, NULL, cState);
+ state = cState_from_state_s(cState, state);
return cState_partial_generate(state, self, depth);
}
@@ -134,7 +135,7 @@ static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
{
VALUE state, depth;
rb_scan_args(argc, argv, "02", &state, &depth);
- if (NIL_P(state)) state = rb_class_new_instance(0, NULL, cState);
+ state = cState_from_state_s(cState, state);
return cState_partial_generate(state, self, depth);
}
@@ -159,7 +160,7 @@ static VALUE mString_to_json(int argc, VALUE *argv, VALUE self)
{
VALUE state, depth;
rb_scan_args(argc, argv, "02", &state, &depth);
- if (NIL_P(state)) state = rb_class_new_instance(0, NULL, cState);
+ state = cState_from_state_s(cState, state);
return cState_partial_generate(state, self, depth);
}
@@ -214,7 +215,7 @@ static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
{
VALUE state, depth;
rb_scan_args(argc, argv, "02", &state, &depth);
- if (NIL_P(state)) state = rb_class_new_instance(0, NULL, cState);
+ state = cState_from_state_s(cState, state);
return cState_partial_generate(state, self, depth);
}
@@ -227,7 +228,7 @@ static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self)
{
VALUE state, depth;
rb_scan_args(argc, argv, "02", &state, &depth);
- if (NIL_P(state)) state = rb_class_new_instance(0, NULL, cState);
+ state = cState_from_state_s(cState, state);
return cState_partial_generate(state, self, depth);
}
@@ -239,7 +240,7 @@ static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self)
{
VALUE state, depth;
rb_scan_args(argc, argv, "02", &state, &depth);
- if (NIL_P(state)) state = rb_class_new_instance(0, NULL, cState);
+ state = cState_from_state_s(cState, state);
return cState_partial_generate(state, self, depth);
}
@@ -256,7 +257,7 @@ static VALUE mObject_to_json(int argc, VALUE *argv, VALUE self)
VALUE string = rb_funcall(self, i_to_s, 0);
rb_scan_args(argc, argv, "02", &state, &depth);
Check_Type(string, T_STRING);
- if (NIL_P(state)) state = rb_class_new_instance(0, NULL, cState);
+ state = cState_from_state_s(cState, state);
return cState_partial_generate(state, string, depth);
}
@@ -348,6 +349,8 @@ static VALUE cState_configure(VALUE self, VALUE opts)
}
tmp = rb_hash_aref(opts, ID2SYM(i_allow_nan));
state->allow_nan = RTEST(tmp);
+ tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
+ state->ascii_only = RTEST(tmp);
return self;
}
@@ -367,6 +370,7 @@ static VALUE cState_to_h(VALUE self)
rb_hash_aset(result, ID2SYM(i_object_nl), state->object_nl);
rb_hash_aset(result, ID2SYM(i_array_nl), state->array_nl);
rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse);
+ rb_hash_aset(result, ID2SYM(i_ascii_only), state->ascii_only ? Qtrue : Qfalse);
rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
return result;
}
@@ -476,15 +480,13 @@ void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, V
case T_STRING:
fbuffer_append_char(buffer, '"');
#ifdef HAVE_RUBY_ENCODING_H
- if (rb_funcall(obj, i_encoding, 0) == CEncoding_UTF_8) {
+ obj = rb_funcall(obj, i_encode, 1, CEncoding_UTF_8);
+#endif
+ if (state->ascii_only) {
JSON_convert_UTF8_to_JSON_ASCII(buffer, obj);
} else {
- VALUE string = rb_funcall(obj, i_encode, 1, CEncoding_UTF_8);
- JSON_convert_UTF8_to_JSON_ASCII(buffer, string);
+ JSON_convert_UTF8_to_JSON(buffer, obj);
}
-#else
- JSON_convert_UTF8_to_JSON_ASCII(buffer, obj);
-#endif
fbuffer_append_char(buffer, '"');
break;
case T_NIL:
@@ -598,7 +600,7 @@ static VALUE cState_initialize(int argc, VALUE *argv, VALUE self)
* new State instance configured by _opts_, something else to create an
* unconfigured instance. If _opts_ is a State object, it is just returned.
*/
-static VALUE cState_from_state_s(VALUE self, VALUE opts)
+inline static VALUE cState_from_state_s(VALUE self, VALUE opts)
{
if (rb_obj_is_kind_of(opts, self)) {
return opts;
@@ -786,6 +788,18 @@ static VALUE cState_allow_nan_p(VALUE self)
}
/*
+ * call-seq: ascii_only?
+ *
+ * Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise
+ * returns false.
+ */
+static VALUE cState_ascii_only_p(VALUE self)
+{
+ GET_STATE(self);
+ return state->ascii_only ? Qtrue : Qfalse;
+}
+
+/*
*
*/
void Init_generator()
@@ -816,6 +830,7 @@ void Init_generator()
rb_define_method(cState, "max_nesting", cState_max_nesting, 0);
rb_define_method(cState, "max_nesting=", cState_max_nesting_set, 1);
rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
+ rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
rb_define_method(cState, "configure", cState_configure, 1);
rb_define_method(cState, "to_h", cState_to_h, 0);
rb_define_method(cState, "generate", cState_generate, 1);
@@ -857,6 +872,7 @@ void Init_generator()
i_array_nl = rb_intern("array_nl");
i_max_nesting = rb_intern("max_nesting");
i_allow_nan = rb_intern("allow_nan");
+ i_ascii_only = rb_intern("ascii_only");
i_pack = rb_intern("pack");
i_unpack = rb_intern("unpack");
i_create_id = rb_intern("create_id");
diff --git a/ext/json/ext/generator/unicode.c b/ext/json/ext/generator/unicode.c
index 2084c60..53a2ec1 100644
--- a/ext/json/ext/generator/unicode.c
+++ b/ext/json/ext/generator/unicode.c
@@ -86,23 +86,29 @@ inline static unsigned char isLegalUTF8(const UTF8 *source, int length)
return 1;
}
-inline static void unicode_escape(FBuffer *buffer, UTF16 character)
+inline static void unicode_escape(char *buf, UTF16 character)
{
const char *digits = "0123456789abcdef";
- char buf[7] = { '\\', 'u' };
- buf[6] = 0;
buf[2] = digits[character >> 12];
buf[3] = digits[(character >> 8) & 0xf];
buf[4] = digits[(character >> 4) & 0xf];
buf[5] = digits[character & 0xf];
+}
+
+
+inline static void unicode_escape_to_buffer(FBuffer *buffer, char buf[7], UTF16 character)
+{
+ unicode_escape(buf, character);
fbuffer_append(buffer, buf, 6);
}
inline void JSON_convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
{
- const UTF8* source = (UTF8 *) RSTRING_PTR(string);
- const UTF8* sourceEnd = source + RSTRING_LEN(string);
+ const UTF8 *source = (UTF8 *) RSTRING_PTR(string);
+ const UTF8 *sourceEnd = source + RSTRING_LEN(string);
+ char buf[7] = { '\\', 'u' };
+ buf[6] = 0;
while (source < sourceEnd) {
UTF32 ch = 0;
@@ -136,11 +142,11 @@ inline void JSON_convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
rb_raise(rb_path2class("JSON::GeneratorError"),
"source sequence is illegal/malformed utf-8");
#else
- unicode_escape(buffer, UNI_REPLACEMENT_CHAR);
+ unicode_escape_to_buffer(buffer, buf, UNI_REPLACEMENT_CHAR);
#endif
} else {
/* normal case */
- switch(ch) {
+ switch (ch) {
case '\n':
fbuffer_append(buffer, "\\n", 2);
break;
@@ -166,7 +172,7 @@ inline void JSON_convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
if (ch >= 0x20 && ch <= 0x7f) {
fbuffer_append_char(buffer, ch);
} else {
- unicode_escape(buffer, (UTF16) ch);
+ unicode_escape_to_buffer(buffer, buf, (UTF16) ch);
}
break;
}
@@ -177,13 +183,72 @@ inline void JSON_convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
rb_raise(rb_path2class("JSON::GeneratorError"),
"source sequence is illegal/malformed utf8");
#else
- unicode_escape(buffer, UNI_REPLACEMENT_CHAR);
+ unicode_escape_to_buffer(buffer, buf, UNI_REPLACEMENT_CHAR);
#endif
} else {
/* target is a character in range 0xFFFF - 0x10FFFF. */
ch -= halfBase;
- unicode_escape(buffer, (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START));
- unicode_escape(buffer, (UTF16)((ch & halfMask) + UNI_SUR_LOW_START));
+ unicode_escape_to_buffer(buffer, buf, (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START));
+ unicode_escape_to_buffer(buffer, buf, (UTF16)((ch & halfMask) + UNI_SUR_LOW_START));
+ }
+ }
+}
+
+inline void JSON_convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
+{
+ const char *ptr = RSTRING_PTR(string), *p;
+ int len = RSTRING_LEN(string), start = 0, end = 0;
+ const char *escape = NULL;
+ int escape_len;
+ char buf[7] = { '\\', 'u' };
+ buf[6] = 0;
+
+ for (start = 0, end = 0; end < len;) {
+ p = ptr + end;
+ switch (*p) {
+ case '\n':
+ escape = "\\n";
+ escape_len = 2;
+ break;
+ case '\r':
+ escape = "\\r";
+ escape_len = 2;
+ break;
+ case '\\':
+ escape = "\\\\";
+ escape_len = 2;
+ break;
+ case '"':
+ escape = "\\\"";
+ escape_len = 2;
+ break;
+ case '\t':
+ escape = "\\t";
+ escape_len = 2;
+ break;
+ case '\f':
+ escape = "\\f";
+ escape_len = 2;
+ break;
+ case '\b':
+ escape = "\\b";
+ escape_len = 2;
+ break;
+ default:
+ if ((unsigned char) *p < 0x20) {
+ unicode_escape(buf, (UTF16) *p);
+ escape = buf;
+ escape_len = 6;
+ } else {
+ end++;
+ continue;
+ }
+ break;
}
+ fbuffer_append(buffer, ptr + start, end - start);
+ fbuffer_append(buffer, escape, escape_len);
+ start = ++end;
+ escape = NULL;
}
+ fbuffer_append(buffer, ptr + start, end - start);
}
diff --git a/ext/json/ext/generator/unicode.h b/ext/json/ext/generator/unicode.h
index a9abf5b..b827119 100644
--- a/ext/json/ext/generator/unicode.h
+++ b/ext/json/ext/generator/unicode.h
@@ -27,6 +27,7 @@ static const UTF32 halfBase = 0x0010000UL;
static const UTF32 halfMask = 0x3FFUL;
inline void JSON_convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string);
+inline void JSON_convert_UTF8_to_JSON(FBuffer *buffer, VALUE string);
#ifndef RARRAY_PTR
#define RARRAY_PTR(ARRAY) RARRAY(ARRAY)->ptr
diff --git a/lib/json/pure/generator.rb b/lib/json/pure/generator.rb
index 715acba..8358988 100644
--- a/lib/json/pure/generator.rb
+++ b/lib/json/pure/generator.rb
@@ -44,6 +44,15 @@ module JSON
string << '' # XXX workaround: avoid buffer sharing
string.force_encoding(::Encoding::ASCII_8BIT)
string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] }
+ string.force_encoding(::Encoding::UTF_8)
+ string
+ end
+
+ def utf8_to_json_ascii(string) # :nodoc:
+ string = string.dup
+ string << '' # XXX workaround: avoid buffer sharing
+ string.force_encoding(::Encoding::ASCII_8BIT)
+ string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] }
string.gsub!(/(
(?:
[\xc2-\xdf][\x80-\xbf] |
@@ -63,6 +72,10 @@ module JSON
end
else
def utf8_to_json(string) # :nodoc:
+ string.gsub(/["\\\x0-\x1f]/) { MAP[$&] }
+ end
+
+ def utf8_to_json_ascii(string) # :nodoc:
string = string.gsub(/["\\\x0-\x1f]/) { MAP[$&] }
string.gsub!(/(
(?:
@@ -81,7 +94,7 @@ module JSON
raise GeneratorError, "Caught #{e.class}: #{e}"
end
end
- module_function :utf8_to_json
+ module_function :utf8_to_json, :utf8_to_json_ascii
module Pure
module Generator
@@ -125,6 +138,7 @@ module JSON
@object_nl = ''
@array_nl = ''
@allow_nan = false
+ @ascii_only = false
configure opts
end
@@ -168,6 +182,10 @@ module JSON
@allow_nan
end
+ def ascii_only?
+ @ascii_only
+ end
+
# Configure this State instance with the Hash _opts_, and return
# itself.
def configure(opts)
@@ -177,6 +195,7 @@ module JSON
@object_nl = opts[:object_nl] if opts.key?(:object_nl)
@array_nl = opts[:array_nl] if opts.key?(:array_nl)
@allow_nan = !!opts[:allow_nan] if opts.key?(:allow_nan)
+ @ascii_only = opts[:ascii_only] if opts.key?(:ascii_only)
if !opts.key?(:max_nesting) # defaults to 19
@max_nesting = 19
elsif opts[:max_nesting]
@@ -343,11 +362,17 @@ module JSON
# This string should be encoded with UTF-8 A call to this method
# returns a JSON string encoded with UTF16 big endian characters as
# \u????.
- def to_json(*)
+ def to_json(*args)
+ state, = *args
+ state ||= JSON.state.from_state(state)
if encoding == ::Encoding::UTF_8
- '"' << JSON.utf8_to_json(self) << '"'
+ string = self
else
string = encode(::Encoding::UTF_8)
+ end
+ if state.ascii_only?
+ '"' << JSON.utf8_to_json_ascii(string) << '"'
+ else
'"' << JSON.utf8_to_json(string) << '"'
end
end
@@ -355,16 +380,23 @@ module JSON
# This string should be encoded with UTF-8 A call to this method
# returns a JSON string encoded with UTF16 big endian characters as
# \u????.
- def to_json(*)
- '"' << JSON.utf8_to_json(self) << '"'
+ def to_json(*args)
+ state, = *args
+ state ||= JSON.state.from_state(state)
+ if state.ascii_only?
+ '"' << JSON.utf8_to_json_ascii(self) << '"'
+ else
+ '"' << JSON.utf8_to_json(self) << '"'
+ end
end
end
# Module that holds the extinding methods if, the String module is
# included.
module Extend
- # Raw Strings are JSON Objects (the raw bytes are stored in an array for the
- # key "raw"). The Ruby String can be created by this module method.
+ # Raw Strings are JSON Objects (the raw bytes are stored in an
+ # array for the key "raw"). The Ruby String can be created by this
+ # module method.
def json_create(o)
o['raw'].pack('C*')
end
diff --git a/tests/test_json_encoding.rb b/tests/test_json_encoding.rb
index bfb3e60..fdea329 100644
--- a/tests/test_json_encoding.rb
+++ b/tests/test_json_encoding.rb
@@ -57,11 +57,12 @@ class TC_JSONEncoding < Test::Unit::TestCase
end
def test_generate
- assert_equal @generated, JSON.generate(@parsed)
+ assert_equal @generated, JSON.generate(@parsed, :ascii_only => true)
if defined?(::Encoding)
- assert_equal @generated, JSON.generate(@utf_16_data)
+ assert_equal @generated, JSON.generate(@utf_16_data, :ascii_only => true)
else
- assert_raises(JSON::GeneratorError) { JSON.generate(@utf_16_data) }
+ # XXX checking of correct utf8 data is not as strict (yet?) without :ascii_only
+ assert_raises(JSON::GeneratorError) { JSON.generate(@utf_16_data, :ascii_only => true) }
end
end
end
diff --git a/tests/test_json_unicode.rb b/tests/test_json_unicode.rb
index 1454fe1..505f5d5 100755
--- a/tests/test_json_unicode.rb
+++ b/tests/test_json_unicode.rb
@@ -19,22 +19,36 @@ class TC_JSONUnicode < Test::Unit::TestCase
assert_equal '" "', ' '.to_json
assert_equal "\"#{0x7f.chr}\"", 0x7f.chr.to_json
utf8 = [ "© ≠ €! \01" ]
+ json = '["© ≠ €! \u0001"]'
+ assert_equal json, utf8.to_json(:ascii_only => false)
+ assert_equal utf8, parse(json)
json = '["\u00a9 \u2260 \u20ac! \u0001"]'
- assert_equal json, utf8.to_json
+ assert_equal json, utf8.to_json(:ascii_only => true)
+ assert_equal utf8, parse(json)
+ utf8 = ["\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212"]
+ json = "[\"\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212\"]"
assert_equal utf8, parse(json)
+ assert_equal json, utf8.to_json(:ascii_only => false)
utf8 = ["\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212"]
+ assert_equal utf8, parse(json)
json = "[\"\\u3042\\u3044\\u3046\\u3048\\u304a\"]"
- assert_equal json, utf8.to_json
+ assert_equal json, utf8.to_json(:ascii_only => true)
assert_equal utf8, parse(json)
utf8 = ['საქართველო']
+ json = '["საქართველო"]'
+ assert_equal json, utf8.to_json(:ascii_only => false)
json = "[\"\\u10e1\\u10d0\\u10e5\\u10d0\\u10e0\\u10d7\\u10d5\\u10d4\\u10da\\u10dd\"]"
- assert_equal json, utf8.to_json
+ assert_equal json, utf8.to_json(:ascii_only => true)
assert_equal utf8, parse(json)
- assert_equal '["\\u00c3"]', JSON.generate(["Ã"])
+ assert_equal '["Ã"]', JSON.generate(["Ã"], :ascii_only => false)
+ assert_equal '["\\u00c3"]', JSON.generate(["Ã"], :ascii_only => true)
assert_equal ["€"], JSON.parse('["\u20ac"]')
utf8 = ["\xf0\xa0\x80\x81"]
+ json = "[\"\xf0\xa0\x80\x81\"]"
+ assert_equal json, JSON.generate(utf8, :ascii_only => false)
+ assert_equal utf8, JSON.parse(json)
json = '["\ud840\udc01"]'
- assert_equal json, JSON.generate(utf8)
+ assert_equal json, JSON.generate(utf8, :ascii_only => true)
assert_equal utf8, JSON.parse(json)
end
@@ -55,7 +69,7 @@ class TC_JSONUnicode < Test::Unit::TestCase
end
end
assert_raise(JSON::GeneratorError) do
- JSON.generate(["\x80"])
+ JSON.generate(["\x80"], :ascii_only => true)
end
assert_equal "\302\200", JSON.parse('["\u0080"]').first
end