Esempio n. 1
0
File: trie.c Progetto: kritik/trie
/*
 * call-seq:
 *   save(filename_base) -> true
 *
 * Saves the trie data to two files, filename_base.da and filename_base.tail.
 * Returns true if saving was successful.
 */
static VALUE rb_trie_save(VALUE self, VALUE filename_base) {
  VALUE da_filename = rb_str_dup(filename_base);
  rb_str_concat(da_filename, rb_str_new2(".da"));
  StringValue(da_filename);
    
  VALUE tail_filename = rb_str_dup(filename_base);
  rb_str_concat(tail_filename, rb_str_new2(".tail"));
  StringValue(tail_filename);

  Trie *trie;
  Data_Get_Struct(self, Trie, trie);

  FILE *da_file = fopen(RSTRING_PTR(da_filename), "w");
  if (da_file == NULL)
    raise_ioerror("Error opening .da file for writing.");
  if (da_write(trie->da, da_file) != 0)
    raise_ioerror("Error writing DArray data.");
  fclose(da_file);

  FILE *tail_file = fopen(RSTRING_PTR(tail_filename), "w");
  if (tail_file == NULL)
    raise_ioerror("Error opening .tail file for writing.");
  if (tail_write(trie->tail, tail_file) != 0)
    raise_ioerror("Error writing Tail data.");
  fclose(tail_file);

  return Qtrue;
}
Esempio n. 2
0
static VALUE
rb_rsvg_dim_to_s(VALUE self)
{
    VALUE ret;

    ret = rb_str_new2("#<");
    rb_str_cat2(ret, rb_obj_classname(self));
    rb_str_cat2(ret, ":");
    rb_str_concat(ret, rb_funcall(INT2NUM(self), id_to_s, 0));
    rb_str_cat2(ret, " ");

    rb_str_cat2(ret, "width=");
    rb_str_concat(ret, to_s(rb_rsvg_dim_get_width(self)));
    rb_str_cat2(ret, ", ");
    rb_str_cat2(ret, "height=");
    rb_str_concat(ret, to_s(rb_rsvg_dim_get_height(self)));
    rb_str_cat2(ret, ", ");
    rb_str_cat2(ret, "em=");
    rb_str_concat(ret, to_s(rb_rsvg_dim_get_em(self)));
    rb_str_cat2(ret, ", ");
    rb_str_cat2(ret, "ex=");
    rb_str_concat(ret, to_s(rb_rsvg_dim_get_ex(self)));
    rb_str_cat2(ret, ">");

    return ret;
}
Esempio n. 3
0
// Dot a single node of a priority queue. Called by pq_to_dot to do the inner work.
// (I'm not proud of this function ;-( )
static
void pq_node2dot(VALUE result_string, priority_node* n, unsigned int level) {
  if (n == NULL) return;  
  unsigned int i;
  for (i=0; i<level; i++) rb_str_cat2(result_string, "  ");  
  if (n->mark)
    rb_str_concat(result_string,
	rb_funcall(Qnil, id_format, 4, rb_str_new2("NODE%i [label=\"%s (%s)\"];\n"), 
	  ULONG2NUM((unsigned long) n), n->object, n->priority));
  else
    rb_str_concat(result_string,
	rb_funcall(Qnil, id_format, 4, rb_str_new2("NODE%i [label=\"%s (%s)\",shape=box];\n"), 
	  ULONG2NUM((unsigned long) n), n->object, n->priority));
  if (n->child != NULL) {
    priority_node* n1 = n->child;
    do {
      pq_node2dot(result_string, n1, level + 1);
      for (i=0; i<level; i++) rb_str_cat2(result_string, "  ");  
      rb_str_concat(result_string,
	  rb_funcall(Qnil, id_format, 4, rb_str_new2("NODE%i -> NODE%i;\n"), 
	    ULONG2NUM((unsigned long) n), ULONG2NUM((unsigned long) n1)));
      n1 = n1->right;
    } while(n1 != n->child);
  }
}
Esempio n. 4
0
/*
 * call-seq:
 *   context.inspect -> String
 *
 * コンテキストの中身を人に見やすい文字列で返す。
 */
