    /*
     *  call-seq:
     *     IndexReader.new(dir) -> index_reader
     *
     *  Create a new IndexReader. You can either pass a string path to a
     *  file-system directory or an actual Ferret::Store::Directory object. For
     *  example;
     *
     *    dir = RAMDirectory.new()
     *    iw = IndexReader.new(dir)
     *
     *    dir = FSDirectory.new("/path/to/index")
     *    iw = IndexReader.new(dir)
     *
     *    iw = IndexReader.new("/path/to/index")
     *
     *  You can also create a what used to be known as a MultiReader by passing an
     *  array of IndexReader objects, Ferret::Store::Directory objects or
     *  file-system paths;
     *
     *    iw = IndexReader.new([dir, dir2, dir3])
     *
     *    iw = IndexReader.new([reader1, reader2, reader3])
     *
     *    iw = IndexReader.new(["/path/to/index1", "/path/to/index2"])
     */
    static VALUE
    frt_ir_init(VALUE self, VALUE rdir)
    {
        Store *store = NULL;
        IndexReader *ir;
        int i;
        FieldInfos *fis;
        VALUE rfield_num_map = rb_hash_new();

        if (TYPE(rdir) == T_ARRAY) {
            VALUE rdirs = rdir;
            const int reader_cnt = RARRAY(rdir)->len;
            IndexReader **sub_readers = ALLOC_N(IndexReader *, reader_cnt);
            int i;
            for (i = 0; i < reader_cnt; i++) {
                rdir = RARRAY(rdirs)->ptr[i];
                switch (TYPE(rdir)) {
                    case T_DATA:
                        if (CLASS_OF(rdir) == cIndexReader) {
                            Data_Get_Struct(rdir, IndexReader, sub_readers[i]);
                            REF(sub_readers[i]);
                            continue;
                        } else if (RTEST(rb_obj_is_kind_of(rdir, cDirectory))) {
                            store = DATA_PTR(rdir);
                        } else {
                            rb_raise(rb_eArgError, "A Multi-IndexReader can only "
                                     "be created from other IndexReaders, "
                                     "Directory objects or file-system paths. "
                                     "Not %s",
                                     rs2s(rb_obj_as_string(rdir)));
                        }
                        break;
                    case T_STRING:
                        frt_create_dir(rdir);
                        store = open_fs_store(rs2s(rdir));
                        DEREF(store);
                        break;
                    default:
                        rb_raise(rb_eArgError, "%s isn't a valid directory "
                                 "argument. You should use either a String or "
                                 "a Directory",
                                 rs2s(rb_obj_as_string(rdir)));
                        break;
                }
                sub_readers[i] = ir_open(store);
            }
            ir = mr_open(sub_readers, reader_cnt);
            Frt_Wrap_Struct(self, &frt_mr_mark, &frt_ir_free, ir);
        } else {
            switch (TYPE(rdir)) {
                case T_DATA:
                    store = DATA_PTR(rdir);
                    break;
                case T_STRING:
                    frt_create_dir(rdir);
                    store = open_fs_store(rs2s(rdir));
                    DEREF(store);
                    break;
                default:
                    rb_raise(rb_eArgError, "%s isn't a valid directory argument. "
                             "You should use either a String or a Directory",
                             rs2s(rb_obj_as_string(rdir)));
                    break;
            }
            ir = ir_open(store);
            Frt_Wrap_Struct(self, &frt_ir_mark, &frt_ir_free, ir);
        }
        object_add(ir, self);

        fis = ir->fis;
        for (i = 0; i < fis->size; i++) {
            FieldInfo *fi = fis->fields[i];
            rb_hash_aset(rfield_num_map,
                         ID2SYM(rb_intern(fi->name)),
                         INT2FIX(fi->number));
        }
        rb_ivar_set(self, id_fld_num_map, rfield_num_map);

        return self;
    }