1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* ext/json: import JSON v 1.1.3.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@19436 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
naruse 2008-09-20 17:41:14 +00:00
parent a91cd48aa1
commit e8eb95ec33
21 changed files with 501 additions and 430 deletions

View file

@ -1,3 +1,7 @@
Sun Sep 21 02:40:20 2008 NARUSE, Yui <naruse@ruby-lang.org>
* ext/json: import JSON v 1.1.3.
Sat Sep 20 11:43:08 2008 Yusuke Endoh <mame@tsg.ne.jp> Sat Sep 20 11:43:08 2008 Yusuke Endoh <mame@tsg.ne.jp>
* lib/optparse.rb (summarize): separator "" should output new line. * lib/optparse.rb (summarize): separator "" should output new line.

View file

@ -2,9 +2,8 @@ require 'mkmf'
require 'rbconfig' require 'rbconfig'
if CONFIG['CC'] =~ /gcc/ if CONFIG['CC'] =~ /gcc/
#$CFLAGS += ' -Wall -ggdb'
$CFLAGS += ' -Wall' $CFLAGS += ' -Wall'
#$CFLAGS += ' -O0 -ggdb'
end end
have_header 'st.h' create_makefile 'generator'
create_makefile 'json/ext/generator'

View file

@ -1,15 +1,8 @@
/* vim: set cin et sw=4 ts=4: */
#include "ruby.h"
#include "ruby/st.h"
#include "unicode.h"
#include <string.h> #include <string.h>
#include "ruby.h"
#include "unicode.h"
#include <math.h> #include <math.h>
#ifdef HAVE_IEEEFP_H
#include <ieeefp.h>
#endif
#define check_max_nesting(state, depth) do { \ #define check_max_nesting(state, depth) do { \
long current_nesting = 1 + depth; \ long current_nesting = 1 + depth; \
if (state->max_nesting != 0 && current_nesting > state->max_nesting) \ if (state->max_nesting != 0 && current_nesting > state->max_nesting) \
@ -297,14 +290,14 @@ static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
return rb_funcall(self, i_to_s, 0); return rb_funcall(self, i_to_s, 0);
} else { } else {
tmp = rb_funcall(self, i_to_s, 0); tmp = rb_funcall(self, i_to_s, 0);
rb_raise(eGeneratorError, "%s not allowed in JSON", StringValueCStr(tmp)); rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
} }
} else if (isnan(value)) { } else if (isnan(value)) {
if (!state || state->allow_nan) { if (!state || state->allow_nan) {
return rb_funcall(self, i_to_s, 0); return rb_funcall(self, i_to_s, 0);
} else { } else {
tmp = rb_funcall(self, i_to_s, 0); tmp = rb_funcall(self, i_to_s, 0);
rb_raise(eGeneratorError, "%s not allowed in JSON", StringValueCStr(tmp)); rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
} }
} else { } else {
return rb_funcall(self, i_to_s, 0); return rb_funcall(self, i_to_s, 0);

View file

@ -1,5 +1,3 @@
/* vim: set cin et sw=4 ts=4: */
#include "unicode.h" #include "unicode.h"
#define unicode_escape(buffer, character) \ #define unicode_escape(buffer, character) \

View file

@ -2,9 +2,8 @@ require 'mkmf'
require 'rbconfig' require 'rbconfig'
if CONFIG['CC'] =~ /gcc/ if CONFIG['CC'] =~ /gcc/
#$CFLAGS += ' -Wall -ggdb'
$CFLAGS += ' -Wall' $CFLAGS += ' -Wall'
#$CFLAGS += ' -O0 -ggdb'
end end
have_header 'st.h' create_makefile 'parser'
create_makefile 'json/ext/parser'

File diff suppressed because it is too large Load diff

View file

@ -1,9 +1,4 @@
/* vim: set cin et sw=4 ts=4: */
#include "ruby.h" #include "ruby.h"
#include "ruby/re.h"
#include "ruby/st.h"
#include "ruby/encoding.h"
#include "unicode.h" #include "unicode.h"
#define EVIL 0x666 #define EVIL 0x666
@ -76,7 +71,7 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
VALUE v = Qnil; VALUE v = Qnil;
char *np = JSON_parse_value(json, fpc, pe, &v); char *np = JSON_parse_value(json, fpc, pe, &v);
if (np == NULL) { if (np == NULL) {
fbreak; fhold; fbreak;
} else { } else {
rb_hash_aset(*result, last_name, v); rb_hash_aset(*result, last_name, v);
fexec np; fexec np;
@ -85,10 +80,10 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
action parse_name { action parse_name {
char *np = JSON_parse_string(json, fpc, pe, &last_name); char *np = JSON_parse_string(json, fpc, pe, &last_name);
if (np == NULL) fbreak; else fexec np; if (np == NULL) { fhold; fbreak; } else fexec np;
} }
action exit { fbreak; } action exit { fhold; fbreak; }
a_pair = ignore* begin_name >parse_name a_pair = ignore* begin_name >parse_name
ignore* name_separator ignore* ignore* name_separator ignore*
@ -148,19 +143,19 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
if (json->allow_nan) { if (json->allow_nan) {
*result = CNaN; *result = CNaN;
} else { } else {
rb_raise(eParserError, "unexpected token at '%s'", p - 2); rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2);
} }
} }
action parse_infinity { action parse_infinity {
if (json->allow_nan) { if (json->allow_nan) {
*result = CInfinity; *result = CInfinity;
} else { } else {
rb_raise(eParserError, "unexpected token at '%s'", p - 8); rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8);
} }
} }
action parse_string { action parse_string {
char *np = JSON_parse_string(json, fpc, pe, result); char *np = JSON_parse_string(json, fpc, pe, result);
if (np == NULL) fbreak; else fexec np; if (np == NULL) { fhold; fbreak; } else fexec np;
} }
action parse_number { action parse_number {
@ -169,35 +164,35 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
if (json->allow_nan) { if (json->allow_nan) {
*result = CMinusInfinity; *result = CMinusInfinity;
fexec p + 10; fexec p + 10;
fbreak; fhold; fbreak;
} else { } else {
rb_raise(eParserError, "unexpected token at '%s'", p); rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
} }
} }
np = JSON_parse_float(json, fpc, pe, result); np = JSON_parse_float(json, fpc, pe, result);
if (np != NULL) fexec np; if (np != NULL) fexec np;
np = JSON_parse_integer(json, fpc, pe, result); np = JSON_parse_integer(json, fpc, pe, result);
if (np != NULL) fexec np; if (np != NULL) fexec np;
fbreak; fhold; fbreak;
} }
action parse_array { action parse_array {
char *np; char *np;
json->current_nesting += 1; json->current_nesting++;
np = JSON_parse_array(json, fpc, pe, result); np = JSON_parse_array(json, fpc, pe, result);
json->current_nesting -= 1; json->current_nesting--;
if (np == NULL) fbreak; else fexec np; if (np == NULL) { fhold; fbreak; } else fexec np;
} }
action parse_object { action parse_object {
char *np; char *np;
json->current_nesting += 1; json->current_nesting++;
np = JSON_parse_object(json, fpc, pe, result); np = JSON_parse_object(json, fpc, pe, result);
json->current_nesting -= 1; json->current_nesting--;
if (np == NULL) fbreak; else fexec np; if (np == NULL) { fhold; fbreak; } else fexec np;
} }
action exit { fbreak; } action exit { fhold; fbreak; }
main := ( main := (
Vnull @parse_null | Vnull @parse_null |
@ -231,7 +226,7 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
write data; write data;
action exit { fbreak; } action exit { fhold; fbreak; }
main := '-'? ('0' | [1-9][0-9]*) (^[0-9] @exit); main := '-'? ('0' | [1-9][0-9]*) (^[0-9] @exit);
}%% }%%
@ -259,7 +254,7 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
write data; write data;
action exit { fbreak; } action exit { fhold; fbreak; }
main := '-'? ( main := '-'? (
(('0' | [1-9][0-9]*) '.' [0-9]+ ([Ee] [+\-]?[0-9]+)?) (('0' | [1-9][0-9]*) '.' [0-9]+ ([Ee] [+\-]?[0-9]+)?)
@ -295,14 +290,14 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
VALUE v = Qnil; VALUE v = Qnil;
char *np = JSON_parse_value(json, fpc, pe, &v); char *np = JSON_parse_value(json, fpc, pe, &v);
if (np == NULL) { if (np == NULL) {
fbreak; fhold; fbreak;
} else { } else {
rb_ary_push(*result, v); rb_ary_push(*result, v);
fexec np; fexec np;
} }
} }
action exit { fbreak; } action exit { fhold; fbreak; }
next_element = value_separator ignore* begin_value >parse_value; next_element = value_separator ignore* begin_value >parse_value;
@ -327,13 +322,13 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
if(cs >= JSON_array_first_final) { if(cs >= JSON_array_first_final) {
return p + 1; return p + 1;
} else { } else {
rb_raise(eParserError, "unexpected token at '%s'", p); rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
} }
} }
static VALUE json_string_unescape(char *p, char *pe) static VALUE json_string_unescape(char *p, char *pe)
{ {
VALUE result = rb_enc_str_new(0, pe - p + 1, rb_utf8_encoding()); VALUE result = rb_str_buf_new(pe - p + 1);
while (p < pe) { while (p < pe) {
if (*p == '\\') { if (*p == '\\') {
@ -395,10 +390,10 @@ static VALUE json_string_unescape(char *p, char *pe)
action parse_string { action parse_string {
*result = json_string_unescape(json->memo + 1, p); *result = json_string_unescape(json->memo + 1, p);
if (NIL_P(*result)) fbreak; else fexec p + 1; if (NIL_P(*result)) { fhold; fbreak; } else fexec p + 1;
} }
action exit { fbreak; } action exit { fhold; fbreak; }
main := '"' ((^(["\\] | 0..0x1f) | '\\'["\\/bfnrt] | '\\u'[0-9a-fA-F]{4} | '\\'^(["\\/bfnrtu]|0..0x1f))* %parse_string) '"' @exit; main := '"' ((^(["\\] | 0..0x1f) | '\\'["\\/bfnrt] | '\\u'[0-9a-fA-F]{4} | '\\'^(["\\/bfnrtu]|0..0x1f))* %parse_string) '"' @exit;
}%% }%%
@ -407,7 +402,7 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
{ {
int cs = EVIL; int cs = EVIL;
*result = rb_enc_str_new("", 0, rb_utf8_encoding()); *result = rb_str_new("", 0);
%% write init; %% write init;
json->memo = p; json->memo = p;
%% write exec; %% write exec;
@ -431,14 +426,14 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
char *np; char *np;
json->current_nesting = 1; json->current_nesting = 1;
np = JSON_parse_object(json, fpc, pe, &result); np = JSON_parse_object(json, fpc, pe, &result);
if (np == NULL) fbreak; else fexec np; if (np == NULL) { fhold; fbreak; } else fexec np;
} }
action parse_array { action parse_array {
char *np; char *np;
json->current_nesting = 1; json->current_nesting = 1;
np = JSON_parse_array(json, fpc, pe, &result); np = JSON_parse_array(json, fpc, pe, &result);
if (np == NULL) fbreak; else fexec np; if (np == NULL) { fhold; fbreak; } else fexec np;
} }
main := ignore* ( main := ignore* (
@ -574,7 +569,7 @@ static VALUE cParser_parse(VALUE self)
if (cs >= JSON_first_final && p == pe) { if (cs >= JSON_first_final && p == pe) {
return result; return result;
} else { } else {
rb_raise(eParserError, "unexpected token at '%s'", p); rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
} }
} }
@ -593,7 +588,7 @@ static void JSON_mark(JSON_Parser *json)
static void JSON_free(JSON_Parser *json) static void JSON_free(JSON_Parser *json)
{ {
ruby_xfree(json); free(json);
} }
static VALUE cJSON_parser_s_allocate(VALUE klass) static VALUE cJSON_parser_s_allocate(VALUE klass)
@ -616,6 +611,7 @@ static VALUE cParser_source(VALUE self)
void Init_parser() void Init_parser()
{ {
rb_require("json/common");
mJSON = rb_define_module("JSON"); mJSON = rb_define_module("JSON");
mExt = rb_define_module_under(mJSON, "Ext"); mExt = rb_define_module_under(mJSON, "Ext");
cParser = rb_define_class_under(mExt, "Parser", rb_cObject); cParser = rb_define_class_under(mExt, "Parser", rb_cObject);

View file

@ -1,5 +1,3 @@
/* vim: set cin et sw=4 ts=4: */
#include "unicode.h" #include "unicode.h"
/* /*
@ -105,12 +103,12 @@ char *JSON_convert_UTF16_to_UTF8 (
+ (ch2 - UNI_SUR_LOW_START) + halfBase; + (ch2 - UNI_SUR_LOW_START) + halfBase;
++tmpPtr; ++tmpPtr;
} else if (flags == strictConversion) { /* it's an unpaired high surrogate */ } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
ruby_xfree(tmp); free(tmp);
rb_raise(rb_path2class("JSON::ParserError"), rb_raise(rb_path2class("JSON::ParserError"),
"source sequence is illegal/malformed near %s", source); "source sequence is illegal/malformed near %s", source);
} }
} else { /* We don't have the 16 bits following the high surrogate. */ } else { /* We don't have the 16 bits following the high surrogate. */
ruby_xfree(tmp); free(tmp);
rb_raise(rb_path2class("JSON::ParserError"), rb_raise(rb_path2class("JSON::ParserError"),
"partial character in source, but hit end near %s", source); "partial character in source, but hit end near %s", source);
break; break;
@ -118,7 +116,7 @@ char *JSON_convert_UTF16_to_UTF8 (
} else if (flags == strictConversion) { } else if (flags == strictConversion) {
/* UTF-16 surrogate values are illegal in UTF-32 */ /* UTF-16 surrogate values are illegal in UTF-32 */
if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
ruby_xfree(tmp); free(tmp);
rb_raise(rb_path2class("JSON::ParserError"), rb_raise(rb_path2class("JSON::ParserError"),
"source sequence is illegal/malformed near %s", source); "source sequence is illegal/malformed near %s", source);
} }
@ -150,7 +148,7 @@ char *JSON_convert_UTF16_to_UTF8 (
} }
rb_str_buf_cat(buffer, p, bytesToWrite); rb_str_buf_cat(buffer, p, bytesToWrite);
} }
ruby_xfree(tmp); free(tmp);
source += 5 + (n - 1) * 6; source += 5 + (n - 1) * 6;
return source; return source;
} }