static VALUE
rb_grn_context_inspect (VALUE self)
{
    VALUE inspected;
    grn_ctx *context;
    grn_obj *database;
    VALUE rb_database;

    context = SELF(self);

    inspected = rb_str_new2("#<");
    rb_str_concat(inspected, rb_inspect(rb_obj_class(self)));
    rb_str_cat2(inspected, " ");

    rb_str_cat2(inspected, "encoding: <");
    rb_str_concat(inspected, rb_inspect(GRNENCODING2RVAL(context->encoding)));
    rb_str_cat2(inspected, ">, ");

    rb_str_cat2(inspected, "database: <");
    database = grn_ctx_db(context);
    rb_database = GRNDB2RVAL(context, database, RB_GRN_FALSE);
    rb_str_concat(inspected, rb_inspect(rb_database));
    rb_str_cat2(inspected, ">");

    rb_str_cat2(inspected, ">");
    return inspected;
}
Esempio n. 5
0
static VALUE
oletypelib_path(VALUE guid, VALUE version)
{
    int k;
    LONG err;
    HKEY hkey;
    HKEY hlang;
    VALUE lang;
    VALUE path = Qnil;

    VALUE key = rb_str_new2("TypeLib\\");
    rb_str_concat(key, guid);
    rb_str_cat2(key, "\\");
    rb_str_concat(key, version);

    err = reg_open_vkey(HKEY_CLASSES_ROOT, key, &hkey);
    if (err != ERROR_SUCCESS) {
        return Qnil;
    }
    for(k = 0; path == Qnil; k++) {
        lang = reg_enum_key(hkey, k);
        if (lang == Qnil)
            break;
        err = reg_open_vkey(hkey, lang, &hlang);
        if (err == ERROR_SUCCESS) {
            path = reg_get_typelib_file_path(hlang);
            RegCloseKey(hlang);
        }
    }
    RegCloseKey(hkey);
    return path;
}
Esempio n. 6
0
/*
 * call-seq:
 *   read(filename_base) -> Trie
 *
 * Returns a new trie with data as read from disk.
 */
static VALUE rb_trie_read(VALUE self, VALUE filename_base) {
	VALUE da_filename = rb_str_dup(filename_base);
	VALUE tail_filename = rb_str_dup(filename_base);
	rb_str_concat(da_filename, rb_str_new2(".da"));
	rb_str_concat(tail_filename, rb_str_new2(".tail"));
	StringValue(tail_filename);
    StringValue(da_filename);
	Trie *trie = trie_new();

	VALUE obj;
	obj = Data_Wrap_Struct(self, 0, trie_free, trie);

	DArray *old_da = trie->da;
	Tail *old_tail = trie->tail;

	FILE *da_file = fopen(RSTRING_PTR(da_filename), "r");
	if (da_file == NULL)
		raise_ioerror("Error reading .da file.");

	trie->da = da_read(da_file);
	fclose(da_file);

	FILE *tail_file = fopen(RSTRING_PTR(tail_filename), "r");
	if (tail_file == NULL)
		raise_ioerror("Error reading .tail file.");

	trie->tail = tail_read(tail_file);
	fclose(tail_file);

	da_free(old_da);
	tail_free(old_tail);

	return obj;
}
Esempio n. 7
0
static VALUE rb_gsl_rational_inspect(VALUE obj)
{
  VALUE str;
  str = rb_str_new2(rb_class2name(CLASS_OF(obj)));
  rb_str_concat(str, rb_str_new2("\n"));
  rb_str_concat(str, rb_gsl_rational_to_s(obj));
  return str;
}
Esempio n. 8
0
static VALUE dh_quote(VALUE self, VALUE string2quote)
{
 /*
  This quoting-stuff is _very_ basic and probably needs *some* work.
 */
 VALUE quotedStr = rb_funcall(string2quote, rb_intern("gsub"), 2, rb_reg_new("'", 1, 0), rb_str_new2("''"));
 
 return  rb_str_concat(rb_str_concat(rb_str_new2("'"), quotedStr), rb_str_new2("'"));
} // dh_quote
Esempio n. 9
0
static VALUE
inspect_enumerator(VALUE obj, VALUE dummy, int recur)
{
    struct enumerator *e;
    const char *cname;
    VALUE eobj, str;
    int tainted, untrusted;

    TypedData_Get_Struct(obj, struct enumerator, &enumerator_data_type, e);

    cname = rb_obj_classname(obj);

    if (!e || e->obj == Qundef) {
	return rb_sprintf("#<%s: uninitialized>", cname);
    }

    if (recur) {
	str = rb_sprintf("#<%s: ...>", cname);
	OBJ_TAINT(str);
	return str;
    }

    eobj = e->obj;

    tainted   = OBJ_TAINTED(eobj);
    untrusted = OBJ_UNTRUSTED(eobj);

    /* (1..100).each_cons(2) => "#<Enumerator: 1..100:each_cons(2)>" */
    str = rb_sprintf("#<%s: ", cname);
    rb_str_concat(str, rb_inspect(eobj));
    rb_str_buf_cat2(str, ":");
    rb_str_buf_cat2(str, rb_id2name(e->meth));

    if (e->args) {
	long   argc = RARRAY_LEN(e->args);
	VALUE *argv = RARRAY_PTR(e->args);

	rb_str_buf_cat2(str, "(");

	while (argc--) {
	    VALUE arg = *argv++;

	    rb_str_concat(str, rb_inspect(arg));
	    rb_str_buf_cat2(str, argc > 0 ? ", " : ")");

	    if (OBJ_TAINTED(arg)) tainted = TRUE;
	    if (OBJ_UNTRUSTED(arg)) untrusted = TRUE;
	}
    }

    rb_str_buf_cat2(str, ">");

    if (tainted) OBJ_TAINT(str);
    if (untrusted) OBJ_UNTRUST(str);
    return str;
}
Esempio n. 10
0
static VALUE rb_gsl_rational_to_s(VALUE obj)
{
  gsl_rational *r = NULL;
  VALUE str;
  Data_Get_Struct(obj, gsl_rational, r);
  str = rb_gsl_vector_to_s(r->num);
  rb_str_concat(str, rb_str_new2("\n"));
  rb_str_concat(str, rb_gsl_vector_to_s(r->den));
  return str;
}
Esempio n. 11
0
static VALUE
rsym_inspect(VALUE sym, SEL sel)
{
    VALUE str = rb_str_new2(":");
    if (sym_should_be_escaped(sym)) {
	rb_str_concat(str, rb_str_inspect(RSYM(sym)->str));
    }
    else {
	rb_str_concat(str, RSYM(sym)->str);
    }
    return str;
}
Esempio n. 12
0
/*
 * Initialize the package database
 * The database {RPM::DB#root} / var / lib /rpm is created.
 *
 * @param [String] root Root of the database
 * @param [Boolean] writable Whether the database is writable. Default +false+.
 */
