/* * This code is copyrighted work by Daniel Luz . * * Distributed under the Ruby license: https://www.ruby-lang.org/en/about/license.txt */ 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 RubyHash opts; private RuntimeInfo info; OptionsReader(ThreadContext context, IRubyObject vOpts) { this.context = context; this.runtime = context.getRuntime(); if (vOpts == null || vOpts.isNil()) { opts = null; } else if (vOpts.respondsTo("to_hash")) { opts = vOpts.convertToHash(); } else if (vOpts.respondsTo("to_h")) { opts = vOpts.callMethod(context, "to_h").convertToHash(); } else { opts = vOpts.convertToHash(); /* Should just raise the correct TypeError */ } } private RuntimeInfo getRuntimeInfo() { if (info != null) return info; info = RuntimeInfo.forRuntime(runtime); return info; } /** * 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 null * 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 false, returns null; attempts to * coerce the value to {@link RubyString String} otherwise. * @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 * evaluate to false and can't be * converted to string */ ByteList getString(String key) { RubyString str = getString(key, null); return str == null ? null : str.getByteList().dup(); } RubyString getString(String key, RubyString defaultValue) { IRubyObject value = get(key); 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()); } return str; } /** * Reads the setting from the options hash. If it is nil 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; return (RubyClass)value; } public RubyHash getHash(String key) { IRubyObject value = get(key); if (value == null || value.isNil()) return new RubyHash(runtime); return (RubyHash) value; } }