summaryrefslogtreecommitdiff
path: root/src/json/ext/OptionsReader.java
diff options
context:
space:
mode:
authorCharles Oliver Nutter <headius@headius.com>2010-08-03 12:21:11 -0500
committerCharles Oliver Nutter <headius@headius.com>2010-08-03 12:21:11 -0500
commit2288d74466463d34a5054ef413e099c850cd832b (patch)
tree76db71c439f26b5c3b7e60fb15178a2bce92c2fb /src/json/ext/OptionsReader.java
parent6ebee56297dfd9c380f8f8fb6c0b8bb5254901b7 (diff)
downloadjson-2288d74466463d34a5054ef413e099c850cd832b.tar.gz
Merge JRuby-compatible extension into json proper.
Diffstat (limited to 'src/json/ext/OptionsReader.java')
-rw-r--r--src/json/ext/OptionsReader.java113
1 files changed, 113 insertions, 0 deletions
diff --git a/src/json/ext/OptionsReader.java b/src/json/ext/OptionsReader.java
new file mode 100644
index 0000000..29de188
--- /dev/null
+++ b/src/json/ext/OptionsReader.java
@@ -0,0 +1,113 @@
+/*
+ * This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
+ *
+ * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
+ * for details.
+ */
+package json.ext;
+
+import org.jruby.Ruby;
+import org.jruby.RubyClass;
+import org.jruby.RubyHash;
+import org.jruby.RubyNumeric;
+import org.jruby.RubyString;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+import org.jruby.util.ByteList;
+
+final class OptionsReader {
+ private final ThreadContext context;
+ private final Ruby runtime;
+ private final RuntimeInfo info;
+ private final RubyHash opts;
+
+ private OptionsReader(ThreadContext context, Ruby runtime,
+ RuntimeInfo info, IRubyObject vOpts) {
+ this.context = context;
+ this.runtime = runtime;
+ this.info = info;
+
+ if (vOpts == null || vOpts.isNil()) {
+ opts = null;
+ } else if (vOpts.respondsTo("to_hash")) {
+ opts = vOpts.convertToHash();
+ } else {
+ opts = vOpts.callMethod(context, "to_h").convertToHash();
+ }
+ }
+
+ OptionsReader(ThreadContext context, IRubyObject vOpts) {
+ this(context, context.getRuntime(), null, vOpts);
+ }
+
+ static OptionsReader withStrings(ThreadContext context, IRubyObject vOpts) {
+ Ruby runtime = context.getRuntime();
+ return new OptionsReader(context, runtime,
+ RuntimeInfo.forRuntime(runtime), vOpts);
+ }
+
+ /**
+ * Efficiently looks up items with a {@link RubySymbol Symbol} key
+ * @param key The Symbol name to look up for
+ * @return The item in the {@link RubyHash Hash}, or <code>null</code>
+ * if not found
+ */
+ IRubyObject get(String key) {
+ return opts == null ? null : opts.fastARef(runtime.newSymbol(key));
+ }
+
+ boolean getBool(String key, boolean defaultValue) {
+ IRubyObject value = get(key);
+ return value == null ? defaultValue : value.isTrue();
+ }
+
+ int getInt(String key, int defaultValue) {
+ IRubyObject value = get(key);
+ if (value == null) return defaultValue;
+ if (!value.isTrue()) return 0;
+ return RubyNumeric.fix2int(value);
+ }
+
+ /**
+ * Reads the setting from the options hash. If no entry is set for this
+ * key or if it evaluates to <code>false</code>, returns null; attempts to
+ * coerce the value to {@link RubyString String} otherwise.
+ * @param key The Symbol name to look up for
+ * @return <code>null</code> if the key is not in the Hash or if
+ * its value evaluates to <code>false</code>
+ * @throws RaiseException <code>TypeError</code> if the value does not
+ * evaluate to <code>false</code> and can't be
+ * converted to string
+ */
+ ByteList getString(String key) {
+ IRubyObject value = get(key);
+ if (value == null || !value.isTrue()) return null;
+
+ RubyString str = value.convertToString();
+ if (info.encodingsSupported() && str.encoding(context) != info.utf8) {
+ str = (RubyString)str.encode(context, info.utf8);
+ }
+ return str.getByteList().dup();
+ }
+
+ /**
+ * Reads the setting from the options hash. If it is <code>nil</code> or
+ * undefined, returns the default value given.
+ * If not, ensures it is a RubyClass instance and shares the same
+ * allocator as the default value (i.e. for the basic types which have
+ * their specific allocators, this ensures the passed value is
+ * a subclass of them).
+ */
+ RubyClass getClass(String key, RubyClass defaultValue) {
+ 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);
+ }
+}