static VALUE
db_s_init(int argc, VALUE* argv, VALUE obj)
{
	int writable = 0;
	const char* root;

	switch (argc) {
	case 0:
		rb_raise(rb_eArgError, "too few argument(1..2)");

	case 1: case 2:
		if (TYPE(argv[0]) != T_STRING) {
			rb_raise(rb_eTypeError, "illegal argument type");
		}
		root = RSTRING_PTR(argv[0]);
		if (argc == 2) {
			writable = RTEST(argv[1]);
		}
		break;

	default:
		rb_raise(rb_eArgError, "too many argument(1..2)");
	}

	if (rpmdbInit(root, writable ? O_RDWR | O_CREAT : O_RDONLY)) {
		rb_raise(rb_eRuntimeError, "can not initialize database in %s",
				 RSTRING_PTR(rb_str_concat(rb_str_new2(root),
									   rb_str_new2("/var/lib/rpm"))));
	}

	return Qnil;
}
Esempio n. 13
0
VALUE string_spec_RSTRING_ptr_assign_call(VALUE self, VALUE str) {
  char *ptr = RSTRING(str)->ptr;

  ptr[1] = 'x';
  rb_str_concat(str, rb_str_new2("d"));
  return str;
}
Esempio n. 14
0
VALUE string_spec_rb_str_ptr_readonly_append(VALUE self, VALUE str, VALUE more) {
  char *ptr = rb_str_ptr_readonly(str);

  rb_str_concat(str, more);

  return rb_str_new2(ptr);
}
Esempio n. 15
0
VALUE string_spec_rb_str_ptr_assign_call(VALUE self, VALUE str) {
  char *ptr = rb_str_ptr(str);

  ptr[1] = 'x';
  rb_str_concat(str, rb_str_new2("d"));
  return str;
}
Esempio n. 16
0
static VALUE rb_gsl_permutation_inspect(VALUE obj)
{
  VALUE str;
  char buf[64];
  sprintf(buf, "%s\n", rb_class2name(CLASS_OF(obj)));
  str = rb_str_new2(buf);
  return rb_str_concat(str, rb_gsl_permutation_to_s(obj));
}
Esempio n. 17
0
/*
* call-seq: [](name)
*
* Return the value returned by method +name+.
*/
static VALUE cState_aref(VALUE self, VALUE name)
{
    name = rb_funcall(name, i_to_s, 0);
    if (RTEST(rb_funcall(self, i_respond_to_p, 1, name))) {
        return rb_funcall(self, i_send, 1, name);
    } else {
        return rb_ivar_get(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)));
    }
}
Esempio n. 18
0
static VALUE
collect_body(VALUE i, VALUE str, int argc, VALUE *argv)
{
  if(argc < 1) {
    return Qnil;
  }
  rb_str_concat(str, argv[0]);
  return Qnil;
}
Esempio n. 19
0
/*
 * call-seq:
 *   field.to_str                                     => "name=value"
 *   field.to_s                                       => "name=value"
 * 
 * Obtain a String representation of this PostField in url-encoded 
 * format. This is used to construct the post data for non-multipart
 * POSTs.
 * 
 * Only content fields may be converted to strings.
 */
