java/src/json/ext/Parser.rl in json_pure-2.0.4 vs java/src/json/ext/Parser.rl in json_pure-2.1.0

- old
+ new

@@ -50,11 +50,12 @@ private int maxNesting; private boolean allowNaN; private boolean symbolizeNames; private RubyClass objectClass; private RubyClass arrayClass; - private RubyHash matchString; + private RubyClass decimalClass; + private RubyHash match_string; private static final int DEFAULT_MAX_NESTING = 100; private static final ByteList JSON_MINUS_INFINITY = new ByteList(ByteList.plain("-Infinity")); // constant names in the JSON module containing those values @@ -129,10 +130,14 @@ * <dd>Defaults to Hash. * * <dt><code>:array_class</code> * <dd>Defaults to Array. * + * <dt><code>:decimal_class</code> + * <dd>Specifies which class to use instead of the default (Float) when + * parsing decimal numbers. This class must accept a single string argument + * in its constructor. * </dl> */ @JRubyMethod(name = "new", required = 1, optional = 1, meta = true) public static IRubyObject newInstance(IRubyObject clazz, IRubyObject[] args, Block block) { Parser parser = (Parser)((RubyClass)clazz).allocate(); @@ -155,11 +160,12 @@ this.symbolizeNames = opts.getBool("symbolize_names", false); this.createId = opts.getString("create_id", getCreateId(context)); this.createAdditions = opts.getBool("create_additions", false); this.objectClass = opts.getClass("object_class", runtime.getHash()); this.arrayClass = opts.getClass("array_class", runtime.getArray()); - this.matchString = opts.getHash("match_string"); + this.decimalClass = opts.getClass("decimal_class", null); + this.match_string = opts.getHash("match_string"); if(symbolizeNames && createAdditions) { throw runtime.newArgumentError( "options :symbolize_names and :create_additions cannot be " + " used in conjunction" @@ -487,17 +493,17 @@ return -1; } return p; } - + RubyInteger createInteger(int p, int new_p) { Ruby runtime = getRuntime(); ByteList num = absSubSequence(p, new_p); return bytesToInum(runtime, num); } - + RubyInteger bytesToInum(Ruby runtime, ByteList num) { return runtime.is1_9() ? ConvertBytes.byteListToInum19(runtime, num, 10, true) : ConvertBytes.byteListToInum(runtime, num, 10, true); } @@ -523,11 +529,13 @@ int new_p = parseFloatInternal(p, pe); if (new_p == -1) { res.update(null, p); return; } - RubyFloat number = createFloat(p, new_p); + IRubyObject number = parser.decimalClass == null ? + createFloat(p, new_p) : createCustomDecimal(p, new_p); + res.update(number, new_p + 1); return; } int parseFloatInternal(int p, int pe) { @@ -538,20 +546,27 @@ %% write exec; if (cs < JSON_float_first_final) { return -1; } - + return p; } - + RubyFloat createFloat(int p, int new_p) { Ruby runtime = getRuntime(); ByteList num = absSubSequence(p, new_p); return RubyFloat.newFloat(runtime, dc.parse(num, true, runtime.is1_9())); } + IRubyObject createCustomDecimal(int p, int new_p) { + Ruby runtime = getRuntime(); + ByteList num = absSubSequence(p, new_p); + IRubyObject numString = runtime.newString(num.toString()); + return parser.decimalClass.callMethod(context, "new", numString); + } + %%{ machine JSON_string; include JSON_common; write data; @@ -614,11 +629,11 @@ } } } } - if (cs >= JSON_string_first_final && result != null) { + if (cs >= JSON_string_first_final && result != null) { if (result instanceof RubyString) { ((RubyString)result).force_encoding(context, info.utf8.get()); } res.update(result, p + 1); } else { @@ -732,10 +747,10 @@ action exit { fhold; fbreak; } - + pair = ignore* begin_name >parse_name ignore* name_separator ignore* begin_value >parse_value; next_pair = ignore* value_separator pair; main := (