View file

@ -9,14 +9,21 @@ require 'date'
class Time class Time
def self.json_create(object) def self.json_create(object)
at(*object.values_at('s', 'u')) if usec = object.delete('u') # used to be tv_usec -> tv_nsec
object['n'] = usec * 1000
end
if respond_to?(:tv_nsec)
at(*object.values_at('s', 'n'))
else
at(object['s'], object['n'] / 1000)
end
end end
def to_json(*args) def to_json(*args)
{ {
'json_class' => self.class.name.to_s, 'json_class' => self.class.name,
's' => tv_sec, 's' => tv_sec,
'u' => tv_usec, 'n' => respond_to?(:tv_nsec) ? tv_nsec : tv_usec * 1000
}.to_json(*args) }.to_json(*args)
end end
end end
@ -26,13 +33,15 @@ class Date
civil(*object.values_at('y', 'm', 'd', 'sg')) civil(*object.values_at('y', 'm', 'd', 'sg'))
end end
alias start sg unless method_defined?(:start)
def to_json(*args) def to_json(*args)
{ {
'json_class' => self.class.name.to_s, 'json_class' => self.class.name,
'y' => year, 'y' => year,
'm' => month, 'm' => month,
'd' => day, 'd' => day,
'sg' => @sg, 'sg' => start,
}.to_json(*args) }.to_json(*args)
end end
end end
@ -41,14 +50,20 @@ class DateTime
def self.json_create(object) def self.json_create(object)
args = object.values_at('y', 'm', 'd', 'H', 'M', 'S') args = object.values_at('y', 'm', 'd', 'H', 'M', 'S')
of_a, of_b = object['of'].split('/') of_a, of_b = object['of'].split('/')
args << Rational(of_a.to_i, of_b.to_i) if of_b and of_b != '0'
args << Rational(of_a.to_i, of_b.to_i)
else
args << of_a
end
args << object['sg'] args << object['sg']
civil(*args) civil(*args)
end end
alias start sg unless method_defined?(:start)
def to_json(*args) def to_json(*args)
{ {
'json_class' => self.class.name.to_s, 'json_class' => self.class.name,
'y' => year, 'y' => year,
'm' => month, 'm' => month,
'd' => day, 'd' => day,
@ -56,7 +71,7 @@ class DateTime
'M' => min, 'M' => min,
'S' => sec, 'S' => sec,
'of' => offset.to_s, 'of' => offset.to_s,
'sg' => @sg, 'sg' => start,
}.to_json(*args) }.to_json(*args)
end end
end end
@ -68,7 +83,7 @@ class Range
def to_json(*args) def to_json(*args)
{ {
'json_class' => self.class.name.to_s, 'json_class' => self.class.name,
'a' => [ first, last, exclude_end? ] 'a' => [ first, last, exclude_end? ]
}.to_json(*args) }.to_json(*args)
end end
@ -80,8 +95,8 @@ class Struct
end end
def to_json(*args) def to_json(*args)
klass = self.class.name.to_s klass = self.class.name
klass.empty? and raise JSON::JSONError, "Only named structs are supported!" klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!"
{ {
'json_class' => klass, 'json_class' => klass,
'v' => values, 'v' => values,
@ -98,7 +113,7 @@ class Exception
def to_json(*args) def to_json(*args)
{ {
'json_class' => self.class.name.to_s, 'json_class' => self.class.name,
'm' => message, 'm' => message,
'b' => backtrace, 'b' => backtrace,
}.to_json(*args) }.to_json(*args)
@ -112,7 +127,7 @@ class Regexp
def to_json(*) def to_json(*)
{ {
'json_class' => self.class.name.to_s, 'json_class' => self.class.name,
'o' => options, 'o' => options,
's' => source, 's' => source,
}.to_json }.to_json

View file

@ -2,7 +2,7 @@ require 'json/version'
module JSON module JSON
class << self class << self
# If _object_ is string like parse the string and return the parsed result # If _object_ is string-like parse the string and return the parsed result
# as a Ruby data structure. Otherwise generate a JSON text from the Ruby # as a Ruby data structure. Otherwise generate a JSON text from the Ruby
# data structure object and return it. # data structure object and return it.
# #
@ -184,7 +184,8 @@ module JSON
end end
# :stopdoc: # :stopdoc:
# I want to deprecate these later, so I'll first be silent about them, and later delete them. # I want to deprecate these later, so I'll first be silent about them, and
# later delete them.
alias unparse generate alias unparse generate
module_function :unparse module_function :unparse
# :startdoc: # :startdoc:
@ -238,7 +239,7 @@ module JSON
# :startdoc: # :startdoc:
# Load a ruby data structure from a JSON _source_ and return it. A source can # Load a ruby data structure from a JSON _source_ and return it. A source can
# either be a string like object, an IO like object, or an object responding # either be a string-like object, an IO like object, or an object responding
# to the read method. If _proc_ was given, it will be called with any nested # to the read method. If _proc_ was given, it will be called with any nested
# Ruby object as an argument recursively in depth first order. # Ruby object as an argument recursively in depth first order.
# #
@ -327,7 +328,7 @@ module ::Kernel
nil nil
end end
# If _object_ is string like parse the string and return the parsed result as # If _object_ is string-like parse the string and return the parsed result as
# a Ruby data structure. Otherwise generate a JSON text from the Ruby data # a Ruby data structure. Otherwise generate a JSON text from the Ruby data
# structure object and return it. # structure object and return it.
# #
@ -351,4 +352,3 @@ class ::Class
respond_to?(:json_create) respond_to?(:json_create)
end end
end end
# vim: set et sw=2 ts=2:

View file

@ -1360,4 +1360,3 @@ module JSON
end end
end end
end end
# vim: set et sw=2 ts=2:

View file

@ -122,9 +122,8 @@ module JSON
def parse_string def parse_string
if scan(STRING) if scan(STRING)
return '' if self[1].empty? return '' if self[1].empty?
self[1].gsub(%r((?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+|\\[\x20-\xff]))n) do self[1].gsub(%r((?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+|\\[\x20-\xff]))n) do |c|
c = $& if u = UNESCAPE_MAP[$&[1]]
if u = UNESCAPE_MAP[c[1]]
u u
else # \uXXXX else # \uXXXX
bytes = '' bytes = ''

View file

@ -1,6 +1,6 @@
module JSON module JSON
# JSON version # JSON version
VERSION = '1.1.2' VERSION = '1.1.3'
VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc: VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc: VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
VERSION_MINOR = VERSION_ARRAY[1] # :nodoc: VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:

View file

@ -1 +1 @@
[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]] // No, we don't limit our depth: Moved to pass... [[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]

View file

@ -23,4 +23,3 @@ class TS_AllTests
end end
end end
Test::Unit::UI::Console::TestRunner.run(TS_AllTests) Test::Unit::UI::Console::TestRunner.run(TS_AllTests)
# vim: set et sw=2 ts=2:

View file

@ -3,6 +3,7 @@
require 'test/unit' require 'test/unit'
require 'json' require 'json'
require 'stringio'
class TC_JSON < Test::Unit::TestCase class TC_JSON < Test::Unit::TestCase
include JSON include JSON
@ -61,6 +62,12 @@ class TC_JSON < Test::Unit::TestCase
assert_equal_float [3.141], parse('[3141.0E-3]') assert_equal_float [3.141], parse('[3141.0E-3]')
assert_equal_float [-3.141], parse('[-3141.0e-3]') assert_equal_float [-3.141], parse('[-3141.0e-3]')
assert_equal_float [-3.141], parse('[-3141e-3]') assert_equal_float [-3.141], parse('[-3141e-3]')
assert_raises(ParserError) { parse('[NaN]') }
assert parse('[NaN]', :allow_nan => true).first.nan?
assert_raises(ParserError) { parse('[Infinity]') }
assert_equal [1.0/0], parse('[Infinity]', :allow_nan => true)
assert_raises(ParserError) { parse('[-Infinity]') }
assert_equal [-1.0/0], parse('[-Infinity]', :allow_nan => true)
assert_equal([""], parse('[""]')) assert_equal([""], parse('[""]'))
assert_equal(["foobar"], parse('["foobar"]')) assert_equal(["foobar"], parse('["foobar"]'))
assert_equal([{}], parse('[{}]')) assert_equal([{}], parse('[{}]'))
@ -238,18 +245,49 @@ EOT
end end
def test_nesting def test_nesting
to_deep = '[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]' assert_raises(JSON::NestingError) { JSON.parse '[[]]', :max_nesting => 1 }
assert_raises(JSON::NestingError) { JSON.parse to_deep } assert_raises(JSON::NestingError) { JSON.parser.new('[[]]', :max_nesting => 1).parse }
assert_raises(JSON::NestingError) { JSON.parser.new(to_deep).parse } assert_equal [[]], JSON.parse('[[]]', :max_nesting => 2)
assert_raises(JSON::NestingError) { JSON.parse to_deep, :max_nesting => 19 } too_deep = '[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]'
ok = JSON.parse to_deep, :max_nesting => 20 too_deep_ary = eval too_deep
assert_kind_of Array, ok assert_raises(JSON::NestingError) { JSON.parse too_deep }
ok = JSON.parse to_deep, :max_nesting => nil assert_raises(JSON::NestingError) { JSON.parser.new(too_deep).parse }
assert_kind_of Array, ok assert_raises(JSON::NestingError) { JSON.parse too_deep, :max_nesting => 19 }
ok = JSON.parse to_deep, :max_nesting => false ok = JSON.parse too_deep, :max_nesting => 20
assert_kind_of Array, ok assert_equal too_deep_ary, ok
ok = JSON.parse to_deep, :max_nesting => 0 ok = JSON.parse too_deep, :max_nesting => nil
assert_kind_of Array, ok assert_equal too_deep_ary, ok
ok = JSON.parse too_deep, :max_nesting => false
assert_equal too_deep_ary, ok
ok = JSON.parse too_deep, :max_nesting => 0
assert_equal too_deep_ary, ok
assert_raises(JSON::NestingError) { JSON.generate [[]], :max_nesting => 1 }
assert_equal '[[]]', JSON.generate([[]], :max_nesting => 2)
assert_raises(JSON::NestingError) { JSON.generate too_deep_ary }
assert_raises(JSON::NestingError) { JSON.generate too_deep_ary, :max_nesting => 19 }
ok = JSON.generate too_deep_ary, :max_nesting => 20
assert_equal too_deep, ok
ok = JSON.generate too_deep_ary, :max_nesting => nil
assert_equal too_deep, ok
ok = JSON.generate too_deep_ary, :max_nesting => false
assert_equal too_deep, ok
ok = JSON.generate too_deep_ary, :max_nesting => 0
assert_equal too_deep, ok
end
def test_load_dump
too_deep = '[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]'
assert_equal too_deep, JSON.dump(eval(too_deep))
assert_kind_of String, Marshal.dump(eval(too_deep))
assert_raises(ArgumentError) { JSON.dump(eval(too_deep), 19) }
assert_raises(ArgumentError) { Marshal.dump(eval(too_deep), 19) }
assert_equal too_deep, JSON.dump(eval(too_deep), 20)
assert_kind_of String, Marshal.dump(eval(too_deep), 20)
output = StringIO.new
JSON.dump(eval(too_deep), output)
assert_equal too_deep, output.string
output = StringIO.new
JSON.dump(eval(too_deep), output, 20)
assert_equal too_deep, output.string
end end
end end
# vim: set et sw=2 ts=2:

View file

@ -31,6 +31,10 @@ class TC_JSONAddition < Test::Unit::TestCase
end end
class B class B
def self.json_creatable?
false
end
def to_json(*args) def to_json(*args)
{ {
'json_class' => self.class.name, 'json_class' => self.class.name,
@ -50,9 +54,6 @@ class TC_JSONAddition < Test::Unit::TestCase
end end
end end
def setup
end
def test_extended_json def test_extended_json
a = A.new(666) a = A.new(666)
assert A.json_creatable? assert A.json_creatable?
@ -77,14 +78,14 @@ class TC_JSONAddition < Test::Unit::TestCase
) )
end end
def test_extended_json_fail def test_extended_json_fail1
b = B.new b = B.new
assert !B.json_creatable? assert !B.json_creatable?
json = generate(b) json = generate(b)
assert_equal({ 'json_class' => B.name }, JSON.parse(json)) assert_equal({ "json_class"=>"TC_JSONAddition::B" }, JSON.parse(json))
end end
def test_extended_json_fail def test_extended_json_fail2
c = C.new c = C.new
assert !C.json_creatable? assert !C.json_creatable?
json = generate(c) json = generate(c)
@ -111,9 +112,11 @@ EOT
assert_equal raw, raw_again assert_equal raw, raw_again
end end
MyJsonStruct = Struct.new 'MyJsonStruct', :foo, :bar
def test_core def test_core
t = Time.at(1198254128, 895990) t = Time.now
assert_equal t, JSON(JSON(t)) assert_equal t.inspect, JSON(JSON(t)).inspect
d = Date.today d = Date.today
assert_equal d, JSON(JSON(d)) assert_equal d, JSON(JSON(d))
d = DateTime.civil(2007, 6, 14, 14, 57, 10, Rational(1, 12), 2299161) d = DateTime.civil(2007, 6, 14, 14, 57, 10, Rational(1, 12), 2299161)
@ -122,8 +125,7 @@ EOT
assert_equal 1...10, JSON(JSON(1...10)) assert_equal 1...10, JSON(JSON(1...10))
assert_equal "a".."c", JSON(JSON("a".."c")) assert_equal "a".."c", JSON(JSON("a".."c"))
assert_equal "a"..."c", JSON(JSON("a"..."c")) assert_equal "a"..."c", JSON(JSON("a"..."c"))
struct = Struct.new 'MyJsonStruct', :foo, :bar s = MyJsonStruct.new 4711, 'foot'
s = struct.new 4711, 'foot'
assert_equal s, JSON(JSON(s)) assert_equal s, JSON(JSON(s))
struct = Struct.new :foo, :bar struct = Struct.new :foo, :bar
s = struct.new 4711, 'foot' s = struct.new 4711, 'foot'
@ -137,7 +139,19 @@ EOT
assert_equal e.message, e_again.message assert_equal e.message, e_again.message
assert_equal e.backtrace, e_again.backtrace assert_equal e.backtrace, e_again.backtrace
end end
assert_equal /foo/, JSON(JSON(/foo/)) assert_equal(/foo/, JSON(JSON(/foo/)))
assert_equal /foo/i, JSON(JSON(/foo/i)) assert_equal(/foo/i, JSON(JSON(/foo/i)))
end
def test_utc_datetime
now = Time.now
d = DateTime.parse(now.to_s) # usual case
assert d, JSON.parse(d.to_json)
d = DateTime.parse(now.utc.to_s) # of = 0
assert d, JSON.parse(d.to_json)
d = DateTime.civil(2008, 6, 17, 11, 48, 32, 1) # of = 1 / 12 => 1/12
assert d, JSON.parse(d.to_json)
d = DateTime.civil(2008, 6, 17, 11, 48, 32, 12) # of = 12 / 12 => 12
assert d, JSON.parse(d.to_json)
end end
end end

View file

@ -70,6 +70,7 @@ EOT
#assert s.check_circular #assert s.check_circular
h = { 1=>2 } h = { 1=>2 }
h[3] = h h[3] = h
assert_raises(JSON::CircularDatastructure) { generate(h) }
assert_raises(JSON::CircularDatastructure) { generate(h, s) } assert_raises(JSON::CircularDatastructure) { generate(h, s) }
s = JSON.state.new(:check_circular => true) s = JSON.state.new(:check_circular => true)
#assert s.check_circular #assert s.check_circular
@ -77,4 +78,22 @@ EOT
a << a a << a
assert_raises(JSON::CircularDatastructure) { generate(a, s) } assert_raises(JSON::CircularDatastructure) { generate(a, s) }
end end
def test_allow_nan
assert_raises(GeneratorError) { generate([JSON::NaN]) }
assert_equal '[NaN]', generate([JSON::NaN], :allow_nan => true)
assert_equal '[NaN]', fast_generate([JSON::NaN])
assert_raises(GeneratorError) { pretty_generate([JSON::NaN]) }
assert_equal "[\n NaN\n]", pretty_generate([JSON::NaN], :allow_nan => true)
assert_raises(GeneratorError) { generate([JSON::Infinity]) }
assert_equal '[Infinity]', generate([JSON::Infinity], :allow_nan => true)
assert_equal '[Infinity]', fast_generate([JSON::Infinity])
assert_raises(GeneratorError) { pretty_generate([JSON::Infinity]) }
assert_equal "[\n Infinity\n]", pretty_generate([JSON::Infinity], :allow_nan => true)
assert_raises(GeneratorError) { generate([JSON::MinusInfinity]) }
assert_equal '[-Infinity]', generate([JSON::MinusInfinity], :allow_nan => true)
assert_equal '[-Infinity]', fast_generate([JSON::MinusInfinity])
assert_raises(GeneratorError) { pretty_generate([JSON::MinusInfinity]) }
assert_equal "[\n -Infinity\n]", pretty_generate([JSON::MinusInfinity], :allow_nan => true)
end
end end

View file

@ -31,6 +31,10 @@ class TC_JSONRails < Test::Unit::TestCase
end end
class B class B
def self.json_creatable?
false
end
def to_json(*args) def to_json(*args)
{ {
'json_class' => self.class.name, 'json_class' => self.class.name,
@ -46,9 +50,6 @@ class TC_JSONRails < Test::Unit::TestCase
end end
end end
def setup
end
def test_extended_json def test_extended_json
a = A.new(666) a = A.new(666)
assert A.json_creatable? assert A.json_creatable?
@ -73,14 +74,14 @@ class TC_JSONRails < Test::Unit::TestCase
) )
end end
def test_extended_json_fail def test_extended_json_fail1
b = B.new b = B.new
assert !B.json_creatable? assert !B.json_creatable?
json = generate(b) json = generate(b)
assert_equal({ 'json_class' => B.name }, JSON.parse(json)) assert_equal({ 'json_class' => B.name }, JSON.parse(json))
end end
def test_extended_json_fail def test_extended_json_fail2
c = C.new # with rails addition all objects are theoretically creatable c = C.new # with rails addition all objects are theoretically creatable
assert C.json_creatable? assert C.json_creatable?
json = generate(c) json = generate(c)

View file

@ -7,9 +7,6 @@ require 'json'
class TC_JSONUnicode < Test::Unit::TestCase class TC_JSONUnicode < Test::Unit::TestCase
include JSON include JSON
def setup
end
def test_unicode def test_unicode
assert_equal '""', ''.to_json assert_equal '""', ''.to_json
assert_equal '"\\b"', "\b".to_json assert_equal '"\\b"', "\b".to_json
@ -54,7 +51,7 @@ class TC_JSONUnicode < Test::Unit::TestCase
end end
end end
assert_raises(JSON::GeneratorError) do assert_raises(JSON::GeneratorError) do
JSON.generate(["" << 0x80]) JSON.generate(["\x80"])
end end
assert_equal "\302\200", JSON.parse('["\u0080"]').first assert_equal "\302\200", JSON.parse('["\u0080"]').first
end end

View file

@ -1,7 +1,7 @@
#define RUBY_VERSION "1.9.0" #define RUBY_VERSION "1.9.0"
#define RUBY_RELEASE_DATE "2008-09-20" #define RUBY_RELEASE_DATE "2008-09-21"
#define RUBY_VERSION_CODE 190 #define RUBY_VERSION_CODE 190
#define RUBY_RELEASE_CODE 20080920 #define RUBY_RELEASE_CODE 20080921
#define RUBY_PATCHLEVEL 0 #define RUBY_PATCHLEVEL 0
#define RUBY_VERSION_MAJOR 1 #define RUBY_VERSION_MAJOR 1
@ -9,7 +9,7 @@
#define RUBY_VERSION_TEENY 0 #define RUBY_VERSION_TEENY 0
#define RUBY_RELEASE_YEAR 2008 #define RUBY_RELEASE_YEAR 2008
#define RUBY_RELEASE_MONTH 9 #define RUBY_RELEASE_MONTH 9
#define RUBY_RELEASE_DAY 20 #define RUBY_RELEASE_DAY 21
#ifdef RUBY_EXTERN #ifdef RUBY_EXTERN
RUBY_EXTERN const char ruby_version[]; RUBY_EXTERN const char ruby_version[];