static VALUE ruby_curl_postfield_to_str(VALUE self) {
  // FIXME This is using the deprecated curl_escape func
  ruby_curl_postfield *rbcpf;
  VALUE result = Qnil;
  
  Data_Get_Struct(self, ruby_curl_postfield, rbcpf);

  if ((rbcpf->local_file == Qnil) && (rbcpf->remote_file == Qnil)) {
    if (rbcpf->name != Qnil) {

      char *tmpchrs = curl_escape(RSTRING_PTR(rbcpf->name), RSTRING_LEN(rbcpf->name));
      
      if (!tmpchrs) {
        rb_raise(eCurlErrInvalidPostField, "Failed to url-encode name `%s'", tmpchrs);
      } else {
        VALUE tmpcontent = Qnil;
        VALUE escd_name = rb_str_new2(tmpchrs);
        curl_free(tmpchrs);
        
        if (rbcpf->content_proc != Qnil) {
          tmpcontent = rb_funcall(rbcpf->content_proc, idCall, 1, self);
        } else if (rbcpf->content != Qnil) {
          tmpcontent = rbcpf->content;
        } else {
          tmpcontent = rb_str_new2("");
        }
        if (TYPE(tmpcontent) != T_STRING) {
          if (rb_respond_to(tmpcontent, rb_intern("to_s"))) {
            tmpcontent = rb_funcall(tmpcontent, rb_intern("to_s"), 0);
          }
          else {
            rb_raise(rb_eRuntimeError, "postfield(%s) is not a string and does not respond_to to_s", RSTRING_PTR(escd_name) );
          }
        }
        //fprintf(stderr, "encoding content: %ld - %s\n", RSTRING_LEN(tmpcontent), RSTRING_PTR(tmpcontent) );
        tmpchrs = curl_escape(RSTRING_PTR(tmpcontent), RSTRING_LEN(tmpcontent));
        if (!tmpchrs) {
          rb_raise(eCurlErrInvalidPostField, "Failed to url-encode content `%s'", tmpchrs);
        } else {
          VALUE escd_content = rb_str_new2(tmpchrs);
          curl_free(tmpchrs);
          
          result = escd_name;
          rb_str_cat(result, "=", 1);
          rb_str_concat(result, escd_content); 
        }            
      }
    } else {
      rb_raise(eCurlErrInvalidPostField, "Cannot convert unnamed field to string");
    }      
  } else {
    rb_raise(eCurlErrInvalidPostField, "Cannot convert non-content field to string");
  }  
  
  return result;
}
Esempio n. 20
0
    VALUE
cb_unify_key(struct cb_bucket_st *bucket, VALUE key, int apply_prefix)
{
    VALUE ret = Qnil, tmp;

    if (RTEST(bucket->key_prefix_val) && apply_prefix) {
        ret = rb_str_dup(bucket->key_prefix_val);
    }
    switch (TYPE(key)) {
        case T_STRING:
            return NIL_P(ret) ? key : rb_str_concat(ret, key);
        case T_SYMBOL:
            tmp = STR_NEW_CSTR(rb_id2name(SYM2ID(key)));
            return NIL_P(ret) ? tmp : rb_str_concat(ret, tmp);
        default:    /* call #to_str or raise error */
            tmp = StringValue(key);
            return NIL_P(ret) ? tmp : rb_str_concat(ret, tmp);
    }
}
Esempio n. 21
0
/*
 *  call-seq:
 *     WIN32OLE_PARAM#inspect -> String
 *
 *  Returns the parameter name with class name. If the parameter has default value,
 *  then returns name=value string with class name.
 *
 */
