static mrb_value mrb_grn_table_group_raw(mrb_state *mrb, mrb_value self) { grn_ctx *ctx = (grn_ctx *)mrb->ud; grn_obj *table; mrb_value mrb_keys; grn_table_sort_key *keys; int i, n_keys; mrb_value mrb_result; grn_table_group_result *result; table = DATA_PTR(self); mrb_get_args(mrb, "oo", &mrb_keys, &mrb_result); mrb_keys = mrb_convert_type(mrb, mrb_keys, MRB_TT_ARRAY, "Array", "to_ary"); n_keys = RARRAY_LEN(mrb_keys); keys = GRN_MALLOCN(grn_table_sort_key, n_keys); for (i = 0; i < n_keys; i++) { memcpy(&(keys[i]), DATA_PTR(RARRAY_PTR(mrb_keys)[i]), sizeof(grn_table_sort_key)); } result = DATA_PTR(mrb_result); grn_table_group(ctx, table, keys, n_keys, result, 1); GRN_FREE(keys); grn_mrb_ctx_check(mrb); return mrb_result; }
static mrb_value ctx_array_reference(mrb_state *mrb, mrb_value self) { grn_ctx *ctx = (grn_ctx *)mrb->ud; mrb_value mrb_id_or_name; grn_obj *object; mrb_get_args(mrb, "o", &mrb_id_or_name); if (mrb_nil_p(mrb_id_or_name)) { return mrb_nil_value(); } if (mrb_fixnum_p(mrb_id_or_name)) { grn_id id = mrb_fixnum(mrb_id_or_name); object = grn_ctx_at(ctx, id); } else { mrb_value mrb_name; mrb_name = mrb_convert_type(mrb, mrb_id_or_name, MRB_TT_STRING, "String", "to_str"); object = grn_ctx_get(ctx, RSTRING_PTR(mrb_name), RSTRING_LEN(mrb_name)); } return grn_mrb_value_from_grn_obj(mrb, object); }
static mrb_value mrb_file_s_unlink(mrb_state *mrb, mrb_value obj) { mrb_value *argv; mrb_value pathv; mrb_int argc, i; const char *path; mrb_get_args(mrb, "*", &argv, &argc); for (i = 0; i < argc; i++) { pathv = mrb_convert_type(mrb, argv[i], MRB_TT_STRING, "String", "to_str"); path = mrb_string_value_cstr(mrb, &pathv); if (UNLINK(path) < 0) { mrb_sys_fail(mrb, path); } } return mrb_fixnum_value(argc); }
mrb_value mrb_Float(mrb_state *mrb, mrb_value val) { if (mrb_nil_p(val)) { mrb_raise(mrb, E_TYPE_ERROR, "can't convert nil into Float"); } switch (mrb_type(val)) { case MRB_TT_FIXNUM: return mrb_float_value(mrb, (mrb_float)mrb_fixnum(val)); case MRB_TT_FLOAT: return val; case MRB_TT_STRING: return mrb_float_value(mrb, mrb_str_to_dbl(mrb, val, TRUE)); default: return mrb_convert_type(mrb, val, MRB_TT_FLOAT, "Float", "to_f"); } }
static mrb_value to_hash(mrb_state *mrb, mrb_value hash) { return mrb_convert_type(mrb, hash, MRB_TT_HASH, "Hash", "to_hash"); }
/* retrieve arguments from mrb_state. mrb_get_args(mrb, format, ...) returns number of arguments parsed. fortmat specifiers: o: Object [mrb_value] S: String [mrb_value] A: Array [mrb_value] H: Hash [mrb_value] s: String [char*,int] z: String [char*] a: Array [mrb_value*,int] f: Float [mrb_float] i: Integer [mrb_int] n: Symbol [mrb_sym] &: Block [mrb_value] *: rest argument [mrb_value*,int] |: optional */ int mrb_get_args(mrb_state *mrb, const char *format, ...) { char c; int i = 0; mrb_value *sp = mrb->stack + 1; va_list ap; int argc = mrb->ci->argc; int opt = 0; va_start(ap, format); if (argc < 0) { struct RArray *a = mrb_ary_ptr(mrb->stack[1]); argc = a->len; sp = a->ptr; } while ((c = *format++)) { switch (c) { case '|': case '*': case '&': break; default: if (argc <= i && !opt) { mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); } } switch (c) { case 'o': { mrb_value *p; p = va_arg(ap, mrb_value*); if (i < argc) { *p = *sp++; i++; } } break; case 'S': { mrb_value *p; p = va_arg(ap, mrb_value*); if (i < argc) { *p = to_str(mrb, *sp++); i++; } } break; case 'A': { mrb_value *p; p = va_arg(ap, mrb_value*); if (i < argc) { *p = to_ary(mrb, *sp++); i++; } } break; case 'H': { mrb_value *p; p = va_arg(ap, mrb_value*); if (i < argc) { *p = to_hash(mrb, *sp++); i++; } } break; case 's': { mrb_value ss; struct RString *s; char **ps = 0; int *pl = 0; ps = va_arg(ap, char**); pl = va_arg(ap, int*); if (i < argc) { ss = to_str(mrb, *sp++); s = mrb_str_ptr(ss); *ps = s->ptr; *pl = s->len; i++; } } break; case 'z': { mrb_value ss; struct RString *s; char **ps; ps = va_arg(ap, char**); if (i < argc) { ss = to_str(mrb, *sp++); s = mrb_str_ptr(ss); if (strlen(s->ptr) != s->len) { mrb_raise(mrb, E_ARGUMENT_ERROR, "String contains NUL"); } *ps = s->ptr; i++; } } break; case 'a': { mrb_value aa; struct RArray *a; mrb_value **pb; int *pl; pb = va_arg(ap, mrb_value**); pl = va_arg(ap, int*); if (i < argc) { aa = to_ary(mrb, *sp++); a = mrb_ary_ptr(aa); *pb = a->ptr; *pl = a->len; i++; } } break; case 'f': { mrb_float *p; p = va_arg(ap, mrb_float*); if (i < argc) { switch (mrb_type(*sp)) { case MRB_TT_FLOAT: *p = mrb_float(*sp); break; case MRB_TT_FIXNUM: *p = (mrb_float)mrb_fixnum(*sp); break; case MRB_TT_STRING: mrb_raise(mrb, E_TYPE_ERROR, "String can't be coerced into Float"); break; default: { mrb_value tmp; tmp = mrb_convert_type(mrb, *sp, MRB_TT_FLOAT, "Float", "to_f"); *p = mrb_float(tmp); } break; } sp++; i++; } } break; case 'i': { mrb_int *p; p = va_arg(ap, mrb_int*); if (i < argc) { switch (mrb_type(*sp)) { case MRB_TT_FIXNUM: *p = mrb_fixnum(*sp); break; case MRB_TT_FLOAT: { mrb_float f = mrb_float(*sp); if (!FIXABLE(f)) { mrb_raise(mrb, E_RANGE_ERROR, "float too big for int"); } *p = (mrb_int)f; } break; case MRB_TT_FALSE: *p = 0; break; default: { mrb_value tmp; tmp = mrb_convert_type(mrb, *sp, MRB_TT_FIXNUM, "Integer", "to_int"); *p = mrb_fixnum(tmp); } break; } sp++; i++; } } break; case 'n': { mrb_sym *symp; symp = va_arg(ap, mrb_sym*); if (i < argc) { mrb_value ss; ss = *sp++; if (mrb_type(ss) == MRB_TT_SYMBOL) { *symp = mrb_symbol(ss); } else { *symp = mrb_intern_str(mrb, to_str(mrb, ss)); } i++; } } break; case '&': { mrb_value *p, *bp; p = va_arg(ap, mrb_value*); if (mrb->ci->argc < 0) { bp = mrb->stack + 2; } else { bp = mrb->stack + mrb->ci->argc + 1; } *p = *bp; } break; case '|': opt = 1; break; case '*': { mrb_value **var; int *pl; var = va_arg(ap, mrb_value**); pl = va_arg(ap, int*); if (argc > i) { *pl = argc-i; if (*pl > 0) { *var = sp; i = argc; } i = argc; sp += *pl; } else { *pl = 0; *var = NULL; } } break; default: mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid argument specifier %c", c); break; } } if (!c && argc > i) { mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); } va_end(ap); return i; }
int mrb_get_args(mrb_state *mrb, const char *format, ...) { char c; int i=0; mrb_value *sp = mrb->stack + 1; va_list ap; int argc = mrb->ci->argc; int *argcp; va_start(ap, format); if (argc < 0) { struct RArray *a = mrb_ary_ptr(mrb->stack[1]); argc = a->len; sp = a->buf; } while ((c = *format++)) { switch (c) { case 'o': { mrb_value *p; p = va_arg(ap, mrb_value*); *p = *sp; i++; sp++; } break; case 'i': { mrb_int *p; p = va_arg(ap, mrb_int*); switch (sp->tt) { case MRB_TT_FIXNUM: *p = mrb_fixnum(*sp); break; case MRB_TT_FLOAT: *p = (mrb_int)mrb_float(*sp); break; case MRB_TT_FALSE: *p = 0; break; default: { mrb_value tmp; tmp = mrb_convert_type(mrb, *sp, MRB_TT_FIXNUM, "Integer", "to_int"); *p = mrb_fixnum(tmp); } break; } i++; sp++; } break; case 'f': { mrb_float *p; p = va_arg(ap, mrb_float*); switch (sp->tt) { case MRB_TT_FLOAT: *p = mrb_float(*sp); break; case MRB_TT_FIXNUM: *p = (mrb_float)mrb_fixnum(*sp); break; case MRB_TT_FALSE: *p = 0.0; break; default: { mrb_value tmp; tmp = mrb_convert_type(mrb, *sp, MRB_TT_FLOAT, "Float", "to_f"); *p = mrb_float(tmp); } break; } i++; sp++; } break; case 's': { char **ps = 0; size_t *pl = 0; struct RString *s; if (argc > i) { s = mrb_str_ptr(*sp); ps = va_arg(ap, char**); *ps = s->buf; pl = va_arg(ap, size_t*); *pl = s->len; } i++; sp++; } break; case 'a': { mrb_value *var; var = va_arg(ap, mrb_value*); if (argc > i) { if (var) { memcpy(var, sp, sizeof(mrb_value)*(argc-i)); } //i = mrb->argc; } else { if (var) *var = mrb_ary_new(mrb); } argcp = va_arg(ap, int*); *argcp = argc-i; goto last_var; } break; case 'b': { struct RProc **p; mrb_value *bp = mrb->stack + 1; p = va_arg(ap, struct RProc**); if (mrb->ci->argc > 0) { bp += mrb->ci->argc; } if (mrb_nil_p(*bp)) *p = 0; else *p = mrb_proc_ptr(*bp); } break; case '&': { mrb_value *p, *bp = mrb->stack + 1; p = va_arg(ap, mrb_value*); if (mrb->ci->argc > 0) { bp += mrb->ci->argc; } *p = *bp; } break; case '*': { mrb_value **var; var = va_arg(ap, mrb_value**); argcp = va_arg(ap, int*); if (argc > i) { *argcp = argc-i; if (*argcp > 0) { if (var) { *var = sp; } i += *argcp; } } else { *argcp = 0; *var = NULL; } goto last_var; } break; } }
/* TODO: Fix memory leak on error */ static mrb_value mrb_grn_table_sort(mrb_state *mrb, mrb_value self) { grn_ctx *ctx = (grn_ctx *)mrb->ud; grn_obj *table; grn_obj *result = NULL; grn_table_sort_key *keys; int i, n_keys; int offset = 0; int limit = -1; mrb_value mrb_keys; mrb_value mrb_options = mrb_nil_value(); table = DATA_PTR(self); mrb_get_args(mrb, "o|H", &mrb_keys, &mrb_options); mrb_keys = mrb_convert_type(mrb, mrb_keys, MRB_TT_ARRAY, "Array", "to_ary"); n_keys = RARRAY_LEN(mrb_keys); keys = GRN_MALLOCN(grn_table_sort_key, n_keys); for (i = 0; i < n_keys; i++) { mrb_value mrb_sort_options; mrb_value mrb_sort_key; mrb_value mrb_sort_order; mrb_sort_options = RARRAY_PTR(mrb_keys)[i]; mrb_sort_key = grn_mrb_options_get_lit(mrb, mrb_sort_options, "key"); switch (mrb_type(mrb_sort_key)) { case MRB_TT_STRING : keys[i].key = grn_obj_column(ctx, table, RSTRING_PTR(mrb_sort_key), RSTRING_LEN(mrb_sort_key)); break; case MRB_TT_SYMBOL : { const char *name; mrb_int name_length; name = mrb_sym2name_len(mrb, mrb_symbol(mrb_sort_key), &name_length); keys[i].key = grn_obj_column(ctx, table, name, name_length); } break; default : /* TODO: free */ mrb_raisef(mrb, E_ARGUMENT_ERROR, "sort key must be string or symbol: %S", mrb_sort_key); break; } keys[i].flags = 0; mrb_sort_order = grn_mrb_options_get_lit(mrb, mrb_sort_options, "order"); if (mrb_nil_p(mrb_sort_order) || (mrb_symbol(mrb_sort_order) == mrb_intern_lit(mrb, "ascending"))) { keys[i].flags |= GRN_TABLE_SORT_ASC; } else { keys[i].flags |= GRN_TABLE_SORT_DESC; } } if (!mrb_nil_p(mrb_options)) { mrb_value mrb_offset; mrb_value mrb_limit; mrb_offset = grn_mrb_options_get_lit(mrb, mrb_options, "offset"); if (!mrb_nil_p(mrb_offset)) { offset = mrb_fixnum(mrb_offset); } mrb_limit = grn_mrb_options_get_lit(mrb, mrb_options, "limit"); if (!mrb_nil_p(mrb_limit)) { limit = mrb_fixnum(mrb_limit); } } result = grn_table_create(ctx, NULL, 0, NULL, GRN_TABLE_NO_KEY, NULL, table); grn_table_sort(ctx, table, offset, limit, result, keys, n_keys); for (i = 0; i < n_keys; i++) { grn_obj_unlink(ctx, keys[i].key); } GRN_FREE(keys); grn_mrb_ctx_check(mrb); return grn_mrb_value_from_grn_obj(mrb, result); }
/* retrieve arguments from mrb_state. mrb_get_args(mrb, format, ...) returns number of arguments parsed. fortmat specifiers: o: Object [mrb_value] S: String [mrb_value] A: Array [mrb_value] H: Hash [mrb_value] s: String [char*,int] z: String [char*] a: Array [mrb_value*,int] f: Float [mrb_float] i: Integer [mrb_int] &: Block [mrb_value] *: rest argument [mrb_value*,int] |: optional */ int mrb_get_args(mrb_state *mrb, const char *format, ...) { char c; int i = 0; mrb_value *sp = mrb->stack + 1; va_list ap; int argc = mrb->ci->argc; int opt = 0; va_start(ap, format); if (argc < 0) { struct RArray *a = mrb_ary_ptr(mrb->stack[1]); argc = a->len; sp = a->buf; } while ((c = *format++)) { switch (c) { case '|': case '*': case '&': break; default: if (argc <= i) { if (opt) continue; mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); } } switch (c) { case 'o': { mrb_value *p; p = va_arg(ap, mrb_value*); *p = *sp; i++; sp++; } break; case 'S': { mrb_value *p; p = va_arg(ap, mrb_value*); *p = to_str(mrb, *sp); i++; sp++; } break; case 'A': { mrb_value *p; p = va_arg(ap, mrb_value*); *p = to_ary(mrb, *sp); i++; sp++; } break; case 'H': { mrb_value *p; p = va_arg(ap, mrb_value*); *p = to_hash(mrb, *sp); i++; sp++; } break; case 's': { mrb_value ss; struct RString *s; char **ps = 0; int *pl = 0; ss = to_str(mrb, *sp); s = mrb_str_ptr(ss); ps = va_arg(ap, char**); *ps = s->buf; pl = va_arg(ap, int*); *pl = s->len; i++; sp++; } break; case 'z': { mrb_value ss; struct RString *s; char **ps; ss = to_str(mrb, *sp); s = mrb_str_ptr(ss); if (strlen(s->buf) != s->len) { mrb_raise(mrb, E_ARGUMENT_ERROR, "String contains NUL"); } ps = va_arg(ap, char**); *ps = s->buf; i++; sp++; } break; case 'a': { mrb_value aa; struct RArray *a; mrb_value **pb; int *pl; aa = to_ary(mrb, *sp); a = mrb_ary_ptr(aa); pb = va_arg(ap, mrb_value**); *pb = a->buf; pl = va_arg(ap, int*); *pl = a->len; i++; sp++; } break; case 'f': { mrb_float *p; p = va_arg(ap, mrb_float*); switch (sp->tt) { case MRB_TT_FLOAT: *p = mrb_float(*sp); break; case MRB_TT_FIXNUM: *p = (mrb_float)mrb_fixnum(*sp); break; case MRB_TT_FALSE: *p = 0.0; break; default: { mrb_value tmp; tmp = mrb_convert_type(mrb, *sp, MRB_TT_FLOAT, "Float", "to_f"); *p = mrb_float(tmp); } break; } i++; sp++; } break; case 'i': { mrb_int *p; p = va_arg(ap, mrb_int*); switch (sp->tt) { case MRB_TT_FIXNUM: *p = mrb_fixnum(*sp); break; case MRB_TT_FLOAT: *p = (mrb_int)mrb_float(*sp); break; case MRB_TT_FALSE: *p = 0; break; default: { mrb_value tmp; tmp = mrb_convert_type(mrb, *sp, MRB_TT_FIXNUM, "Integer", "to_int"); *p = mrb_fixnum(tmp); } break; } i++; sp++; } break; case '&': { mrb_value *p, *bp = mrb->stack + 1; p = va_arg(ap, mrb_value*); if (mrb->ci->argc > 0) { bp += mrb->ci->argc; } *p = *bp; } break; case '|': opt = 1; break; case '*': { mrb_value **var; int *pl; var = va_arg(ap, mrb_value**); pl = va_arg(ap, int*); if (argc > i) { *pl = argc-i; if (*pl > 0) { *var = sp; i = argc; } i = argc; sp += *pl; } else { *pl = 0; *var = NULL; } } break; } } if (!c && argc > i) { mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); } va_end(ap); return i; }