    /*
     * call-seq: new(source, opts => {})
     *
     * Creates a new JSON::Ext::Parser instance for the string _source_.
     *
     * Creates a new JSON::Ext::Parser instance for the string _source_.
     *
     * It will be configured by the _opts_ hash. _opts_ can have the following
     * keys:
     *
     * _opts_ can have the following keys:
     * * *max_nesting*: The maximum depth of nesting allowed in the parsed data
     *   structures. Disable depth checking with :max_nesting => false|nil|0, it
     *   defaults to 19.
     * * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
     *   defiance of RFC 4627 to be parsed by the Parser. This option defaults to
     *   false.
     * * *symbolize_names*: If set to true, returns symbols for the names
     *   (keys) in a JSON object. Otherwise strings are returned, which is also
     *   the default.
     * * *create_additions*: If set to false, the Parser doesn't create
     *   additions even if a matchin class and create_id was found. This option
     *   defaults to true.
     * * *object_class*: Defaults to Hash
     * * *array_class*: Defaults to Array
     */
    static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
    {
        VALUE source, opts;
        GET_PARSER_INIT;

        if (json->Vsource) {
            rb_raise(rb_eTypeError, "already initialized instance");
        }
        rb_scan_args(argc, argv, "11", &source, &opts);
        if (!NIL_P(opts)) {
            opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
            if (NIL_P(opts)) {
                rb_raise(rb_eArgError, "opts needs to be like a hash");
            } else {
                VALUE tmp = ID2SYM(i_max_nesting);
                if (option_given_p(opts, tmp)) {
                    VALUE max_nesting = rb_hash_aref(opts, tmp);
                    if (RTEST(max_nesting)) {
                        Check_Type(max_nesting, T_FIXNUM);
                        json->max_nesting = FIX2INT(max_nesting);
                    } else {
                        json->max_nesting = 0;
                    }
                } else {
                    json->max_nesting = 19;
                }
                tmp = ID2SYM(i_allow_nan);
                if (option_given_p(opts, tmp)) {
                    json->allow_nan = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
                } else {
                    json->allow_nan = 0;
                }
                tmp = ID2SYM(i_symbolize_names);
                if (option_given_p(opts, tmp)) {
                    json->symbolize_names = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
                } else {
                    json->symbolize_names = 0;
                }
                tmp = ID2SYM(i_quirks_mode);
                if (option_given_p(opts, tmp)) {
                    VALUE quirks_mode = rb_hash_aref(opts, tmp);
                    json->quirks_mode = RTEST(quirks_mode) ? 1 : 0;
                } else {
                    json->quirks_mode = 0;
                }
                tmp = ID2SYM(i_create_additions);
                if (option_given_p(opts, tmp)) {
                    json->create_additions = RTEST(rb_hash_aref(opts, tmp));
                } else {
                    json->create_additions = 1;
                }
                tmp = ID2SYM(i_create_id);
                if (option_given_p(opts, tmp)) {
                    json->create_id = rb_hash_aref(opts, tmp);
                } else {
                    json->create_id = rb_funcall(mJSON, i_create_id, 0);
                }
                tmp = ID2SYM(i_object_class);
                if (option_given_p(opts, tmp)) {
                    json->object_class = rb_hash_aref(opts, tmp);
                } else {
                    json->object_class = Qnil;
                }
                tmp = ID2SYM(i_array_class);
                if (option_given_p(opts, tmp)) {
                    json->array_class = rb_hash_aref(opts, tmp);
                } else {
                    json->array_class = Qnil;
                }
                tmp = ID2SYM(i_match_string);
                if (option_given_p(opts, tmp)) {
                    VALUE match_string = rb_hash_aref(opts, tmp);
                    json->match_string = RTEST(match_string) ? match_string : Qnil;
                } else {
                    json->match_string = Qnil;
                }
            }
        } else {
            json->max_nesting = 19;
            json->allow_nan = 0;
            json->create_additions = 1;
            json->create_id = rb_funcall(mJSON, i_create_id, 0);
            json->object_class = Qnil;
            json->array_class = Qnil;
        }
        source = rb_convert_type(source, T_STRING, "String", "to_str");
        if (!json->quirks_mode) {
          source = convert_encoding(StringValue(source));
        }
        json->current_nesting = 0;
        json->len = RSTRING_LEN(source);
        json->source = RSTRING_PTR(source);;
        json->Vsource = source;
        return self;
    }