summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Frank <flori@ping.de>2011-12-20 22:28:12 +0100
committerFlorian Frank <flori@ping.de>2011-12-20 22:28:12 +0100
commitdec1286737e8d9c3d61ec9f6726a88d65592f48e (patch)
tree8295668fa08d8aeadec6e9380bda960d0c2307cb
parent43460e877f3759af36bc541433ddb6b32d510116 (diff)
downloadjson-dec1286737e8d9c3d61ec9f6726a88d65592f48e.tar.gz
Support hash ducktype objects on JRuby as well
-rw-r--r--ext/json/ext/parser/parser.rl10
-rw-r--r--java/src/json/ext/OptionsReader.java8
-rw-r--r--java/src/json/ext/Parser.java71
-rw-r--r--java/src/json/ext/Parser.rl28
4 files changed, 63 insertions, 54 deletions
diff --git a/ext/json/ext/parser/parser.rl b/ext/json/ext/parser/parser.rl
index 1bee5bd..5838dac 100644
--- a/ext/json/ext/parser/parser.rl
+++ b/ext/json/ext/parser/parser.rl
@@ -167,12 +167,12 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
if (cs >= JSON_object_first_final) {
if (json->create_additions) {
- VALUE klassname;
+ VALUE klassname;
if (NIL_P(json->object_class)) {
- klassname = rb_hash_aref(*result, json->create_id);
- } else {
- klassname = rb_funcall(*result, i_aref, 1, json->create_id);
- }
+ klassname = rb_hash_aref(*result, json->create_id);
+ } else {
+ klassname = rb_funcall(*result, i_aref, 1, json->create_id);
+ }
if (!NIL_P(klassname)) {
VALUE klass = rb_funcall(mJSON, i_deep_const_get, 1, klassname);
if (RTEST(rb_funcall(klass, i_json_creatable_p, 0))) {
diff --git a/java/src/json/ext/OptionsReader.java b/java/src/json/ext/OptionsReader.java
index a0b76b1..6835735 100644
--- a/java/src/json/ext/OptionsReader.java
+++ b/java/src/json/ext/OptionsReader.java
@@ -102,13 +102,7 @@ final class OptionsReader {
IRubyObject value = get(key);
if (value == null || value.isNil()) return defaultValue;
-
- if (value instanceof RubyClass &&
- ((RubyClass)value).getAllocator() == defaultValue.getAllocator()) {
- return (RubyClass)value;
- }
- throw runtime.newTypeError(key + " option must be a subclass of "
- + defaultValue);
+ return (RubyClass)value;
}
public RubyHash getHash(String key) {
diff --git a/java/src/json/ext/Parser.java b/java/src/json/ext/Parser.java
index 7178c16..1ff25a6 100644
--- a/java/src/json/ext/Parser.java
+++ b/java/src/json/ext/Parser.java
@@ -1887,6 +1887,7 @@ static final int JSON_object_en_main = 1;
void parseObject(ParserResult res, int p, int pe) {
int cs = EVIL;
IRubyObject lastName = null;
+ boolean objectDefault = true;
if (parser.maxNesting > 0 && currentNesting > parser.maxNesting) {
throw newException(Utils.M_NESTING_ERROR,
@@ -1895,23 +1896,24 @@ static final int JSON_object_en_main = 1;
// this is guaranteed to be a RubyHash due to the earlier
// allocator test at OptionsReader#getClass
- RubyHash result;
- if (parser.objectClass != getRuntime().getHash()) {
- result = (RubyHash)parser.objectClass.newInstance(context,
- IRubyObject.NULL_ARRAY, Block.NULL_BLOCK);
- } else {
+ IRubyObject result;
+ if (parser.objectClass == getRuntime().getHash()) {
result = RubyHash.newHash(getRuntime());
+ } else {
+ objectDefault = false;
+ result = parser.objectClass.newInstance(context,
+ IRubyObject.NULL_ARRAY, Block.NULL_BLOCK);
}
-// line 1908 "Parser.java"
+// line 1910 "Parser.java"
{
cs = JSON_object_start;
}
-// line 794 "Parser.rl"
+// line 796 "Parser.rl"
-// line 1915 "Parser.java"
+// line 1917 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -1999,10 +2001,10 @@ case 1:
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
} else {
- if (parser.objectClass != getRuntime().getHash()) {
- result.callMethod(context, "[]=", new IRubyObject[] { lastName, res.result });
+ if (parser.objectClass == getRuntime().getHash()) {
+ ((RubyHash)result).op_aset(context, lastName, res.result);
} else {
- result.op_aset(context, lastName, res.result);
+ result.callMethod(context, "[]=", new IRubyObject[] { lastName, res.result });
}
{p = (( res.p))-1;}
}
@@ -2035,7 +2037,7 @@ case 1:
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 2039 "Parser.java"
+// line 2041 "Parser.java"
}
}
}
@@ -2055,10 +2057,9 @@ case 5:
break; }
}
-// line 795 "Parser.rl"
+// line 797 "Parser.rl"
if (cs < JSON_object_first_final) {
- res.update(null, p + 1);
return;
}
@@ -2066,7 +2067,13 @@ case 5:
// attempt to de-serialize object
if (parser.createAdditions) {
- IRubyObject vKlassName = result.op_aref(context, parser.createId);
+ IRubyObject vKlassName;
+ if (objectDefault) {
+ vKlassName = ((RubyHash)result).op_aref(context, parser.createId);
+ } else {
+ vKlassName = result.callMethod(context, "[]", parser.createId);
+ }
+
if (!vKlassName.isNil()) {
// might throw ArgumentError, we let it propagate
IRubyObject klass = parser.info.jsonModule.get().
@@ -2082,7 +2089,7 @@ case 5:
}
-// line 2085 "Parser.java"
+// line 2093 "Parser.java"
private static byte[] init__JSON_actions_0()
{
return new byte [] {
@@ -2186,7 +2193,7 @@ static final int JSON_error = 0;
static final int JSON_en_main = 1;
-// line 853 "Parser.rl"
+// line 861 "Parser.rl"
public IRubyObject parseStrict() {
@@ -2196,16 +2203,16 @@ static final int JSON_en_main = 1;
ParserResult res = new ParserResult();
-// line 2199 "Parser.java"
+// line 2207 "Parser.java"
{
cs = JSON_start;
}
-// line 862 "Parser.rl"
+// line 870 "Parser.rl"
p = byteList.begin();
pe = p + byteList.length();
-// line 2208 "Parser.java"
+// line 2216 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -2286,7 +2293,7 @@ case 1:
switch ( _JSON_actions[_acts++] )
{
case 0:
-// line 825 "Parser.rl"
+// line 833 "Parser.rl"
{
currentNesting = 1;
parseObject(res, p, pe);
@@ -2300,7 +2307,7 @@ case 1:
}
break;
case 1:
-// line 837 "Parser.rl"
+// line 845 "Parser.rl"
{
currentNesting = 1;
parseArray(res, p, pe);
@@ -2313,7 +2320,7 @@ case 1:
}
}
break;
-// line 2316 "Parser.java"
+// line 2324 "Parser.java"
}
}
}
@@ -2333,7 +2340,7 @@ case 5:
break; }
}
-// line 865 "Parser.rl"
+// line 873 "Parser.rl"
if (cs >= JSON_first_final && p == pe) {
return result;
@@ -2343,7 +2350,7 @@ case 5:
}
-// line 2346 "Parser.java"
+// line 2354 "Parser.java"
private static byte[] init__JSON_quirks_mode_actions_0()
{
return new byte [] {
@@ -2446,7 +2453,7 @@ static final int JSON_quirks_mode_error = 0;
static final int JSON_quirks_mode_en_main = 1;
-// line 893 "Parser.rl"
+// line 901 "Parser.rl"
public IRubyObject parseQuirksMode() {
@@ -2456,16 +2463,16 @@ static final int JSON_quirks_mode_en_main = 1;
ParserResult res = new ParserResult();
-// line 2459 "Parser.java"
+// line 2467 "Parser.java"
{
cs = JSON_quirks_mode_start;
}
-// line 902 "Parser.rl"
+// line 910 "Parser.rl"
p = byteList.begin();
pe = p + byteList.length();
-// line 2468 "Parser.java"
+// line 2476 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -2546,7 +2553,7 @@ case 1:
switch ( _JSON_quirks_mode_actions[_acts++] )
{
case 0:
-// line 879 "Parser.rl"
+// line 887 "Parser.rl"
{
parseValue(res, p, pe);
if (res.result == null) {
@@ -2558,7 +2565,7 @@ case 1:
}
}
break;
-// line 2561 "Parser.java"
+// line 2569 "Parser.java"
}
}
}
@@ -2578,7 +2585,7 @@ case 5:
break; }
}
-// line 905 "Parser.rl"
+// line 913 "Parser.rl"
if (cs >= JSON_quirks_mode_first_final && p == pe) {
return result;
diff --git a/java/src/json/ext/Parser.rl b/java/src/json/ext/Parser.rl
index bee52c8..bb6a38f 100644
--- a/java/src/json/ext/Parser.rl
+++ b/java/src/json/ext/Parser.rl
@@ -730,10 +730,10 @@ public class Parser extends RubyObject {
fhold;
fbreak;
} else {
- if (parser.objectClass != getRuntime().getHash()) {
- result.callMethod(context, "[]=", new IRubyObject[] { lastName, res.result });
+ if (parser.objectClass == getRuntime().getHash()) {
+ ((RubyHash)result).op_aset(context, lastName, res.result);
} else {
- result.op_aset(context, lastName, res.result);
+ result.callMethod(context, "[]=", new IRubyObject[] { lastName, res.result });
}
fexec res.p;
}
@@ -774,6 +774,7 @@ public class Parser extends RubyObject {
void parseObject(ParserResult res, int p, int pe) {
int cs = EVIL;
IRubyObject lastName = null;
+ boolean objectDefault = true;
if (parser.maxNesting > 0 && currentNesting > parser.maxNesting) {
throw newException(Utils.M_NESTING_ERROR,
@@ -782,26 +783,33 @@ public class Parser extends RubyObject {
// this is guaranteed to be a RubyHash due to the earlier
// allocator test at OptionsReader#getClass
- RubyHash result;
- if (parser.objectClass != getRuntime().getHash()) {
- result = (RubyHash)parser.objectClass.newInstance(context,
- IRubyObject.NULL_ARRAY, Block.NULL_BLOCK);
- } else {
+ IRubyObject result;
+ if (parser.objectClass == getRuntime().getHash()) {
result = RubyHash.newHash(getRuntime());
+ } else {
+ objectDefault = false;
+ result = parser.objectClass.newInstance(context,
+ IRubyObject.NULL_ARRAY, Block.NULL_BLOCK);
}
%% write init;
%% write exec;
if (cs < JSON_object_first_final) {
- return null;
+ return;
}
IRubyObject returnedResult = result;
// attempt to de-serialize object
if (parser.createAdditions) {
- IRubyObject vKlassName = result.op_aref(context, parser.createId);
+ IRubyObject vKlassName;
+ if (objectDefault) {
+ vKlassName = ((RubyHash)result).op_aref(context, parser.createId);
+ } else {
+ vKlassName = result.callMethod(context, "[]", parser.createId);
+ }
+
if (!vKlassName.isNil()) {
// might throw ArgumentError, we let it propagate
IRubyObject klass = parser.info.jsonModule.get().