static VALUE
foleparam_inspect(VALUE self)
{
    VALUE detail = foleparam_name(self);
    VALUE defval = foleparam_default(self);
    if (defval != Qnil) {
        rb_str_cat2(detail, "=");
        rb_str_concat(detail, rb_inspect(defval));
    }
    return make_inspect("WIN32OLE_PARAM", detail);
}
Esempio n. 22
0
static VALUE
cr_glyph_to_s (VALUE self)
{
  VALUE ret;

  ret = rb_str_new2 ("#<");
  rb_str_cat2 (ret, rb_class2name (CLASS_OF (self)));
  rb_str_cat2 (ret, ": ");
  rb_str_cat2 (ret, "index=");
  rb_str_concat (ret, rb_inspect (cr_glyph_index (self)));
  rb_str_cat2 (ret, ", ");
  rb_str_cat2 (ret, "x=");
  rb_str_concat (ret, rb_inspect (cr_glyph_x (self)));
  rb_str_cat2 (ret, ", ");
  rb_str_cat2 (ret, "y=");
  rb_str_concat (ret, rb_inspect (cr_glyph_y (self)));
  rb_str_cat2 (ret, ">");

  return ret;
}
Esempio n. 23
0
/*
 * call-seq:
 *    cmp.inspect  ->  string
 *
 * Returns the value as a string for inspection.
 *
 *    Complex(2).inspect                       #=> "(2+0i)"
 *    Complex('-8/6').inspect                  #=> "((-4/3)+0i)"
 *    Complex('1/2i').inspect                  #=> "(0+(1/2)*i)"
 *    Complex(0, Float::INFINITY).inspect      #=> "(0+Infinity*i)"
 *    Complex(Float::NAN, Float::NAN).inspect  #=> "(NaN+NaN*i)"
 */
static VALUE
nucomp_inspect(VALUE self)
{
    VALUE s;

    s = rb_usascii_str_new2("(");
    rb_str_concat(s, f_format(self, rb_inspect));
    rb_str_cat2(s, ")");

    return s;
}
Esempio n. 24
0
/*
 * call-seq:
 *    rat.inspect  ->  string
 *
 * Returns the value as a string for inspection.
 *
 * For example:
 *
 *    Rational(2).inspect      #=> "(2/1)"
 *    Rational(-8, 6).inspect  #=> "(-4/3)"
 *    Rational('0.5').inspect  #=> "(1/2)"
 */
