diff --git a/java/src/json/ext/ByteListTranscoder.java b/java/src/json/ext/ByteListTranscoder.java index 0fedcabd..78d8037c 100644 --- a/java/src/json/ext/ByteListTranscoder.java +++ b/java/src/json/ext/ByteListTranscoder.java @@ -17,8 +17,6 @@ * using UTF-8 ByteLists as both input and output. */ abstract class ByteListTranscoder { - protected final ThreadContext context; - protected ByteList src; protected int srcEnd; /** Position where the last read character started */ @@ -26,7 +24,6 @@ abstract class ByteListTranscoder { /** Position of the next character to read */ protected int pos; - private OutputStream out; /** * When a character that can be copied straight into the output is found, * its index is stored on this variable, and copying is delayed until @@ -36,20 +33,15 @@ abstract class ByteListTranscoder { */ private int quoteStart = -1; - protected ByteListTranscoder(ThreadContext context) { - this.context = context; - } - - protected void init(ByteList src, OutputStream out) { - this.init(src, 0, src.length(), out); + protected void init(ByteList src) { + this.init(src, 0, src.length()); } - protected void init(ByteList src, int start, int end, OutputStream out) { + protected void init(ByteList src, int start, int end) { this.src = src; this.pos = start; this.charStart = start; this.srcEnd = end; - this.out = out; } /** @@ -70,52 +62,57 @@ private char next() { * Reads an UTF-8 character from the input and returns its code point, * while advancing the input position. * - *
Raises an {@link #invalidUtf8()} exception if an invalid byte + *
Raises an {@link #invalidUtf8(ThreadContext)} exception if an invalid byte * is found. */ - protected int readUtf8Char() { + protected int readUtf8Char(ThreadContext context) { charStart = pos; char head = next(); if (head <= 0x7f) { // 0b0xxxxxxx (ASCII) return head; } if (head <= 0xbf) { // 0b10xxxxxx - throw invalidUtf8(); // tail byte with no head + throw invalidUtf8(context); // tail byte with no head } if (head <= 0xdf) { // 0b110xxxxx - ensureMin(1); + ensureMin(context, 1); int cp = ((head & 0x1f) << 6) - | nextPart(); - if (cp < 0x0080) throw invalidUtf8(); + | nextPart(context); + if (cp < 0x0080) throw invalidUtf8(context); return cp; } if (head <= 0xef) { // 0b1110xxxx - ensureMin(2); + ensureMin(context, 2); int cp = ((head & 0x0f) << 12) - | (nextPart() << 6) - | nextPart(); - if (cp < 0x0800) throw invalidUtf8(); + | (nextPart(context) << 6) + | nextPart(context); + if (cp < 0x0800) throw invalidUtf8(context); return cp; } if (head <= 0xf7) { // 0b11110xxx - ensureMin(3); + ensureMin(context, 3); int cp = ((head & 0x07) << 18) - | (nextPart() << 12) - | (nextPart() << 6) - | nextPart(); - if (!Character.isValidCodePoint(cp)) throw invalidUtf8(); + | (nextPart(context) << 12) + | (nextPart(context) << 6) + | nextPart(context); + if (!Character.isValidCodePoint(cp)) throw invalidUtf8(context); return cp; } // 0b11111xxx? - throw invalidUtf8(); + throw invalidUtf8(context); + } + + protected int readASCIIChar() { + charStart = pos; + return next(); } /** * Throws a GeneratorError if the input list doesn't have at least this * many bytes left. */ - protected void ensureMin(int n) { - if (pos + n > srcEnd) throw incompleteUtf8(); + protected void ensureMin(ThreadContext context, int n) { + if (pos + n > srcEnd) throw incompleteUtf8(context); } /** @@ -124,10 +121,10 @@ protected void ensureMin(int n) { * *
Throws a GeneratorError if the byte is not a valid tail.
*/
- private int nextPart() {
+ private int nextPart(ThreadContext context) {
char c = next();
// tail bytes must be 0b10xxxxxx
- if ((c & 0xc0) != 0x80) throw invalidUtf8();
+ if ((c & 0xc0) != 0x80) throw invalidUtf8(context);
return c & 0x3f;
}
@@ -147,23 +144,19 @@ protected void quoteStart() {
*/
protected void quoteStop(int endPos) throws IOException {
if (quoteStart != -1) {
- out.write(src.bytes(), quoteStart, endPos - quoteStart);
+ append(src.unsafeBytes(), src.begin() + quoteStart, endPos - quoteStart);
quoteStart = -1;
}
}
- protected void append(int b) throws IOException {
- out.write(b);
- }
+ protected abstract void append(int b) throws IOException;
- protected void append(byte[] origin, int start, int length) throws IOException {
- out.write(origin, start, length);
- }
+ protected abstract void append(byte[] origin, int start, int length) throws IOException;
- protected abstract RaiseException invalidUtf8();
+ protected abstract RaiseException invalidUtf8(ThreadContext context);
- protected RaiseException incompleteUtf8() {
- return invalidUtf8();
+ protected RaiseException incompleteUtf8(ThreadContext context) {
+ return invalidUtf8(context);
}
}
diff --git a/java/src/json/ext/Generator.java b/java/src/json/ext/Generator.java
index 65c30ffa..9f5f7e86 100644
--- a/java/src/json/ext/Generator.java
+++ b/java/src/json/ext/Generator.java
@@ -6,29 +6,41 @@
package json.ext;
import org.jcodings.Encoding;
+import org.jcodings.specific.ASCIIEncoding;
+import org.jcodings.specific.USASCIIEncoding;
import org.jcodings.specific.UTF8Encoding;
import org.jruby.Ruby;
import org.jruby.RubyArray;
import org.jruby.RubyBasicObject;
import org.jruby.RubyBignum;
import org.jruby.RubyBoolean;
+import org.jruby.RubyClass;
import org.jruby.RubyFixnum;
import org.jruby.RubyFloat;
import org.jruby.RubyHash;
-import org.jruby.RubyIO;
import org.jruby.RubyString;
+import org.jruby.RubySymbol;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;
import org.jruby.exceptions.RaiseException;
+import org.jruby.util.ConvertBytes;
import org.jruby.util.IOOutputStream;
+import org.jruby.util.StringSupport;
+import org.jruby.util.TypeConverter;
+import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
-import java.nio.charset.StandardCharsets;
+import java.math.BigInteger;
+
+import static java.nio.charset.StandardCharsets.*;
public final class Generator {
+
+ private static final int IO_BUFFER_SIZE = 8192;
+
private Generator() {
throw new RuntimeException();
}
@@ -36,21 +48,28 @@ private Generator() {
/**
* Encodes the given object as a JSON string, using the given handler.
*/
- static Note that anything called indirectly (via {@link GENERIC_HANDLER})
+ * Note that anything called indirectly (via {@link #GENERIC_HANDLER})
* won't be part of the session.
*/
static class Session {
- private final ThreadContext context;
private GeneratorState state;
private IRubyObject possibleState;
private RuntimeInfo info;
private StringEncoder stringEncoder;
- private boolean tainted = false;
- private boolean untrusted = false;
-
- Session(ThreadContext context, GeneratorState state) {
- this.context = context;
+ Session(GeneratorState state) {
this.state = state;
}
- Session(ThreadContext context, IRubyObject possibleState) {
- this.context = context;
+ Session(IRubyObject possibleState) {
this.possibleState = possibleState == null || possibleState.isNil()
? null : possibleState;
}
- public ThreadContext getContext() {
- return context;
- }
-
- public Ruby getRuntime() {
- return context.getRuntime();
- }
-
- public GeneratorState getState() {
+ public GeneratorState getState(ThreadContext context) {
if (state == null) {
- state = GeneratorState.fromState(context, getInfo(), possibleState);
+ state = GeneratorState.fromState(context, getInfo(context), possibleState);
}
return state;
}
- public RuntimeInfo getInfo() {
- if (info == null) info = RuntimeInfo.forRuntime(getRuntime());
+ public RuntimeInfo getInfo(ThreadContext context) {
+ if (info == null) info = RuntimeInfo.forRuntime(context.runtime);
return info;
}
- public StringEncoder getStringEncoder() {
+ public StringEncoder getStringEncoder(ThreadContext context) {
if (stringEncoder == null) {
- stringEncoder = new StringEncoder(context, getState().asciiOnly(), getState().scriptSafe());
+ GeneratorState state = getState(context);
+ stringEncoder = new StringEncoder(state.asciiOnly(), state.scriptSafe());
}
return stringEncoder;
}
-
- public void infectBy(IRubyObject object) {
- if (object.isTaint()) tainted = true;
- if (object.isUntrusted()) untrusted = true;
- }
-
- public This method creates a JSON text from the result of a call to
* {@link #to_json_raw_object} of this String.
*/
- @JRubyMethod(rest=true)
- public static IRubyObject to_json_raw(ThreadContext context,
- IRubyObject vSelf, IRubyObject[] args) {
+ @JRubyMethod
+ public static IRubyObject to_json_raw(ThreadContext context, IRubyObject vSelf) {
RubyHash obj = toJsonRawObject(context, Utils.ensureString(vSelf));
- return Generator.generateJson(context, obj,
- Generator.HASH_HANDLER, args);
+ return Generator.generateJson(context, obj, Generator.HASH_HANDLER);
+ }
+
+ @JRubyMethod
+ public static IRubyObject to_json_raw(ThreadContext context, IRubyObject vSelf, IRubyObject arg0) {
+ RubyHash obj = toJsonRawObject(context, Utils.ensureString(vSelf));
+ return Generator.generateJson(context, obj, Generator.HASH_HANDLER, arg0);
}
/**
@@ -128,15 +145,14 @@ public static IRubyObject to_json_raw(ThreadContext context,
* method should be used if you want to convert raw strings to JSON
* instead of UTF-8 strings, e.g. binary data.
*/
- @JRubyMethod(rest=true)
- public static IRubyObject to_json_raw_object(ThreadContext context,
- IRubyObject vSelf, IRubyObject[] args) {
+ @JRubyMethod
+ public static IRubyObject to_json_raw_object(ThreadContext context, IRubyObject vSelf) {
return toJsonRawObject(context, Utils.ensureString(vSelf));
}
private static RubyHash toJsonRawObject(ThreadContext context,
RubyString self) {
- Ruby runtime = context.getRuntime();
+ Ruby runtime = context.runtime;
RubyHash result = RubyHash.newHash(runtime);
IRubyObject createId = RuntimeInfo.forRuntime(runtime)
@@ -154,11 +170,10 @@ private static RubyHash toJsonRawObject(ThreadContext context,
return result;
}
- @JRubyMethod(required=1, module=true)
- public static IRubyObject included(ThreadContext context,
- IRubyObject vSelf, IRubyObject module) {
- RuntimeInfo info = RuntimeInfo.forRuntime(context.getRuntime());
- return module.callMethod(context, "extend", info.stringExtendModule.get());
+ @JRubyMethod(module=true)
+ public static IRubyObject included(ThreadContext context, IRubyObject extendModule, IRubyObject module) {
+ RuntimeInfo info = RuntimeInfo.forRuntime(context.runtime);
+ return module.callMethod(context, "extend", ((RubyModule) extendModule).getConstant("Extend"));
}
}
@@ -170,10 +185,10 @@ public static class StringExtend {
* array for the key "raw"). The Ruby String can be created by this
* module method.
*/
- @JRubyMethod(required=1)
+ @JRubyMethod
public static IRubyObject json_create(ThreadContext context,
IRubyObject vSelf, IRubyObject vHash) {
- Ruby runtime = context.getRuntime();
+ Ruby runtime = context.runtime;
RubyHash o = vHash.convertToHash();
IRubyObject rawData = o.fastARef(runtime.newString("raw"));
if (rawData == null) {
@@ -195,37 +210,50 @@ public static IRubyObject json_create(ThreadContext context,
}
public static class RbTrue {
- @JRubyMethod(rest=true)
- public static IRubyObject to_json(ThreadContext context,
- IRubyObject vSelf, IRubyObject[] args) {
- return Generator.generateJson(context, (RubyBoolean)vSelf,
- Generator.TRUE_HANDLER, args);
+ @JRubyMethod
+ public static IRubyObject to_json(ThreadContext context, IRubyObject vSelf) {
+ return Generator.generateJson(context, (RubyBoolean)vSelf, Generator.TRUE_HANDLER);
+ }
+
+ @JRubyMethod
+ public static IRubyObject to_json(ThreadContext context, IRubyObject vSelf, IRubyObject arg0) {
+ return Generator.generateJson(context, (RubyBoolean)vSelf, Generator.TRUE_HANDLER, arg0);
}
}
public static class RbFalse {
- @JRubyMethod(rest=true)
- public static IRubyObject to_json(ThreadContext context,
- IRubyObject vSelf, IRubyObject[] args) {
- return Generator.generateJson(context, (RubyBoolean)vSelf,
- Generator.FALSE_HANDLER, args);
+ @JRubyMethod
+ public static IRubyObject to_json(ThreadContext context, IRubyObject vSelf) {
+ return Generator.generateJson(context, (RubyBoolean)vSelf, Generator.FALSE_HANDLER);
+ }
+
+ @JRubyMethod
+ public static IRubyObject to_json(ThreadContext context, IRubyObject vSelf, IRubyObject arg0) {
+ return Generator.generateJson(context, (RubyBoolean)vSelf, Generator.FALSE_HANDLER, arg0);
}
}
public static class RbNil {
- @JRubyMethod(rest=true)
- public static IRubyObject to_json(ThreadContext context,
- IRubyObject vSelf, IRubyObject[] args) {
- return Generator.generateJson(context, vSelf,
- Generator.NIL_HANDLER, args);
+ @JRubyMethod
+ public static IRubyObject to_json(ThreadContext context, IRubyObject vSelf) {
+ return Generator.generateJson(context, vSelf, Generator.NIL_HANDLER);
+ }
+
+ @JRubyMethod
+ public static IRubyObject to_json(ThreadContext context, IRubyObject vSelf, IRubyObject arg0) {
+ return Generator.generateJson(context, vSelf, Generator.NIL_HANDLER, arg0);
}
}
public static class RbObject {
- @JRubyMethod(rest=true)
- public static IRubyObject to_json(ThreadContext context,
- IRubyObject self, IRubyObject[] args) {
- return RbString.to_json(context, self.asString(), args);
+ @JRubyMethod
+ public static IRubyObject to_json(ThreadContext context, IRubyObject self) {
+ return RbString.to_json(context, self.asString());
+ }
+
+ @JRubyMethod
+ public static IRubyObject to_json(ThreadContext context, IRubyObject self, IRubyObject arg0) {
+ return RbString.to_json(context, self.asString(), arg0);
}
}
}
diff --git a/java/src/json/ext/GeneratorService.java b/java/src/json/ext/GeneratorService.java
index 1500c412..7d3f86e5 100644
--- a/java/src/json/ext/GeneratorService.java
+++ b/java/src/json/ext/GeneratorService.java
@@ -23,7 +23,8 @@ public boolean basicLoad(Ruby runtime) throws IOException {
runtime.getLoadService().require("json/common");
RuntimeInfo info = RuntimeInfo.initRuntime(runtime);
- info.jsonModule = new WeakReference
* Instantiates a new
* This class does not perform the actual parsing, just acts as an interface
- * to Ruby code. When the {@link #parse()} method is invoked, a
+ * to Ruby code. When the {@link #parse(ThreadContext)} method is invoked, a
* Parser.ParserSession object is instantiated, which handles the process.
*
* @author mernen
@@ -71,11 +73,7 @@ public class Parser extends RubyObject {
private static final String CONST_INFINITY = "Infinity";
private static final String CONST_MINUS_INFINITY = "MinusInfinity";
- static final ObjectAllocator ALLOCATOR = new ObjectAllocator() {
- public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
- return new Parser(runtime, klazz);
- }
- };
+ static final ObjectAllocator ALLOCATOR = Parser::new;
/**
* Multiple-value return for internal parser methods.
@@ -113,42 +111,42 @@ public Parser(Ruby runtime, RubyClass metaClass) {
*
*
*
*
*
*
*
*
* This class does not perform the actual parsing, just acts as an interface
- * to Ruby code. When the {@link #parse()} method is invoked, a
+ * to Ruby code. When the {@link #parse(ThreadContext)} method is invoked, a
* Parser.ParserSession object is instantiated, which handles the process.
*
* @author mernen
@@ -69,11 +71,7 @@ public class Parser extends RubyObject {
private static final String CONST_INFINITY = "Infinity";
private static final String CONST_MINUS_INFINITY = "MinusInfinity";
- static final ObjectAllocator ALLOCATOR = new ObjectAllocator() {
- public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
- return new Parser(runtime, klazz);
- }
- };
+ static final ObjectAllocator ALLOCATOR = Parser::new;
/**
* Multiple-value return for internal parser methods.
@@ -111,42 +109,42 @@ public class Parser extends RubyObject {
*
*
*
*
*
*
*
*
* Object#to_json
): coerces the object
@@ -460,15 +484,15 @@ void generate(Session session, RubyString object, OutputStream buffer) throws IO
static final HandlerJSON::Generator::GeneratorMethods
)
*/
static void populate(RuntimeInfo info, RubyModule module) {
@@ -45,65 +44,79 @@ static void populate(RuntimeInfo info, RubyModule module) {
defineMethods(module, "String", RbString.class);
defineMethods(module, "TrueClass", RbTrue.class);
- info.stringExtendModule = new WeakReferenceopts
is a State
* object, it is just returned.
- * @param clazzParam The receiver of the method call
- * ({@link RubyClass} State
)
+ * @param context The current thread context
+ * @param klass The receiver of the method call ({@link RubyClass} State
)
* @param opts The object to use as a base for the new State
- * @param block The block passed to the method
* @return A GeneratorState
as determined above
*/
@JRubyMethod(meta=true)
- public static IRubyObject from_state(ThreadContext context,
- IRubyObject klass, IRubyObject opts) {
+ public static IRubyObject from_state(ThreadContext context, IRubyObject klass, IRubyObject opts) {
return fromState(context, opts);
}
@@ -144,7 +138,7 @@ public static IRubyObject generate(ThreadContext context, IRubyObject klass, IRu
}
static GeneratorState fromState(ThreadContext context, IRubyObject opts) {
- return fromState(context, RuntimeInfo.forRuntime(context.getRuntime()), opts);
+ return fromState(context, RuntimeInfo.forRuntime(context.runtime), opts);
}
static GeneratorState fromState(ThreadContext context, RuntimeInfo info,
@@ -155,9 +149,8 @@ static GeneratorState fromState(ThreadContext context, RuntimeInfo info,
if (klass.isInstance(opts)) return (GeneratorState)opts;
// if the given parameter is a Hash, pass it to the instantiator
- if (context.getRuntime().getHash().isInstance(opts)) {
- return (GeneratorState)klass.newInstance(context,
- new IRubyObject[] {opts}, Block.NULL_BLOCK);
+ if (context.runtime.getHash().isInstance(opts)) {
+ return (GeneratorState)klass.newInstance(context, opts, Block.NULL_BLOCK);
}
}
@@ -167,9 +160,9 @@ static GeneratorState fromState(ThreadContext context, RuntimeInfo info,
/**
* State#initialize(opts = {})
- *
+ * State
object, configured by opts
.
- *
+ * opts
can have the following keys:
*
*
@@ -194,15 +187,21 @@ static GeneratorState fromState(ThreadContext context, RuntimeInfo info,
*
true
if U+2028, U+2029 and forward slashes should be escaped
* in the json output to make it safe to include in a JavaScript tag (default: false
)
*/
- @JRubyMethod(optional=1, visibility=Visibility.PRIVATE)
- public IRubyObject initialize(ThreadContext context, IRubyObject[] args) {
- _configure(context, args.length > 0 ? args[0] : null);
+ @JRubyMethod(visibility=Visibility.PRIVATE)
+ public IRubyObject initialize(ThreadContext context) {
+ _configure(context, null);
+ return this;
+ }
+
+ @JRubyMethod(visibility=Visibility.PRIVATE)
+ public IRubyObject initialize(ThreadContext context, IRubyObject arg0) {
+ _configure(context, arg0);
return this;
}
@JRubyMethod
public IRubyObject initialize_copy(ThreadContext context, IRubyObject vOrig) {
- Ruby runtime = context.getRuntime();
+ Ruby runtime = context.runtime;
if (!(vOrig instanceof GeneratorState)) {
throw runtime.newTypeError(vOrig, getType());
}
@@ -231,7 +230,7 @@ public IRubyObject initialize_copy(ThreadContext context, IRubyObject vOrig) {
@JRubyMethod(visibility = Visibility.PRIVATE)
public IRubyObject _generate(ThreadContext context, IRubyObject obj, IRubyObject io) {
IRubyObject result = Generator.generateJson(context, obj, this, io);
- RuntimeInfo info = RuntimeInfo.forRuntime(context.getRuntime());
+ RuntimeInfo info = RuntimeInfo.forRuntime(context.runtime);
if (!(result instanceof RubyString)) {
return result;
}
@@ -239,25 +238,16 @@ public IRubyObject _generate(ThreadContext context, IRubyObject obj, IRubyObject
RubyString resultString = result.convertToString();
if (resultString.getEncoding() != UTF8Encoding.INSTANCE) {
if (resultString.isFrozen()) {
- resultString = resultString.strDup(context.getRuntime());
+ resultString = resultString.strDup(context.runtime);
}
- resultString.force_encoding(context, info.utf8.get());
+ resultString.setEncoding(UTF8Encoding.INSTANCE);
+ resultString.clearCodeRange();
}
return resultString;
}
- private static boolean matchClosingBrace(ByteList bl, int pos, int len,
- int brace) {
- for (int endPos = len - 1; endPos > pos; endPos--) {
- int b = bl.get(endPos);
- if (Character.isWhitespace(b)) continue;
- return b == brace;
- }
- return false;
- }
-
- @JRubyMethod(name="[]", required=1)
+ @JRubyMethod(name="[]")
public IRubyObject op_aref(ThreadContext context, IRubyObject vName) {
String name = vName.asJavaString();
if (getMetaClass().isMethodBound(name, true)) {
@@ -268,16 +258,16 @@ public IRubyObject op_aref(ThreadContext context, IRubyObject vName) {
}
}
- @JRubyMethod(name="[]=", required=2)
+ @JRubyMethod(name="[]=")
public IRubyObject op_aset(ThreadContext context, IRubyObject vName, IRubyObject value) {
String name = vName.asJavaString();
String nameWriter = name + "=";
if (getMetaClass().isMethodBound(nameWriter, true)) {
- return send(context, context.getRuntime().newString(nameWriter), value, Block.NULL_BLOCK);
+ return send(context, context.runtime.newString(nameWriter), value, Block.NULL_BLOCK);
} else {
getInstanceVariables().setInstanceVariable("@" + name, value);
}
- return context.getRuntime().getNil();
+ return context.nil;
}
public ByteList getIndent() {
@@ -286,7 +276,7 @@ public ByteList getIndent() {
@JRubyMethod(name="indent")
public RubyString indent_get(ThreadContext context) {
- return context.getRuntime().newString(indent);
+ return context.runtime.newString(indent);
}
@JRubyMethod(name="indent=")
@@ -301,7 +291,7 @@ public ByteList getSpace() {
@JRubyMethod(name="space")
public RubyString space_get(ThreadContext context) {
- return context.getRuntime().newString(space);
+ return context.runtime.newString(space);
}
@JRubyMethod(name="space=")
@@ -316,7 +306,7 @@ public ByteList getSpaceBefore() {
@JRubyMethod(name="space_before")
public RubyString space_before_get(ThreadContext context) {
- return context.getRuntime().newString(spaceBefore);
+ return context.runtime.newString(spaceBefore);
}
@JRubyMethod(name="space_before=")
@@ -332,7 +322,7 @@ public ByteList getObjectNl() {
@JRubyMethod(name="object_nl")
public RubyString object_nl_get(ThreadContext context) {
- return context.getRuntime().newString(objectNl);
+ return context.runtime.newString(objectNl);
}
@JRubyMethod(name="object_nl=")
@@ -348,7 +338,7 @@ public ByteList getArrayNl() {
@JRubyMethod(name="array_nl")
public RubyString array_nl_get(ThreadContext context) {
- return context.getRuntime().newString(arrayNl);
+ return context.runtime.newString(arrayNl);
}
@JRubyMethod(name="array_nl=")
@@ -360,19 +350,12 @@ public IRubyObject array_nl_set(ThreadContext context,
@JRubyMethod(name="check_circular?")
public RubyBoolean check_circular_p(ThreadContext context) {
- return context.getRuntime().newBoolean(maxNesting != 0);
- }
-
- /**
- * Returns the maximum level of nesting configured for this state.
- */
- public int getMaxNesting() {
- return maxNesting;
+ return RubyBoolean.newBoolean(context, maxNesting != 0);
}
@JRubyMethod(name="max_nesting")
public RubyInteger max_nesting_get(ThreadContext context) {
- return context.getRuntime().newFixnum(maxNesting);
+ return context.runtime.newFixnum(maxNesting);
}
@JRubyMethod(name="max_nesting=")
@@ -390,7 +373,7 @@ public boolean scriptSafe() {
@JRubyMethod(name="script_safe", alias="escape_slash")
public RubyBoolean script_safe_get(ThreadContext context) {
- return context.getRuntime().newBoolean(scriptSafe);
+ return RubyBoolean.newBoolean(context, scriptSafe);
}
@JRubyMethod(name="script_safe=", alias="escape_slash=")
@@ -401,7 +384,7 @@ public IRubyObject script_safe_set(IRubyObject script_safe) {
@JRubyMethod(name="script_safe?", alias="escape_slash?")
public RubyBoolean script_safe_p(ThreadContext context) {
- return context.getRuntime().newBoolean(scriptSafe);
+ return RubyBoolean.newBoolean(context, scriptSafe);
}
/**
@@ -413,7 +396,7 @@ public boolean strict() {
@JRubyMethod(name={"strict","strict?"})
public RubyBoolean strict_get(ThreadContext context) {
- return context.getRuntime().newBoolean(strict);
+ return RubyBoolean.newBoolean(context, strict);
}
@JRubyMethod(name="strict=")
@@ -428,7 +411,7 @@ public boolean allowNaN() {
@JRubyMethod(name="allow_nan?")
public RubyBoolean allow_nan_p(ThreadContext context) {
- return context.getRuntime().newBoolean(allowNaN);
+ return RubyBoolean.newBoolean(context, allowNaN);
}
public boolean asciiOnly() {
@@ -437,12 +420,12 @@ public boolean asciiOnly() {
@JRubyMethod(name="ascii_only?")
public RubyBoolean ascii_only_p(ThreadContext context) {
- return context.getRuntime().newBoolean(asciiOnly);
+ return RubyBoolean.newBoolean(context, asciiOnly);
}
@JRubyMethod(name="buffer_initial_length")
public RubyInteger buffer_initial_length_get(ThreadContext context) {
- return context.getRuntime().newFixnum(bufferInitialLength);
+ return context.runtime.newFixnum(bufferInitialLength);
}
@JRubyMethod(name="buffer_initial_length=")
@@ -458,7 +441,7 @@ public int getDepth() {
@JRubyMethod(name="depth")
public RubyInteger depth_get(ThreadContext context) {
- return context.getRuntime().newFixnum(depth);
+ return context.runtime.newFixnum(depth);
}
@JRubyMethod(name="depth=")
@@ -469,9 +452,8 @@ public IRubyObject depth_set(IRubyObject vDepth) {
private ByteList prepareByteList(ThreadContext context, IRubyObject value) {
RubyString str = value.convertToString();
- RuntimeInfo info = RuntimeInfo.forRuntime(context.getRuntime());
- if (str.encoding(context) != info.utf8.get()) {
- str = (RubyString)str.encode(context, info.utf8.get());
+ if (str.getEncoding() != UTF8Encoding.INSTANCE) {
+ str = (RubyString)str.encode(context, context.runtime.getEncodingService().convertEncodingToRubyEncoding(UTF8Encoding.INSTANCE));
}
return str.getByteList().dup();
}
@@ -527,7 +509,7 @@ public IRubyObject _configure(ThreadContext context, IRubyObject vOpts) {
*/
@JRubyMethod(alias = "to_hash")
public RubyHash to_h(ThreadContext context) {
- Ruby runtime = context.getRuntime();
+ Ruby runtime = context.runtime;
RubyHash result = RubyHash.newHash(runtime);
result.op_aset(context, runtime.newSymbol("indent"), indent_get(context));
@@ -548,26 +530,24 @@ public RubyHash to_h(ThreadContext context) {
return result;
}
- public int increaseDepth() {
+ public int increaseDepth(ThreadContext context) {
depth++;
- checkMaxNesting();
+ checkMaxNesting(context);
return depth;
}
- public int decreaseDepth() {
- return --depth;
+ public void decreaseDepth() {
+ --depth;
}
/**
* Checks if the current depth is allowed as per this state's options.
- * @param context
- * @param depth The current depth
+ * @param context The current context
*/
- private void checkMaxNesting() {
+ private void checkMaxNesting(ThreadContext context) {
if (maxNesting != 0 && depth > maxNesting) {
depth--;
- throw Utils.newException(getRuntime().getCurrentContext(),
- Utils.M_NESTING_ERROR, "nesting of " + depth + " is too deep");
+ throw Utils.newException(context, Utils.M_NESTING_ERROR, "nesting of " + depth + " is too deep");
}
}
}
diff --git a/java/src/json/ext/OptionsReader.java b/java/src/json/ext/OptionsReader.java
index 70426d42..ff976c38 100644
--- a/java/src/json/ext/OptionsReader.java
+++ b/java/src/json/ext/OptionsReader.java
@@ -5,6 +5,7 @@
*/
package json.ext;
+import org.jcodings.specific.UTF8Encoding;
import org.jruby.Ruby;
import org.jruby.RubyClass;
import org.jruby.RubyHash;
@@ -22,7 +23,7 @@ final class OptionsReader {
OptionsReader(ThreadContext context, IRubyObject vOpts) {
this.context = context;
- this.runtime = context.getRuntime();
+ this.runtime = context.runtime;
if (vOpts == null || vOpts.isNil()) {
opts = null;
} else if (vOpts.respondsTo("to_hash")) {
@@ -41,7 +42,7 @@ private RuntimeInfo getRuntimeInfo() {
}
/**
- * Efficiently looks up items with a {@link RubySymbol Symbol} key
+ * Efficiently looks up items with a {@link org.jruby.RubySymbol Symbol} key
* @param key The Symbol name to look up for
* @return The item in the {@link RubyHash Hash}, or null
* if not found
@@ -69,7 +70,7 @@ int getInt(String key, int defaultValue) {
* @param key The Symbol name to look up for
* @return null
if the key is not in the Hash or if
* its value evaluates to false
- * @throws RaiseException TypeError
if the value does not
+ * @throws org.jruby.exceptions.RaiseException TypeError
if the value does not
* evaluate to false
and can't be
* converted to string
*/
@@ -83,9 +84,8 @@ RubyString getString(String key, RubyString defaultValue) {
if (value == null || !value.isTrue()) return defaultValue;
RubyString str = value.convertToString();
- RuntimeInfo info = getRuntimeInfo();
- if (str.encoding(context) != info.utf8.get()) {
- str = (RubyString)str.encode(context, info.utf8.get());
+ if (str.getEncoding() != UTF8Encoding.INSTANCE) {
+ str = (RubyString)str.encode(context, context.runtime.getEncodingService().convertEncodingToRubyEncoding(UTF8Encoding.INSTANCE));
}
return str;
}
diff --git a/java/src/json/ext/Parser.java b/java/src/json/ext/Parser.java
index 74037d37..47e66795 100644
--- a/java/src/json/ext/Parser.java
+++ b/java/src/json/ext/Parser.java
@@ -7,10 +7,12 @@
*/
package json.ext;
+import org.jcodings.Encoding;
+import org.jcodings.specific.ASCIIEncoding;
+import org.jcodings.specific.UTF8Encoding;
import org.jruby.Ruby;
import org.jruby.RubyArray;
import org.jruby.RubyClass;
-import org.jruby.RubyEncoding;
import org.jruby.RubyFloat;
import org.jruby.RubyHash;
import org.jruby.RubyInteger;
@@ -20,13 +22,13 @@
import org.jruby.exceptions.JumpException;
import org.jruby.exceptions.RaiseException;
import org.jruby.runtime.Block;
+import org.jruby.runtime.Helpers;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.Visibility;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;
import org.jruby.util.ConvertBytes;
-import org.jruby.util.ConvertDouble;
import java.util.function.BiFunction;
@@ -41,7 +43,7 @@
* This is performed for you when you include "json/ext"
.
*
* source
.
* It will be configured by the opts
Hash.
* opts
can have the following keys:
- *
+ *
*
*/
- @JRubyMethod(name = "new", required = 1, optional = 1, meta = true)
- public static IRubyObject newInstance(IRubyObject clazz, IRubyObject[] args, Block block) {
+ @JRubyMethod(name = "new", meta = true)
+ public static IRubyObject newInstance(IRubyObject clazz, IRubyObject arg0, Block block) {
Parser parser = (Parser)((RubyClass)clazz).allocate();
- parser.callInit(args, block);
+ parser.callInit(arg0, block);
+
+ return parser;
+ }
+
+ @JRubyMethod(name = "new", meta = true)
+ public static IRubyObject newInstance(IRubyObject clazz, IRubyObject arg0, IRubyObject arg1, Block block) {
+ Parser parser = (Parser)((RubyClass)clazz).allocate();
+
+ parser.callInit(arg0, arg1, block);
return parser;
}
@JRubyMethod(meta=true)
public static IRubyObject parse(ThreadContext context, IRubyObject clazz, IRubyObject source, IRubyObject opts) {
- IRubyObject[] args = new IRubyObject[] {source, opts};
Parser parser = (Parser)((RubyClass)clazz).allocate();
- parser.callInit(args, null);
+ parser.callInit(source, opts, null);
return parser.parse(context);
}
- @JRubyMethod(required = 1, optional = 1, visibility = Visibility.PRIVATE)
- public IRubyObject initialize(ThreadContext context, IRubyObject[] args) {
- Ruby runtime = context.getRuntime();
+ @JRubyMethod(visibility = Visibility.PRIVATE)
+ public IRubyObject initialize(ThreadContext context, IRubyObject arg0) {
+ return initialize(context, arg0, null);
+ }
+
+ @JRubyMethod(visibility = Visibility.PRIVATE)
+ public IRubyObject initialize(ThreadContext context, IRubyObject arg0, IRubyObject arg1) {
+ Ruby runtime = context.runtime;
if (this.vSource != null) {
throw runtime.newTypeError("already initialized instance");
- }
+ }
- OptionsReader opts = new OptionsReader(context, args.length > 1 ? args[1] : null);
+ OptionsReader opts = new OptionsReader(context, arg1);
this.maxNesting = opts.getInt("max_nesting", DEFAULT_MAX_NESTING);
this.allowNaN = opts.getBool("allow_nan", false);
this.allowTrailingComma = opts.getBool("allow_trailing_comma", false);
@@ -215,12 +226,9 @@ public IRubyObject initialize(ThreadContext context, IRubyObject[] args) {
}
if(symbolizeNames && createAdditions) {
- throw runtime.newArgumentError(
- "options :symbolize_names and :create_additions cannot be " +
- " used in conjunction"
- );
+ throw runtime.newArgumentError("options :symbolize_names and :create_additions cannot be used in conjunction");
}
- this.vSource = args[0].convertToString();
+ this.vSource = arg0.convertToString();
this.vSource = convertEncoding(context, vSource);
return this;
@@ -232,44 +240,17 @@ public IRubyObject initialize(ThreadContext context, IRubyObject[] args) {
* Returns the source string if no conversion is needed.
*/
private RubyString convertEncoding(ThreadContext context, RubyString source) {
- RubyEncoding encoding = (RubyEncoding)source.encoding(context);
- if (encoding == info.ascii8bit.get()) {
+ Encoding encoding = source.getEncoding();
+ if (encoding == ASCIIEncoding.INSTANCE) {
source = (RubyString) source.dup();
- source.force_encoding(context, info.utf8.get());
- } else {
- source = (RubyString) source.encode(context, info.utf8.get());
+ source.setEncoding(UTF8Encoding.INSTANCE);
+ source.clearCodeRange();
+ } else if (encoding != UTF8Encoding.INSTANCE) {
+ source = (RubyString) source.encode(context, context.runtime.getEncodingService().convertEncodingToRubyEncoding(UTF8Encoding.INSTANCE));
}
return source;
}
- /**
- * Checks the first four bytes of the given ByteList to infer its encoding,
- * using the principle demonstrated on section 3 of RFC 4627 (JSON).
- */
- private static String sniffByteList(ByteList bl) {
- if (bl.length() < 4) return null;
- if (bl.get(0) == 0 && bl.get(2) == 0) {
- return bl.get(1) == 0 ? "utf-32be" : "utf-16be";
- }
- if (bl.get(1) == 0 && bl.get(3) == 0) {
- return bl.get(2) == 0 ? "utf-32le" : "utf-16le";
- }
- return null;
- }
-
- /**
- * Assumes the given (binary) RubyString to be in the given encoding, then
- * converts it to UTF-8.
- */
- private RubyString reinterpretEncoding(ThreadContext context,
- RubyString str, String sniffedEncoding) {
- RubyEncoding actualEncoding = info.getEncoding(context, sniffedEncoding);
- RubyEncoding targetEncoding = info.utf8.get();
- RubyString dup = (RubyString)str.dup();
- dup.force_encoding(context, actualEncoding);
- return (RubyString)dup.encode_bang(context, targetEncoding);
- }
-
/**
* :max_nesting
* :max_nesting => false|nil|0
,
* it defaults to 100.
- *
+ * :allow_nan
* true
, allow NaN
,
* Infinity
and -Infinity
in defiance of RFC 4627
* to be parsed by the Parser. This option defaults to false
.
- *
+ * :allow_trailing_comma
* true
, allow arrays and objects with a trailing
* comma in defiance of RFC 4627 to be parsed by the Parser.
* This option defaults to false
.
- *
+ * :symbolize_names
* true
, returns symbols for the names (keys) in
* a JSON object. Otherwise strings are returned, which is also the default.
- *
+ * :create_additions
* false
, the Parser doesn't create additions
* even if a matching class and create_id
was found. This option
* defaults to true
.
- *
+ * :object_class
* new
without arguments, and return an object that respond to []=
.
- *
+ * :array_class
* new
without arguments, and return an object that respond to <<
.
- *
+ * :decimal_class
* Parser#parse()
*
@@ -278,7 +259,7 @@ private RubyString reinterpretEncoding(ThreadContext context,
*/
@JRubyMethod
public IRubyObject parse(ThreadContext context) {
- return new ParserSession(this, context, info).parse();
+ return new ParserSession(this, context, info).parse(context);
}
/**
@@ -288,15 +269,15 @@ public IRubyObject parse(ThreadContext context) {
* used to construct this Parser.
*/
@JRubyMethod(name = "source")
- public IRubyObject source_get() {
- return checkAndGetSource().dup();
+ public IRubyObject source_get(ThreadContext context) {
+ return checkAndGetSource(context).dup();
}
- public RubyString checkAndGetSource() {
+ public RubyString checkAndGetSource(ThreadContext context) {
if (vSource != null) {
return vSource;
} else {
- throw getRuntime().newTypeError("uninitialized instance");
+ throw context.runtime.newTypeError("uninitialized instance");
}
}
@@ -335,47 +316,35 @@ private IRubyObject createCustomDecimal(final ThreadContext context, final ByteL
@SuppressWarnings("fallthrough")
private static class ParserSession {
private final Parser parser;
- private final ThreadContext context;
private final RuntimeInfo info;
private final ByteList byteList;
private final ByteList view;
private final byte[] data;
private final StringDecoder decoder;
private int currentNesting = 0;
- private final DoubleConverter dc;
-
- // initialization value for all state variables.
- // no idea about the origins of this value, ask Flori ;)
- private static final int EVIL = 0x666;
private ParserSession(Parser parser, ThreadContext context, RuntimeInfo info) {
this.parser = parser;
- this.context = context;
this.info = info;
- this.byteList = parser.checkAndGetSource().getByteList();
+ this.byteList = parser.checkAndGetSource(context).getByteList();
this.data = byteList.unsafeBytes();
this.view = new ByteList(data, false);
- this.decoder = new StringDecoder(context);
- this.dc = new DoubleConverter();
+ this.decoder = new StringDecoder();
}
- private RaiseException unexpectedToken(int absStart, int absEnd) {
- RubyString msg = getRuntime().newString("unexpected token at '")
+ private RaiseException unexpectedToken(ThreadContext context, int absStart, int absEnd) {
+ RubyString msg = context.runtime.newString("unexpected token at '")
.cat(data, absStart, Math.min(absEnd - absStart, 32))
.cat((byte)'\'');
- return newException(Utils.M_PARSER_ERROR, msg);
- }
-
- private Ruby getRuntime() {
- return context.getRuntime();
+ return newException(context, Utils.M_PARSER_ERROR, msg);
}
-// line 397 "Parser.rl"
+// line 366 "Parser.rl"
-// line 379 "Parser.java"
+// line 348 "Parser.java"
private static byte[] init__JSON_value_actions_0()
{
return new byte [] {
@@ -489,22 +458,22 @@ private static byte[] init__JSON_value_from_state_actions_0()
static final int JSON_value_en_main = 1;
-// line 503 "Parser.rl"
+// line 472 "Parser.rl"
- void parseValue(ParserResult res, int p, int pe) {
- int cs = EVIL;
+ void parseValue(ThreadContext context, ParserResult res, int p, int pe) {
+ int cs;
IRubyObject result = null;
-// line 501 "Parser.java"
+// line 470 "Parser.java"
{
cs = JSON_value_start;
}
-// line 510 "Parser.rl"
+// line 479 "Parser.rl"
-// line 508 "Parser.java"
+// line 477 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -530,13 +499,13 @@ void parseValue(ParserResult res, int p, int pe) {
while ( _nacts-- > 0 ) {
switch ( _JSON_value_actions[_acts++] ) {
case 9:
-// line 488 "Parser.rl"
+// line 457 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 540 "Parser.java"
+// line 509 "Parser.java"
}
}
@@ -599,45 +568,45 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] )
switch ( _JSON_value_actions[_acts++] )
{
case 0:
-// line 405 "Parser.rl"
+// line 374 "Parser.rl"
{
- result = getRuntime().getNil();
+ result = context.nil;
}
break;
case 1:
-// line 408 "Parser.rl"
+// line 377 "Parser.rl"
{
- result = getRuntime().getFalse();
+ result = context.fals;
}
break;
case 2:
-// line 411 "Parser.rl"
+// line 380 "Parser.rl"
{
- result = getRuntime().getTrue();
+ result = context.tru;
}
break;
case 3:
-// line 414 "Parser.rl"
+// line 383 "Parser.rl"
{
if (parser.allowNaN) {
result = getConstant(CONST_NAN);
} else {
- throw unexpectedToken(p - 2, pe);
+ throw unexpectedToken(context, p - 2, pe);
}
}
break;
case 4:
-// line 421 "Parser.rl"
+// line 390 "Parser.rl"
{
if (parser.allowNaN) {
result = getConstant(CONST_INFINITY);
} else {
- throw unexpectedToken(p - 7, pe);
+ throw unexpectedToken(context, p - 7, pe);
}
}
break;
case 5:
-// line 428 "Parser.rl"
+// line 397 "Parser.rl"
{
if (pe > p + 8 &&
absSubSequence(p, p + 9).equals(JSON_MINUS_INFINITY)) {
@@ -648,15 +617,15 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] )
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
} else {
- throw unexpectedToken(p, pe);
+ throw unexpectedToken(context, p, pe);
}
}
- parseFloat(res, p, pe);
+ parseFloat(context, res, p, pe);
if (res.result != null) {
result = res.result;
{p = (( res.p))-1;}
}
- parseInteger(res, p, pe);
+ parseInteger(context, res, p, pe);
if (res.result != null) {
result = res.result;
{p = (( res.p))-1;}
@@ -666,9 +635,9 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] )
}
break;
case 6:
-// line 454 "Parser.rl"
+// line 423 "Parser.rl"
{
- parseString(res, p, pe);
+ parseString(context, res, p, pe);
if (res.result == null) {
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
@@ -679,10 +648,10 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] )
}
break;
case 7:
-// line 464 "Parser.rl"
+// line 433 "Parser.rl"
{
currentNesting++;
- parseArray(res, p, pe);
+ parseArray(context, res, p, pe);
currentNesting--;
if (res.result == null) {
p--;
@@ -694,10 +663,10 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] )
}
break;
case 8:
-// line 476 "Parser.rl"
+// line 445 "Parser.rl"
{
currentNesting++;
- parseObject(res, p, pe);
+ parseObject(context, res, p, pe);
currentNesting--;
if (res.result == null) {
p--;
@@ -708,7 +677,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] )
}
}
break;
-// line 712 "Parser.java"
+// line 681 "Parser.java"
}
}
}
@@ -728,7 +697,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] )
break; }
}
-// line 511 "Parser.rl"
+// line 480 "Parser.rl"
if (cs >= JSON_value_first_final && result != null) {
if (parser.freeze) {
@@ -741,7 +710,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] )
}
-// line 745 "Parser.java"
+// line 714 "Parser.java"
private static byte[] init__JSON_integer_actions_0()
{
return new byte [] {
@@ -840,33 +809,32 @@ private static byte[] init__JSON_integer_trans_actions_0()
static final int JSON_integer_en_main = 1;
-// line 533 "Parser.rl"
+// line 502 "Parser.rl"
- void parseInteger(ParserResult res, int p, int pe) {
+ void parseInteger(ThreadContext context, ParserResult res, int p, int pe) {
int new_p = parseIntegerInternal(p, pe);
if (new_p == -1) {
res.update(null, p);
return;
}
- RubyInteger number = createInteger(p, new_p);
+ RubyInteger number = createInteger(context, p, new_p);
res.update(number, new_p + 1);
- return;
}
int parseIntegerInternal(int p, int pe) {
- int cs = EVIL;
+ int cs;
-// line 862 "Parser.java"
+// line 830 "Parser.java"
{
cs = JSON_integer_start;
}
-// line 550 "Parser.rl"
+// line 518 "Parser.rl"
int memo = p;
-// line 870 "Parser.java"
+// line 838 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -947,13 +915,13 @@ else if ( data[p] > _JSON_integer_trans_keys[_mid+1] )
switch ( _JSON_integer_actions[_acts++] )
{
case 0:
-// line 527 "Parser.rl"
+// line 496 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 957 "Parser.java"
+// line 925 "Parser.java"
}
}
}
@@ -973,7 +941,7 @@ else if ( data[p] > _JSON_integer_trans_keys[_mid+1] )
break; }
}
-// line 552 "Parser.rl"
+// line 520 "Parser.rl"
if (cs < JSON_integer_first_final) {
return -1;
@@ -982,8 +950,8 @@ else if ( data[p] > _JSON_integer_trans_keys[_mid+1] )
return p;
}
- RubyInteger createInteger(int p, int new_p) {
- Ruby runtime = getRuntime();
+ RubyInteger createInteger(ThreadContext context, int p, int new_p) {
+ Ruby runtime = context.runtime;
ByteList num = absSubSequence(p, new_p);
return bytesToInum(runtime, num);
}
@@ -993,7 +961,7 @@ RubyInteger bytesToInum(Ruby runtime, ByteList num) {
}
-// line 997 "Parser.java"
+// line 965 "Parser.java"
private static byte[] init__JSON_float_actions_0()
{
return new byte [] {
@@ -1095,10 +1063,10 @@ private static byte[] init__JSON_float_trans_actions_0()
static final int JSON_float_en_main = 1;
-// line 585 "Parser.rl"
+// line 553 "Parser.rl"
- void parseFloat(ParserResult res, int p, int pe) {
+ void parseFloat(ThreadContext context, ParserResult res, int p, int pe) {
int new_p = parseFloatInternal(p, pe);
if (new_p == -1) {
res.update(null, p);
@@ -1111,18 +1079,18 @@ void parseFloat(ParserResult res, int p, int pe) {
}
int parseFloatInternal(int p, int pe) {
- int cs = EVIL;
+ int cs;
-// line 1118 "Parser.java"
+// line 1086 "Parser.java"
{
cs = JSON_float_start;
}
-// line 603 "Parser.rl"
+// line 571 "Parser.rl"
int memo = p;
-// line 1126 "Parser.java"
+// line 1094 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -1203,13 +1171,13 @@ else if ( data[p] > _JSON_float_trans_keys[_mid+1] )
switch ( _JSON_float_actions[_acts++] )
{
case 0:
-// line 576 "Parser.rl"
+// line 544 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 1213 "Parser.java"
+// line 1181 "Parser.java"
}
}
}
@@ -1229,7 +1197,7 @@ else if ( data[p] > _JSON_float_trans_keys[_mid+1] )
break; }
}
-// line 605 "Parser.rl"
+// line 573 "Parser.rl"
if (cs < JSON_float_first_final) {
return -1;
@@ -1239,7 +1207,7 @@ else if ( data[p] > _JSON_float_trans_keys[_mid+1] )
}
-// line 1243 "Parser.java"
+// line 1211 "Parser.java"
private static byte[] init__JSON_string_actions_0()
{
return new byte [] {
@@ -1341,23 +1309,23 @@ private static byte[] init__JSON_string_trans_actions_0()
static final int JSON_string_en_main = 1;
-// line 644 "Parser.rl"
+// line 612 "Parser.rl"
- void parseString(ParserResult res, int p, int pe) {
- int cs = EVIL;
+ void parseString(ThreadContext context, ParserResult res, int p, int pe) {
+ int cs;
IRubyObject result = null;
-// line 1353 "Parser.java"
+// line 1321 "Parser.java"
{
cs = JSON_string_start;
}
-// line 651 "Parser.rl"
+// line 619 "Parser.rl"
int memo = p;
-// line 1361 "Parser.java"
+// line 1329 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -1438,12 +1406,12 @@ else if ( data[p] > _JSON_string_trans_keys[_mid+1] )
switch ( _JSON_string_actions[_acts++] )
{
case 0:
-// line 619 "Parser.rl"
+// line 587 "Parser.rl"
{
int offset = byteList.begin();
- ByteList decoded = decoder.decode(byteList, memo + 1 - offset,
+ ByteList decoded = decoder.decode(context, byteList, memo + 1 - offset,
p - offset);
- result = getRuntime().newString(decoded);
+ result = context.runtime.newString(decoded);
if (result == null) {
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
@@ -1453,13 +1421,13 @@ else if ( data[p] > _JSON_string_trans_keys[_mid+1] )
}
break;
case 1:
-// line 632 "Parser.rl"
+// line 600 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 1463 "Parser.java"
+// line 1431 "Parser.java"
}
}
}
@@ -1479,29 +1447,21 @@ else if ( data[p] > _JSON_string_trans_keys[_mid+1] )
break; }
}
-// line 653 "Parser.rl"
+// line 621 "Parser.rl"
if (parser.createAdditions) {
RubyHash matchString = parser.match_string;
if (matchString != null) {
final IRubyObject[] memoArray = { result, null };
try {
- matchString.visitAll(new RubyHash.Visitor() {
- @Override
- public void visit(IRubyObject pattern, IRubyObject klass) {
- if (pattern.callMethod(context, "===", memoArray[0]).isTrue()) {
- memoArray[1] = klass;
- throw JumpException.SPECIAL_JUMP;
- }
- }
- });
+ matchString.visitAll(context, MATCH_VISITOR, memoArray);
} catch (JumpException e) { }
if (memoArray[1] != null) {
RubyClass klass = (RubyClass) memoArray[1];
if (klass.respondsTo("json_creatable?") &&
klass.callMethod(context, "json_creatable?").isTrue()) {
if (parser.deprecatedCreateAdditions) {
- klass.getRuntime().getWarnings().warn("JSON.load implicit support for `create_additions: true` is deprecated and will be removed in 3.0, use JSON.unsafe_load or explicitly pass `create_additions: true`");
+ context.runtime.getWarnings().warn("JSON.load implicit support for `create_additions: true` is deprecated and will be removed in 3.0, use JSON.unsafe_load or explicitly pass `create_additions: true`");
}
result = klass.callMethod(context, "json_create", result);
}
@@ -1512,10 +1472,11 @@ public void visit(IRubyObject pattern, IRubyObject klass) {
if (cs >= JSON_string_first_final && result != null) {
if (result instanceof RubyString) {
RubyString string = (RubyString)result;
- string.force_encoding(context, info.utf8.get());
+ string.setEncoding(UTF8Encoding.INSTANCE);
+ string.clearCodeRange();
if (parser.freeze) {
string.setFrozen(true);
- string = getRuntime().freezeAndDedupString(string);
+ string = context.runtime.freezeAndDedupString(string);
}
res.update(string, p + 1);
} else {
@@ -1527,7 +1488,7 @@ public void visit(IRubyObject pattern, IRubyObject klass) {
}
-// line 1531 "Parser.java"
+// line 1492 "Parser.java"
private static byte[] init__JSON_array_actions_0()
{
return new byte [] {
@@ -1694,34 +1655,34 @@ private static byte[] init__JSON_array_trans_actions_0()
static final int JSON_array_en_main = 1;
-// line 738 "Parser.rl"
+// line 699 "Parser.rl"
- void parseArray(ParserResult res, int p, int pe) {
- int cs = EVIL;
+ void parseArray(ThreadContext context, ParserResult res, int p, int pe) {
+ int cs;
if (parser.maxNesting > 0 && currentNesting > parser.maxNesting) {
- throw newException(Utils.M_NESTING_ERROR,
+ throw newException(context, Utils.M_NESTING_ERROR,
"nesting of " + currentNesting + " is too deep");
}
IRubyObject result;
- if (parser.arrayClass == getRuntime().getArray()) {
- result = RubyArray.newArray(getRuntime());
+ if (parser.arrayClass == context.runtime.getArray()) {
+ result = RubyArray.newArray(context.runtime);
} else {
result = parser.arrayClass.newInstance(context,
IRubyObject.NULL_ARRAY, Block.NULL_BLOCK);
}
-// line 1718 "Parser.java"
+// line 1679 "Parser.java"
{
cs = JSON_array_start;
}
-// line 757 "Parser.rl"
+// line 718 "Parser.rl"
-// line 1725 "Parser.java"
+// line 1686 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -1764,7 +1725,7 @@ else if ( _widec > _JSON_array_cond_keys[_mid+1] )
case 0: {
_widec = 65536 + (data[p] - 0);
if (
-// line 705 "Parser.rl"
+// line 666 "Parser.rl"
parser.allowTrailingComma ) _widec += 65536;
break;
}
@@ -1834,14 +1795,14 @@ else if ( _widec > _JSON_array_trans_keys[_mid+1] )
switch ( _JSON_array_actions[_acts++] )
{
case 0:
-// line 707 "Parser.rl"
+// line 668 "Parser.rl"
{
- parseValue(res, p, pe);
+ parseValue(context, res, p, pe);
if (res.result == null) {
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
} else {
- if (parser.arrayClass == getRuntime().getArray()) {
+ if (parser.arrayClass == context.runtime.getArray()) {
((RubyArray)result).append(res.result);
} else {
result.callMethod(context, "<<", res.result);
@@ -1851,13 +1812,13 @@ else if ( _widec > _JSON_array_trans_keys[_mid+1] )
}
break;
case 1:
-// line 722 "Parser.rl"
+// line 683 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 1861 "Parser.java"
+// line 1822 "Parser.java"
}
}
}
@@ -1877,17 +1838,17 @@ else if ( _widec > _JSON_array_trans_keys[_mid+1] )
break; }
}
-// line 758 "Parser.rl"
+// line 719 "Parser.rl"
if (cs >= JSON_array_first_final) {
res.update(result, p + 1);
} else {
- throw unexpectedToken(p, pe);
+ throw unexpectedToken(context, p, pe);
}
}
-// line 1891 "Parser.java"
+// line 1852 "Parser.java"
private static byte[] init__JSON_object_actions_0()
{
return new byte [] {
@@ -2064,24 +2025,24 @@ private static byte[] init__JSON_object_trans_actions_0()
static final int JSON_object_en_main = 1;
-// line 819 "Parser.rl"
+// line 780 "Parser.rl"
- void parseObject(ParserResult res, int p, int pe) {
- int cs = EVIL;
+ void parseObject(ThreadContext context, ParserResult res, int p, int pe) {
+ int cs;
IRubyObject lastName = null;
boolean objectDefault = true;
if (parser.maxNesting > 0 && currentNesting > parser.maxNesting) {
- throw newException(Utils.M_NESTING_ERROR,
+ throw newException(context, Utils.M_NESTING_ERROR,
"nesting of " + currentNesting + " is too deep");
}
// this is guaranteed to be a RubyHash due to the earlier
// allocator test at OptionsReader#getClass
IRubyObject result;
- if (parser.objectClass == getRuntime().getHash()) {
- result = RubyHash.newHash(getRuntime());
+ if (parser.objectClass == context.runtime.getHash()) {
+ result = RubyHash.newHash(context.runtime);
} else {
objectDefault = false;
result = parser.objectClass.newInstance(context,
@@ -2089,14 +2050,14 @@ void parseObject(ParserResult res, int p, int pe) {
}
-// line 2093 "Parser.java"
+// line 2054 "Parser.java"
{
cs = JSON_object_start;
}
-// line 843 "Parser.rl"
+// line 804 "Parser.rl"
-// line 2100 "Parser.java"
+// line 2061 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -2139,7 +2100,7 @@ else if ( _widec > _JSON_object_cond_keys[_mid+1] )
case 0: {
_widec = 65536 + (data[p] - 0);
if (
-// line 772 "Parser.rl"
+// line 733 "Parser.rl"
parser.allowTrailingComma ) _widec += 65536;
break;
}
@@ -2209,26 +2170,26 @@ else if ( _widec > _JSON_object_trans_keys[_mid+1] )
switch ( _JSON_object_actions[_acts++] )
{
case 0:
-// line 774 "Parser.rl"
+// line 735 "Parser.rl"
{
- parseValue(res, p, pe);
+ parseValue(context, res, p, pe);
if (res.result == null) {
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
} else {
- if (parser.objectClass == getRuntime().getHash()) {
+ if (parser.objectClass == context.runtime.getHash()) {
((RubyHash)result).op_aset(context, lastName, res.result);
} else {
- result.callMethod(context, "[]=", new IRubyObject[] { lastName, res.result });
+ Helpers.invoke(context, result, "[]=", lastName, res.result);
}
{p = (( res.p))-1;}
}
}
break;
case 1:
-// line 789 "Parser.rl"
+// line 750 "Parser.rl"
{
- parseString(res, p, pe);
+ parseString(context, res, p, pe);
if (res.result == null) {
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
@@ -2244,13 +2205,13 @@ else if ( _widec > _JSON_object_trans_keys[_mid+1] )
}
break;
case 2:
-// line 805 "Parser.rl"
+// line 766 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 2254 "Parser.java"
+// line 2215 "Parser.java"
}
}
}
@@ -2270,7 +2231,7 @@ else if ( _widec > _JSON_object_trans_keys[_mid+1] )
break; }
}
-// line 844 "Parser.rl"
+// line 805 "Parser.rl"
if (cs < JSON_object_first_final) {
res.update(null, p + 1);
@@ -2295,7 +2256,7 @@ else if ( _widec > _JSON_object_trans_keys[_mid+1] )
if (klass.respondsTo("json_creatable?") &&
klass.callMethod(context, "json_creatable?").isTrue()) {
if (parser.deprecatedCreateAdditions) {
- klass.getRuntime().getWarnings().warn("JSON.load implicit support for `create_additions: true` is deprecated and will be removed in 3.0, use JSON.unsafe_load or explicitly pass `create_additions: true`");
+ context.runtime.getWarnings().warn("JSON.load implicit support for `create_additions: true` is deprecated and will be removed in 3.0, use JSON.unsafe_load or explicitly pass `create_additions: true`");
}
returnedResult = klass.callMethod(context, "json_create", result);
@@ -2306,7 +2267,7 @@ else if ( _widec > _JSON_object_trans_keys[_mid+1] )
}
-// line 2310 "Parser.java"
+// line 2271 "Parser.java"
private static byte[] init__JSON_actions_0()
{
return new byte [] {
@@ -2409,26 +2370,26 @@ private static byte[] init__JSON_trans_actions_0()
static final int JSON_en_main = 1;
-// line 898 "Parser.rl"
+// line 859 "Parser.rl"
- public IRubyObject parseImplemetation() {
- int cs = EVIL;
+ public IRubyObject parseImplementation(ThreadContext context) {
+ int cs;
int p, pe;
IRubyObject result = null;
ParserResult res = new ParserResult();
-// line 2423 "Parser.java"
+// line 2384 "Parser.java"
{
cs = JSON_start;
}
-// line 907 "Parser.rl"
+// line 868 "Parser.rl"
p = byteList.begin();
pe = p + byteList.length();
-// line 2432 "Parser.java"
+// line 2393 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -2509,9 +2470,9 @@ else if ( data[p] > _JSON_trans_keys[_mid+1] )
switch ( _JSON_actions[_acts++] )
{
case 0:
-// line 884 "Parser.rl"
+// line 845 "Parser.rl"
{
- parseValue(res, p, pe);
+ parseValue(context, res, p, pe);
if (res.result == null) {
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
@@ -2521,7 +2482,7 @@ else if ( data[p] > _JSON_trans_keys[_mid+1] )
}
}
break;
-// line 2525 "Parser.java"
+// line 2486 "Parser.java"
}
}
}
@@ -2541,23 +2502,23 @@ else if ( data[p] > _JSON_trans_keys[_mid+1] )
break; }
}
-// line 910 "Parser.rl"
+// line 871 "Parser.rl"
if (cs >= JSON_first_final && p == pe) {
return result;
} else {
- throw unexpectedToken(p, pe);
+ throw unexpectedToken(context, p, pe);
}
}
- public IRubyObject parse() {
- return parseImplemetation();
+ public IRubyObject parse(ThreadContext context) {
+ return parseImplementation(context);
}
/**
* Updates the "view" bytelist with the new offsets and returns it.
- * @param start
- * @param end
+ * @param absStart
+ * @param absEnd
*/
private ByteList absSubSequence(int absStart, int absEnd) {
view.setBegin(absStart);
@@ -2573,18 +2534,22 @@ private IRubyObject getConstant(String name) {
return parser.info.jsonModule.get().getConstant(name);
}
- private RaiseException newException(String className, String message) {
+ private RaiseException newException(ThreadContext context, String className, String message) {
return Utils.newException(context, className, message);
}
- private RaiseException newException(String className, RubyString message) {
+ private RaiseException newException(ThreadContext context, String className, RubyString message) {
return Utils.newException(context, className, message);
}
- private RaiseException newException(String className,
- String messageBegin, ByteList messageEnd) {
- return newException(className,
- getRuntime().newString(messageBegin).cat(messageEnd));
- }
+ RubyHash.VisitorWithStateinclude "json/ext"
.
*
* source
.
* It will be configured by the opts
Hash.
* opts
can have the following keys:
- *
+ *
*
*/
- @JRubyMethod(name = "new", required = 1, optional = 1, meta = true)
- public static IRubyObject newInstance(IRubyObject clazz, IRubyObject[] args, Block block) {
+ @JRubyMethod(name = "new", meta = true)
+ public static IRubyObject newInstance(IRubyObject clazz, IRubyObject arg0, Block block) {
Parser parser = (Parser)((RubyClass)clazz).allocate();
- parser.callInit(args, block);
+ parser.callInit(arg0, block);
+
+ return parser;
+ }
+
+ @JRubyMethod(name = "new", meta = true)
+ public static IRubyObject newInstance(IRubyObject clazz, IRubyObject arg0, IRubyObject arg1, Block block) {
+ Parser parser = (Parser)((RubyClass)clazz).allocate();
+
+ parser.callInit(arg0, arg1, block);
return parser;
}
@JRubyMethod(meta=true)
public static IRubyObject parse(ThreadContext context, IRubyObject clazz, IRubyObject source, IRubyObject opts) {
- IRubyObject[] args = new IRubyObject[] {source, opts};
Parser parser = (Parser)((RubyClass)clazz).allocate();
- parser.callInit(args, null);
+ parser.callInit(source, opts, null);
return parser.parse(context);
}
- @JRubyMethod(required = 1, optional = 1, visibility = Visibility.PRIVATE)
- public IRubyObject initialize(ThreadContext context, IRubyObject[] args) {
- Ruby runtime = context.getRuntime();
+ @JRubyMethod(visibility = Visibility.PRIVATE)
+ public IRubyObject initialize(ThreadContext context, IRubyObject arg0) {
+ return initialize(context, arg0, null);
+ }
+
+ @JRubyMethod(visibility = Visibility.PRIVATE)
+ public IRubyObject initialize(ThreadContext context, IRubyObject arg0, IRubyObject arg1) {
+ Ruby runtime = context.runtime;
if (this.vSource != null) {
throw runtime.newTypeError("already initialized instance");
- }
+ }
- OptionsReader opts = new OptionsReader(context, args.length > 1 ? args[1] : null);
+ OptionsReader opts = new OptionsReader(context, arg1);
this.maxNesting = opts.getInt("max_nesting", DEFAULT_MAX_NESTING);
this.allowNaN = opts.getBool("allow_nan", false);
this.allowTrailingComma = opts.getBool("allow_trailing_comma", false);
@@ -213,12 +224,9 @@ public class Parser extends RubyObject {
}
if(symbolizeNames && createAdditions) {
- throw runtime.newArgumentError(
- "options :symbolize_names and :create_additions cannot be " +
- " used in conjunction"
- );
+ throw runtime.newArgumentError("options :symbolize_names and :create_additions cannot be used in conjunction");
}
- this.vSource = args[0].convertToString();
+ this.vSource = arg0.convertToString();
this.vSource = convertEncoding(context, vSource);
return this;
@@ -230,44 +238,17 @@ public class Parser extends RubyObject {
* Returns the source string if no conversion is needed.
*/
private RubyString convertEncoding(ThreadContext context, RubyString source) {
- RubyEncoding encoding = (RubyEncoding)source.encoding(context);
- if (encoding == info.ascii8bit.get()) {
+ Encoding encoding = source.getEncoding();
+ if (encoding == ASCIIEncoding.INSTANCE) {
source = (RubyString) source.dup();
- source.force_encoding(context, info.utf8.get());
- } else {
- source = (RubyString) source.encode(context, info.utf8.get());
+ source.setEncoding(UTF8Encoding.INSTANCE);
+ source.clearCodeRange();
+ } else if (encoding != UTF8Encoding.INSTANCE) {
+ source = (RubyString) source.encode(context, context.runtime.getEncodingService().convertEncodingToRubyEncoding(UTF8Encoding.INSTANCE));
}
return source;
}
- /**
- * Checks the first four bytes of the given ByteList to infer its encoding,
- * using the principle demonstrated on section 3 of RFC 4627 (JSON).
- */
- private static String sniffByteList(ByteList bl) {
- if (bl.length() < 4) return null;
- if (bl.get(0) == 0 && bl.get(2) == 0) {
- return bl.get(1) == 0 ? "utf-32be" : "utf-16be";
- }
- if (bl.get(1) == 0 && bl.get(3) == 0) {
- return bl.get(2) == 0 ? "utf-32le" : "utf-16le";
- }
- return null;
- }
-
- /**
- * Assumes the given (binary) RubyString to be in the given encoding, then
- * converts it to UTF-8.
- */
- private RubyString reinterpretEncoding(ThreadContext context,
- RubyString str, String sniffedEncoding) {
- RubyEncoding actualEncoding = info.getEncoding(context, sniffedEncoding);
- RubyEncoding targetEncoding = info.utf8.get();
- RubyString dup = (RubyString)str.dup();
- dup.force_encoding(context, actualEncoding);
- return (RubyString)dup.encode_bang(context, targetEncoding);
- }
-
/**
* :max_nesting
* :max_nesting => false|nil|0
,
* it defaults to 100.
- *
+ * :allow_nan
* true
, allow NaN
,
* Infinity
and -Infinity
in defiance of RFC 4627
* to be parsed by the Parser. This option defaults to false
.
- *
+ * :allow_trailing_comma
* true
, allow arrays and objects with a trailing
* comma in defiance of RFC 4627 to be parsed by the Parser.
* This option defaults to false
.
- *
+ * :symbolize_names
* true
, returns symbols for the names (keys) in
* a JSON object. Otherwise strings are returned, which is also the default.
- *
+ * :create_additions
* false
, the Parser doesn't create additions
* even if a matching class and create_id
was found. This option
* defaults to true
.
- *
+ * :object_class
* new
without arguments, and return an object that respond to []=
.
- *
+ * :array_class
* new
without arguments, and return an object that respond to <<
.
- *
+ * :decimal_class
* Parser#parse()
*
@@ -276,7 +257,7 @@ public class Parser extends RubyObject {
*/
@JRubyMethod
public IRubyObject parse(ThreadContext context) {
- return new ParserSession(this, context, info).parse();
+ return new ParserSession(this, context, info).parse(context);
}
/**
@@ -286,15 +267,15 @@ public class Parser extends RubyObject {
* used to construct this Parser.
*/
@JRubyMethod(name = "source")
- public IRubyObject source_get() {
- return checkAndGetSource().dup();
+ public IRubyObject source_get(ThreadContext context) {
+ return checkAndGetSource(context).dup();
}
- public RubyString checkAndGetSource() {
+ public RubyString checkAndGetSource(ThreadContext context) {
if (vSource != null) {
return vSource;
} else {
- throw getRuntime().newTypeError("uninitialized instance");
+ throw context.runtime.newTypeError("uninitialized instance");
}
}
@@ -333,39 +314,27 @@ public class Parser extends RubyObject {
@SuppressWarnings("fallthrough")
private static class ParserSession {
private final Parser parser;
- private final ThreadContext context;
private final RuntimeInfo info;
private final ByteList byteList;
private final ByteList view;
private final byte[] data;
private final StringDecoder decoder;
private int currentNesting = 0;
- private final DoubleConverter dc;
-
- // initialization value for all state variables.
- // no idea about the origins of this value, ask Flori ;)
- private static final int EVIL = 0x666;
private ParserSession(Parser parser, ThreadContext context, RuntimeInfo info) {
this.parser = parser;
- this.context = context;
this.info = info;
- this.byteList = parser.checkAndGetSource().getByteList();
+ this.byteList = parser.checkAndGetSource(context).getByteList();
this.data = byteList.unsafeBytes();
this.view = new ByteList(data, false);
- this.decoder = new StringDecoder(context);
- this.dc = new DoubleConverter();
+ this.decoder = new StringDecoder();
}
- private RaiseException unexpectedToken(int absStart, int absEnd) {
- RubyString msg = getRuntime().newString("unexpected token at '")
+ private RaiseException unexpectedToken(ThreadContext context, int absStart, int absEnd) {
+ RubyString msg = context.runtime.newString("unexpected token at '")
.cat(data, absStart, Math.min(absEnd - absStart, 32))
.cat((byte)'\'');
- return newException(Utils.M_PARSER_ERROR, msg);
- }
-
- private Ruby getRuntime() {
- return context.getRuntime();
+ return newException(context, Utils.M_PARSER_ERROR, msg);
}
%%{
@@ -403,26 +372,26 @@ public class Parser extends RubyObject {
write data;
action parse_null {
- result = getRuntime().getNil();
+ result = context.nil;
}
action parse_false {
- result = getRuntime().getFalse();
+ result = context.fals;
}
action parse_true {
- result = getRuntime().getTrue();
+ result = context.tru;
}
action parse_nan {
if (parser.allowNaN) {
result = getConstant(CONST_NAN);
} else {
- throw unexpectedToken(p - 2, pe);
+ throw unexpectedToken(context, p - 2, pe);
}
}
action parse_infinity {
if (parser.allowNaN) {
result = getConstant(CONST_INFINITY);
} else {
- throw unexpectedToken(p - 7, pe);
+ throw unexpectedToken(context, p - 7, pe);
}
}
action parse_number {
@@ -435,15 +404,15 @@ public class Parser extends RubyObject {
fhold;
fbreak;
} else {
- throw unexpectedToken(p, pe);
+ throw unexpectedToken(context, p, pe);
}
}
- parseFloat(res, fpc, pe);
+ parseFloat(context, res, fpc, pe);
if (res.result != null) {
result = res.result;
fexec res.p;
}
- parseInteger(res, fpc, pe);
+ parseInteger(context, res, fpc, pe);
if (res.result != null) {
result = res.result;
fexec res.p;
@@ -452,7 +421,7 @@ public class Parser extends RubyObject {
fbreak;
}
action parse_string {
- parseString(res, fpc, pe);
+ parseString(context, res, fpc, pe);
if (res.result == null) {
fhold;
fbreak;
@@ -463,7 +432,7 @@ public class Parser extends RubyObject {
}
action parse_array {
currentNesting++;
- parseArray(res, fpc, pe);
+ parseArray(context, res, fpc, pe);
currentNesting--;
if (res.result == null) {
fhold;
@@ -475,7 +444,7 @@ public class Parser extends RubyObject {
}
action parse_object {
currentNesting++;
- parseObject(res, fpc, pe);
+ parseObject(context, res, fpc, pe);
currentNesting--;
if (res.result == null) {
fhold;
@@ -502,8 +471,8 @@ public class Parser extends RubyObject {
) %*exit;
}%%
- void parseValue(ParserResult res, int p, int pe) {
- int cs = EVIL;
+ void parseValue(ThreadContext context, ParserResult res, int p, int pe) {
+ int cs;
IRubyObject result = null;
%% write init;
@@ -532,19 +501,18 @@ public class Parser extends RubyObject {
main := '-'? ( '0' | [1-9][0-9]* ) ( ^[0-9]? @exit );
}%%
- void parseInteger(ParserResult res, int p, int pe) {
+ void parseInteger(ThreadContext context, ParserResult res, int p, int pe) {
int new_p = parseIntegerInternal(p, pe);
if (new_p == -1) {
res.update(null, p);
return;
}
- RubyInteger number = createInteger(p, new_p);
+ RubyInteger number = createInteger(context, p, new_p);
res.update(number, new_p + 1);
- return;
}
int parseIntegerInternal(int p, int pe) {
- int cs = EVIL;
+ int cs;
%% write init;
int memo = p;
@@ -557,8 +525,8 @@ public class Parser extends RubyObject {
return p;
}
- RubyInteger createInteger(int p, int new_p) {
- Ruby runtime = getRuntime();
+ RubyInteger createInteger(ThreadContext context, int p, int new_p) {
+ Ruby runtime = context.runtime;
ByteList num = absSubSequence(p, new_p);
return bytesToInum(runtime, num);
}
@@ -584,7 +552,7 @@ public class Parser extends RubyObject {
( ^[0-9Ee.\-]? @exit );
}%%
- void parseFloat(ParserResult res, int p, int pe) {
+ void parseFloat(ThreadContext context, ParserResult res, int p, int pe) {
int new_p = parseFloatInternal(p, pe);
if (new_p == -1) {
res.update(null, p);
@@ -597,7 +565,7 @@ public class Parser extends RubyObject {
}
int parseFloatInternal(int p, int pe) {
- int cs = EVIL;
+ int cs;
%% write init;
int memo = p;
@@ -618,9 +586,9 @@ public class Parser extends RubyObject {
action parse_string {
int offset = byteList.begin();
- ByteList decoded = decoder.decode(byteList, memo + 1 - offset,
+ ByteList decoded = decoder.decode(context, byteList, memo + 1 - offset,
p - offset);
- result = getRuntime().newString(decoded);
+ result = context.runtime.newString(decoded);
if (result == null) {
fhold;
fbreak;
@@ -643,8 +611,8 @@ public class Parser extends RubyObject {
) '"' @exit;
}%%
- void parseString(ParserResult res, int p, int pe) {
- int cs = EVIL;
+ void parseString(ThreadContext context, ParserResult res, int p, int pe) {
+ int cs;
IRubyObject result = null;
%% write init;
@@ -656,22 +624,14 @@ public class Parser extends RubyObject {
if (matchString != null) {
final IRubyObject[] memoArray = { result, null };
try {
- matchString.visitAll(new RubyHash.Visitor() {
- @Override
- public void visit(IRubyObject pattern, IRubyObject klass) {
- if (pattern.callMethod(context, "===", memoArray[0]).isTrue()) {
- memoArray[1] = klass;
- throw JumpException.SPECIAL_JUMP;
- }
- }
- });
+ matchString.visitAll(context, MATCH_VISITOR, memoArray);
} catch (JumpException e) { }
if (memoArray[1] != null) {
RubyClass klass = (RubyClass) memoArray[1];
if (klass.respondsTo("json_creatable?") &&
klass.callMethod(context, "json_creatable?").isTrue()) {
if (parser.deprecatedCreateAdditions) {
- klass.getRuntime().getWarnings().warn("JSON.load implicit support for `create_additions: true` is deprecated and will be removed in 3.0, use JSON.unsafe_load or explicitly pass `create_additions: true`");
+ context.runtime.getWarnings().warn("JSON.load implicit support for `create_additions: true` is deprecated and will be removed in 3.0, use JSON.unsafe_load or explicitly pass `create_additions: true`");
}
result = klass.callMethod(context, "json_create", result);
}
@@ -682,10 +642,11 @@ public class Parser extends RubyObject {
if (cs >= JSON_string_first_final && result != null) {
if (result instanceof RubyString) {
RubyString string = (RubyString)result;
- string.force_encoding(context, info.utf8.get());
+ string.setEncoding(UTF8Encoding.INSTANCE);
+ string.clearCodeRange();
if (parser.freeze) {
string.setFrozen(true);
- string = getRuntime().freezeAndDedupString(string);
+ string = context.runtime.freezeAndDedupString(string);
}
res.update(string, p + 1);
} else {
@@ -705,12 +666,12 @@ public class Parser extends RubyObject {
action allow_trailing_comma { parser.allowTrailingComma }
action parse_value {
- parseValue(res, fpc, pe);
+ parseValue(context, res, fpc, pe);
if (res.result == null) {
fhold;
fbreak;
} else {
- if (parser.arrayClass == getRuntime().getArray()) {
+ if (parser.arrayClass == context.runtime.getArray()) {
((RubyArray)result).append(res.result);
} else {
result.callMethod(context, "<<", res.result);
@@ -737,17 +698,17 @@ public class Parser extends RubyObject {
end_array @exit;
}%%
- void parseArray(ParserResult res, int p, int pe) {
- int cs = EVIL;
+ void parseArray(ThreadContext context, ParserResult res, int p, int pe) {
+ int cs;
if (parser.maxNesting > 0 && currentNesting > parser.maxNesting) {
- throw newException(Utils.M_NESTING_ERROR,
+ throw newException(context, Utils.M_NESTING_ERROR,
"nesting of " + currentNesting + " is too deep");
}
IRubyObject result;
- if (parser.arrayClass == getRuntime().getArray()) {
- result = RubyArray.newArray(getRuntime());
+ if (parser.arrayClass == context.runtime.getArray()) {
+ result = RubyArray.newArray(context.runtime);
} else {
result = parser.arrayClass.newInstance(context,
IRubyObject.NULL_ARRAY, Block.NULL_BLOCK);
@@ -759,7 +720,7 @@ public class Parser extends RubyObject {
if (cs >= JSON_array_first_final) {
res.update(result, p + 1);
} else {
- throw unexpectedToken(p, pe);
+ throw unexpectedToken(context, p, pe);
}
}
@@ -772,22 +733,22 @@ public class Parser extends RubyObject {
action allow_trailing_comma { parser.allowTrailingComma }
action parse_value {
- parseValue(res, fpc, pe);
+ parseValue(context, res, fpc, pe);
if (res.result == null) {
fhold;
fbreak;
} else {
- if (parser.objectClass == getRuntime().getHash()) {
+ if (parser.objectClass == context.runtime.getHash()) {
((RubyHash)result).op_aset(context, lastName, res.result);
} else {
- result.callMethod(context, "[]=", new IRubyObject[] { lastName, res.result });
+ Helpers.invoke(context, result, "[]=", lastName, res.result);
}
fexec res.p;
}
}
action parse_name {
- parseString(res, fpc, pe);
+ parseString(context, res, fpc, pe);
if (res.result == null) {
fhold;
fbreak;
@@ -818,21 +779,21 @@ public class Parser extends RubyObject {
) @exit;
}%%
- void parseObject(ParserResult res, int p, int pe) {
- int cs = EVIL;
+ void parseObject(ThreadContext context, ParserResult res, int p, int pe) {
+ int cs;
IRubyObject lastName = null;
boolean objectDefault = true;
if (parser.maxNesting > 0 && currentNesting > parser.maxNesting) {
- throw newException(Utils.M_NESTING_ERROR,
+ throw newException(context, Utils.M_NESTING_ERROR,
"nesting of " + currentNesting + " is too deep");
}
// this is guaranteed to be a RubyHash due to the earlier
// allocator test at OptionsReader#getClass
IRubyObject result;
- if (parser.objectClass == getRuntime().getHash()) {
- result = RubyHash.newHash(getRuntime());
+ if (parser.objectClass == context.runtime.getHash()) {
+ result = RubyHash.newHash(context.runtime);
} else {
objectDefault = false;
result = parser.objectClass.newInstance(context,
@@ -865,7 +826,7 @@ public class Parser extends RubyObject {
if (klass.respondsTo("json_creatable?") &&
klass.callMethod(context, "json_creatable?").isTrue()) {
if (parser.deprecatedCreateAdditions) {
- klass.getRuntime().getWarnings().warn("JSON.load implicit support for `create_additions: true` is deprecated and will be removed in 3.0, use JSON.unsafe_load or explicitly pass `create_additions: true`");
+ context.runtime.getWarnings().warn("JSON.load implicit support for `create_additions: true` is deprecated and will be removed in 3.0, use JSON.unsafe_load or explicitly pass `create_additions: true`");
}
returnedResult = klass.callMethod(context, "json_create", result);
@@ -882,7 +843,7 @@ public class Parser extends RubyObject {
write data;
action parse_value {
- parseValue(res, fpc, pe);
+ parseValue(context, res, fpc, pe);
if (res.result == null) {
fhold;
fbreak;
@@ -897,8 +858,8 @@ public class Parser extends RubyObject {
ignore*;
}%%
- public IRubyObject parseImplemetation() {
- int cs = EVIL;
+ public IRubyObject parseImplementation(ThreadContext context) {
+ int cs;
int p, pe;
IRubyObject result = null;
ParserResult res = new ParserResult();
@@ -911,18 +872,18 @@ public class Parser extends RubyObject {
if (cs >= JSON_first_final && p == pe) {
return result;
} else {
- throw unexpectedToken(p, pe);
+ throw unexpectedToken(context, p, pe);
}
}
- public IRubyObject parse() {
- return parseImplemetation();
+ public IRubyObject parse(ThreadContext context) {
+ return parseImplementation(context);
}
/**
* Updates the "view" bytelist with the new offsets and returns it.
- * @param start
- * @param end
+ * @param absStart
+ * @param absEnd
*/
private ByteList absSubSequence(int absStart, int absEnd) {
view.setBegin(absStart);
@@ -938,18 +899,22 @@ public class Parser extends RubyObject {
return parser.info.jsonModule.get().getConstant(name);
}
- private RaiseException newException(String className, String message) {
+ private RaiseException newException(ThreadContext context, String className, String message) {
return Utils.newException(context, className, message);
}
- private RaiseException newException(String className, RubyString message) {
+ private RaiseException newException(ThreadContext context, String className, RubyString message) {
return Utils.newException(context, className, message);
}
- private RaiseException newException(String className,
- String messageBegin, ByteList messageEnd) {
- return newException(className,
- getRuntime().newString(messageBegin).cat(messageEnd));
- }
+ RubyHash.VisitorWithState