static VALUE
nurat_inspect(VALUE self, SEL sel)
{
    VALUE s;

    s = rb_usascii_str_new2("(");
    rb_str_concat(s, f_format(self, f_inspect));
    rb_str_cat2(s, ")");

    return s;
}
Esempio n. 25
0
static VALUE
f_format(VALUE self, VALUE (*func)(VALUE))
{
    VALUE s;
    get_dat1(self);

    s = (*func)(dat->num);
    rb_str_cat2(s, "/");
    rb_str_concat(s, (*func)(dat->den));

    return s;
}
Esempio n. 26
0
static int
write_body2mem(client_t *client, const char *buffer, size_t buffer_len)
{
  /* printf("body2mem called\n"); */
  VALUE obj = (VALUE)client->body;
  rb_str_concat(obj, rb_str_new(buffer, buffer_len));
  client->body_readed += buffer_len;
#ifdef DEBUG
  printf("write_body2mem %d bytes \n", buffer_len);
#endif
  return client->body_readed;
}
Esempio n. 27
0
/*
* call-seq: []=(name, value)
*
* Set the attribute name to value.
*/
static VALUE cState_aset(VALUE self, VALUE name, VALUE value)
{
    VALUE name_writer;

    name = rb_funcall(name, i_to_s, 0);
    name_writer = rb_str_cat2(rb_str_dup(name), "=");
    if (RTEST(rb_funcall(self, i_respond_to_p, 1, name_writer))) {
        return rb_funcall(self, i_send, 2, name_writer, value);
    } else {
        rb_ivar_set(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)), value);
    }
    return Qnil;
}
Esempio n. 28
0
static VALUE
//iter_struct_inspect(na_loop_t *const lp)
iter_struct_inspect(char *ptr, size_t pos, VALUE opt)
{
    VALUE   types, defs, def, name, elmt, vary, v, x;
    size_t  ofs;
    long    i, len;
    narray_view_t *ne;

    types = RARRAY_AREF(opt,0);
    defs = RARRAY_AREF(opt,1);

    len = RARRAY_LEN(types);
    vary = rb_ary_new2(len);

    for (i=0; i<len; i++) {
        def  = RARRAY_AREF(defs,i);
        name = RARRAY_AREF(def,0);
        ofs  = NUM2SIZET(RARRAY_AREF(def,2));
        elmt = RARRAY_AREF(types,i);
        GetNArrayView(elmt,ne);
        ne->offset = pos + ofs;
        v = rb_str_concat(rb_sym_to_s(name), rb_str_new2(": "));
        x = rb_funcall(elmt, rb_intern("format_to_a"), 0);        // <-- fix me
        if (ne->base.ndim==0) {
            x = rb_funcall(x, rb_intern("first"), 0);
        }
        x = rb_funcall(x, rb_intern("to_s"), 0);
        v = rb_str_concat(v, x);
        rb_ary_push(vary, v);
    }
    v = rb_ary_join(vary, rb_str_new2(", "));
    v = rb_str_concat(rb_str_new2("["), v);
    v = rb_str_concat(v, rb_str_new2("]"));
    return v;
}
Esempio n. 29
0
/*
Returns the name of the Python object which this instance wraps.

If it cannot determine a reasonable name it just gives up.
*/
static
VALUE rpObjectectGetName(VALUE self)
{
	//It only makes sense to query a python object if the interpreter is running.
	if(Py_IsInitialized())
	{
		PyObject *pObject,*pName,*pRepr;
		VALUE rName;
		
		pObject = rpObjectGetPyObject(self);
		
		
		pName = PyObject_GetAttrString(pObject,"__name__");
		
		if(!pName)
		{
			PyErr_Clear();
			
			pName = PyObject_GetAttrString(pObject,"__class__");
	 		pRepr = PyObject_Repr(pName);
			rName = ptorString(pRepr);
			Py_XDECREF(pRepr);
			
			return rb_str_concat(rb_str_new2("An instance of "), rName);
			if(!pName)
			{
				PyErr_Clear();
				
				pName = PyObject_Repr(pObject);
				
				if(!pName)
				{
					PyErr_Clear();
					return rb_str_new2("__Unnameable__");
				}
			}
		}
		
		rName = ptorString(pName);
		
		Py_XDECREF(pName);
		
		return rName;
	}
	
	return rb_str_new2("__FREED__");

}
Esempio n. 30
0
/*
 * The package database is opened, but transactional processing
 * (@see RPM::DB#transaction) cannot be done for when +writable+ is false.
 * When +writable+ is +false+ then the generated object gets freezed.
 * @param [Boolean] writable Whether the database is writable. Default is +false+.
 * @param [String] root Root path for the database, default is empty.
 * @return [RPM::DB]
 *
 * @example
 *   db = RPM::DB.open
 *   db.each do |pkg|
 *     puts pkg.name
 *   end
 */
static VALUE
db_s_open(int argc, VALUE* argv, VALUE obj)
{
	VALUE db;
	rpm_db_t* rdb;
	int writable = 0;
	const char* root = "";

	switch (argc) {
	case 0:
		break;

	case 1:
		writable = RTEST(argv[0]);
		break;

	case 2:
		if (!NIL_P(argv[1])) {
			if (TYPE(argv[1]) != T_STRING) {
				rb_raise(rb_eTypeError, "illegal argument type");
			}
			root = RSTRING_PTR(argv[1]);
		}
		writable = RTEST(argv[0]);
		break;

	default:
		rb_raise(rb_eArgError, "too many argument(0..2)");
	}


	rdb = ALLOC_N(rpm_db_t,1);
	if (rpmdbOpen(root, &(rdb->db), writable ? O_RDWR | O_CREAT : O_RDONLY, 0644)) {
		free(rdb);
		rb_raise(rb_eRuntimeError, "can not open database in %s",
				 RSTRING_PTR(rb_str_concat(rb_str_new2(root),
			         rb_str_new2("/var/lib/rpm"))));
	}

	rdb->ref_count = 0;
	db_ref(rdb);
	db = Data_Wrap_Struct(rpm_cDB, NULL, db_free, rdb);
	if (!writable) {
		rb_obj_freeze(db);
	}
	return db;
}