Esempio n. 1
0
static VALUE decode(VALUE self, VALUE str)
{
  int rc;
  punycode_uint *ustr;
  size_t len;
  char *buf = NULL;
  VALUE retv;

  str = rb_check_convert_type(str, T_STRING, "String", "to_s");

  len = RSTRING_LEN(str);
  ustr = malloc(len * sizeof(punycode_uint));

  if (ustr == NULL) {
    rb_raise(rb_eNoMemError, "cannot allocate memory (%d bytes)", (uint32_t)len);
    return Qnil;
  }

  rc = punycode_decode(RSTRING_LEN(str), RSTRING_PTR(str),
                       &len, ustr, NULL);

  if (rc != PUNYCODE_SUCCESS) {
    xfree(ustr);
    rb_raise(ePunycodeError, "%s (%d)", punycode_strerror(rc), rc);
    return Qnil;
  }

  buf = stringprep_ucs4_to_utf8(ustr, len, NULL, &len);
  retv = rb_enc_str_new(buf, len, rb_utf8_encoding());
  xfree(ustr);
  xfree(buf);
  return retv;
}
Esempio n. 2
0
/* @overload write_plist(hash, path)
 *
 * Writes the serialized contents of a property list to the specified path.
 *
 * @note This does not yet support all possible types that can exist in a valid property list.
 *
 * @note This currently only assumes to be given an Xcode project document.
 *       This means that it only accepts dictionaries, arrays, and strings in
 *       the document.
 *
 * @param [Hash] hash     The property list to serialize.
 * @param [String] path   The path to the property list file.
 * @return [true, false]  Wether or not saving was successful.
 */
static VALUE
write_plist(VALUE self, VALUE hash, VALUE path) {
  VALUE h = rb_check_convert_type(hash, T_HASH, "Hash", "to_hash");
  if (NIL_P(h)) {
    rb_raise(rb_eTypeError, "%s can't be coerced to Hash", rb_obj_classname(hash));
  }

  CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL,
                                                          0,
                                                          &kCFTypeDictionaryKeyCallBacks,
                                                          &kCFTypeDictionaryValueCallBacks);

  rb_hash_foreach(h, dictionary_set, (st_data_t)dict);

  CFURLRef fileURL = str_to_url(path);
  CFWriteStreamRef stream = CFWriteStreamCreateWithFile(NULL, fileURL);
  CFRelease(fileURL);

  CFIndex success = 0;
  if (CFWriteStreamOpen(stream)) {
    CFStringRef errorString;
    success = CFPropertyListWriteToStream(dict, stream, kCFPropertyListXMLFormat_v1_0, &errorString);
    if (!success) {
      CFShow(errorString);
    }
  } else {
    printf("Unable to open stream!\n");
  }

  CFRelease(dict);
  return success ? Qtrue : Qfalse;
}
Esempio n. 3
0
PRIMITIVE VALUE
vm_to_ary(VALUE obj)
{
    VALUE ary = rb_check_convert_type(obj, T_ARRAY, "Array", "to_ary");
    if (NIL_P(ary)) {
	ary = rb_ary_new4(1, &obj);
    }
    return ary;
}
Esempio n. 4
0
static void
vm_caller_setup_arg_block(const rb_thread_t *th, rb_control_frame_t *reg_cfp,
			  struct rb_calling_info *calling, const struct rb_call_info *ci, rb_iseq_t *blockiseq, const int is_super)
{
    if (ci->flag & VM_CALL_ARGS_BLOCKARG) {
	rb_proc_t *po;
	VALUE proc;

	proc = *(--reg_cfp->sp);

	if (NIL_P(proc)) {
	    calling->blockptr = NULL;
	}
	else if (SYMBOL_P(proc) && rb_method_basic_definition_p(rb_cSymbol, idTo_proc)) {
	    calling->blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(reg_cfp);
	    calling->blockptr->iseq = (rb_iseq_t *)proc;
	    calling->blockptr->proc = proc;
	}
	else if (RUBY_VM_IFUNC_P(proc)) {
	    calling->blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(reg_cfp);
	    calling->blockptr->iseq = (rb_iseq_t *)proc;
	    calling->blockptr->proc = proc;
	}
	else {
	    if (!rb_obj_is_proc(proc)) {
		VALUE b;
		b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");

		if (NIL_P(b) || !rb_obj_is_proc(b)) {
		    rb_raise(rb_eTypeError,
			     "wrong argument type %s (expected Proc)",
			     rb_obj_classname(proc));
		}
		proc = b;
	    }
	    GetProcPtr(proc, po);
	    calling->blockptr = &po->block;
	    RUBY_VM_GET_BLOCK_PTR_IN_CFP(reg_cfp)->proc = proc;
	}
    }
    else if (blockiseq != 0) { /* likely */
	rb_block_t *blockptr = calling->blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(reg_cfp);
	blockptr->iseq = blockiseq;
	blockptr->proc = 0;
    }
    else {
	if (is_super) {
	    calling->blockptr = GET_BLOCK_PTR();
	}
	else {
	    calling->blockptr = NULL;
	}
    }
}
Esempio n. 5
0
PRIMITIVE VALUE
vm_ary_cat(VALUE ary, VALUE obj)
{
    VALUE ary2 = rb_check_convert_type(obj, T_ARRAY, "Array", "to_a");
    if (!NIL_P(ary2)) {
	rb_ary_concat(ary, ary2);
    }
    else {
	rb_ary_push(ary, obj);
    }
    return ary;
}
Esempio n. 6
0
PRIMITIVE VALUE
vm_ary_check(VALUE obj, int size)
{
    VALUE ary = rb_check_convert_type(obj, T_ARRAY, "Array", "to_ary");
    if (NIL_P(ary)) {
	rb_raise(rb_eTypeError, "expected Array");
    }
    if (RARRAY_LEN(ary) != size) {
	rb_raise(rb_eArgError, "expected Array of size %d, got %ld",
		size, RARRAY_LEN(ary));
    }
    return ary;
}
Esempio n. 7
0
vm_resolve_args(VALUE **pargv, size_t argv_size, int *pargc, VALUE *args)
{
    unsigned int i, argc = *pargc, real_argc = 0, j = 0;
    VALUE *argv = *pargv;
    bool splat_arg_follows = false;
    for (i = 0; i < argc; i++) {
	VALUE arg = args[j++];
	if (arg == SPLAT_ARG_FOLLOWS) {
	    splat_arg_follows = true;
	    i--;
	}
	else {
	    if (splat_arg_follows) {
		VALUE ary = rb_check_convert_type(arg, T_ARRAY, "Array",
			"to_a");
		if (NIL_P(ary)) {
		    ary = rb_ary_new4(1, &arg);
		}
		int count = RARRAY_LEN(ary);
		if (real_argc + count >= argv_size) {
		    const size_t new_argv_size = real_argc + count + 100;
		    VALUE *new_argv = (VALUE *)xmalloc_ptrs(sizeof(VALUE)
			    * new_argv_size);
		    memcpy(new_argv, argv, sizeof(VALUE) * argv_size);
		    argv = new_argv;
		    argv_size = new_argv_size;
		}
		int j;
		for (j = 0; j < count; j++) {
		    argv[real_argc++] = RARRAY_AT(ary, j);
		}
		splat_arg_follows = false;
	    }
	    else {
		if (real_argc >= argv_size) {
		    const size_t new_argv_size = real_argc + 100;
		    VALUE *new_argv = (VALUE *)xmalloc_ptrs(sizeof(VALUE)
			    * new_argv_size);
		    memcpy(new_argv, argv, sizeof(VALUE) * argv_size);
		    argv = new_argv;
		    argv_size = new_argv_size;
		}
		argv[real_argc++] = arg;
	    }
	}
    }
    *pargv = argv;
    *pargc = real_argc;
}
Esempio n. 8
0
PRIMITIVE void *
vm_get_block(VALUE obj)
{
    if (obj == Qnil) {
	return NULL;
    }

    VALUE proc = rb_check_convert_type(obj, T_DATA, "Proc", "to_proc");
    if (NIL_P(proc)) {
	rb_raise(rb_eTypeError,
		"wrong argument type %s (expected Proc)",
		rb_obj_classname(obj));
    }
    return rb_proc_get_block(proc);
}
Esempio n. 9
0
static VALUE
get_hash(volatile VALUE *hash, int argc, const VALUE *argv)
{
    VALUE tmp;

    if (*hash != Qundef) return *hash;
    if (argc != 2) {
	rb_raise(rb_eArgError, "one hash required");
    }
    tmp = rb_check_convert_type(argv[1], T_HASH, "Hash", "to_hash");
    if (NIL_P(tmp)) {
	rb_raise(rb_eArgError, "one hash required");
    }
    return (*hash = tmp);
}
Esempio n. 10
0
PRIMITIVE VALUE
vm_when_splat(unsigned char overriden, VALUE comparedTo, VALUE splat)
{
    VALUE ary = rb_check_convert_type(splat, T_ARRAY, "Array", "to_a");
    if (NIL_P(ary)) {
	ary = rb_ary_new4(1, &splat);
    }
    long i, count = RARRAY_LEN(ary);
    for (i = 0; i < count; i++) {
	VALUE o = RARRAY_AT(ary, i);
	if (RTEST(vm_fast_eqq(o, comparedTo, overriden))) {
	    return Qtrue;
	}
    }
    return Qfalse;
}
Esempio n. 11
0
static VALUE
rhash_set_default_proc(VALUE hash, SEL sel, VALUE proc)
{
    rhash_modify(hash);
    VALUE tmp = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
    if (NIL_P(tmp)) {
        rb_raise(rb_eTypeError,
		"wrong default_proc type %s (expected Proc)",
		rb_obj_classname(proc));
    }
    proc = tmp;
    default_proc_arity_check(proc);
    GC_WB(&RHASH(hash)->ifnone, proc);
    RHASH(hash)->has_proc_default = true;
    return proc;
}
Esempio n. 12
0
File: proc.c Progetto: MSch/MacRuby
VALUE
rb_proc_check_and_call(VALUE proc, int argc, VALUE *argv)
{
    VALUE tmp = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
    if (NIL_P(tmp)) {
        rb_raise(rb_eTypeError,
		"wrong type %s (expected Proc)",
		rb_obj_classname(proc));
    }
    proc = tmp;

    const int arity = rb_proc_arity(proc);
    if (arity != argc) {
	rb_raise(rb_eArgError, "expected Proc with %d arguments (got %d)",
		argc, arity);
    }
    return proc_call(proc, 0, argc, argv);
}
Esempio n. 13
0
static VALUE encode(VALUE self, VALUE str)
{
  int rc;
  punycode_uint *ustr;
  size_t len;
  size_t buflen = 0x100;
  char *buf = NULL;
  VALUE retv;

  str = rb_check_convert_type(str, T_STRING, "String", "to_s");
  ustr = stringprep_utf8_to_ucs4(RSTRING_PTR(str), RSTRING_LEN(str), &len);

  while (1) {
    buf = realloc(buf, buflen);

    if (buf == NULL) {
      xfree(ustr);
      rb_raise(rb_eNoMemError, "cannot allocate memory (%d bytes)", (uint32_t)buflen);
      return Qnil;
    }

    rc = punycode_encode(len, ustr, NULL, &buflen, buf);

    if (rc == PUNYCODE_SUCCESS) {
      break;
    } else if (rc == PUNYCODE_BIG_OUTPUT) {
      buflen += 0x100;
    } else {
      xfree(ustr);
      xfree(buf);
      rb_raise(ePunycodeError, "%s (%d)", punycode_strerror(rc), rc);
      return Qnil;
    }
  }

  retv = rb_str_new(buf, buflen);
  xfree(ustr);
  xfree(buf);
  return retv;
}
Esempio n. 14
0
void
rb_grn_scan_options (VALUE options, ...)
{
    VALUE original_options = options;
    VALUE available_keys;
    const char *key;
    VALUE *value;
    va_list args;

    options = rb_check_convert_type(options, T_HASH, "Hash", "to_hash");
    if (NIL_P(options)) {
        options = rb_hash_new();
    } else if (options == original_options) {
        options = rb_funcall(options, rb_intern("dup"), 0);
    }

    available_keys = rb_ary_new();
    va_start(args, options);
    key = va_arg(args, const char *);
    while (key) {
        VALUE rb_key;
        value = va_arg(args, VALUE *);

        rb_key = RB_GRN_INTERN(key);
        rb_ary_push(available_keys, rb_key);
        *value = rb_funcall(options, rb_intern("delete"), 1, rb_key);

        key = va_arg(args, const char *);
    }
    va_end(args);

    if (RVAL2CBOOL(rb_funcall(options, rb_intern("empty?"), 0)))
        return;

    rb_raise(rb_eArgError,
             "unexpected key(s) exist: %s: available keys: %s",
             rb_grn_inspect(rb_funcall(options, rb_intern("keys"), 0)),
             rb_grn_inspect(available_keys));
}
Esempio n. 15
0
VALUE
rb_grn_check_convert_to_hash (VALUE object)
{
    return rb_check_convert_type(object, RUBY_T_HASH, "Hash", "to_hash");
}
Esempio n. 16
0
/*
 * call-seq: configure(opts)
 *
 * Configure this State instance with the Hash _opts_, and return
 * itself.
 */
static VALUE cState_configure(VALUE self, VALUE opts)
{
    VALUE tmp;
    GET_STATE(self);
    tmp = rb_check_convert_type(opts, T_HASH, "Hash", "to_hash");
    if (NIL_P(tmp)) tmp = rb_convert_type(opts, T_HASH, "Hash", "to_h");
    opts = tmp;
    tmp = rb_hash_aref(opts, ID2SYM(i_indent));
    if (RTEST(tmp)) {
        unsigned long len;
        Check_Type(tmp, T_STRING);
        len = RSTRING_LEN(tmp);
        state->indent = fstrndup(RSTRING_PTR(tmp), len + 1);
        state->indent_len = len;
    }
    tmp = rb_hash_aref(opts, ID2SYM(i_space));
    if (RTEST(tmp)) {
        unsigned long len;
        Check_Type(tmp, T_STRING);
        len = RSTRING_LEN(tmp);
        state->space = fstrndup(RSTRING_PTR(tmp), len + 1);
        state->space_len = len;
    }
    tmp = rb_hash_aref(opts, ID2SYM(i_space_before));
    if (RTEST(tmp)) {
        unsigned long len;
        Check_Type(tmp, T_STRING);
        len = RSTRING_LEN(tmp);
        state->space_before = fstrndup(RSTRING_PTR(tmp), len + 1);
        state->space_before_len = len;
    }
    tmp = rb_hash_aref(opts, ID2SYM(i_array_nl));
    if (RTEST(tmp)) {
        unsigned long len;
        Check_Type(tmp, T_STRING);
        len = RSTRING_LEN(tmp);
        state->array_nl = fstrndup(RSTRING_PTR(tmp), len + 1);
        state->array_nl_len = len;
    }
    tmp = rb_hash_aref(opts, ID2SYM(i_object_nl));
    if (RTEST(tmp)) {
        unsigned long len;
        Check_Type(tmp, T_STRING);
        len = RSTRING_LEN(tmp);
        state->object_nl = fstrndup(RSTRING_PTR(tmp), len + 1);
        state->object_nl_len = len;
    }
    tmp = ID2SYM(i_max_nesting);
    state->max_nesting = 100;
    if (option_given_p(opts, tmp)) {
        VALUE max_nesting = rb_hash_aref(opts, tmp);
        if (RTEST(max_nesting)) {
            Check_Type(max_nesting, T_FIXNUM);
            state->max_nesting = FIX2LONG(max_nesting);
        } else {
            state->max_nesting = 0;
        }
    }
    tmp = ID2SYM(i_depth);
    state->depth = 0;
    if (option_given_p(opts, tmp)) {
        VALUE depth = rb_hash_aref(opts, tmp);
        if (RTEST(depth)) {
            Check_Type(depth, T_FIXNUM);
            state->depth = FIX2LONG(depth);
        } else {
            state->depth = 0;
        }
    }
    tmp = ID2SYM(i_buffer_initial_length);
    if (option_given_p(opts, tmp)) {
        VALUE buffer_initial_length = rb_hash_aref(opts, tmp);
        if (RTEST(buffer_initial_length)) {
            long initial_length;
            Check_Type(buffer_initial_length, T_FIXNUM);
            initial_length = FIX2LONG(buffer_initial_length);
            if (initial_length > 0) state->buffer_initial_length = initial_length;
        }
    }
    tmp = rb_hash_aref(opts, ID2SYM(i_allow_nan));
    state->allow_nan = RTEST(tmp);
    tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
    state->ascii_only = RTEST(tmp);
    tmp = rb_hash_aref(opts, ID2SYM(i_quirks_mode));
    state->quirks_mode = RTEST(tmp);
    return self;
}
Esempio n. 17
0
File: class.c Progetto: fi8on/ruby
int
rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
{
    int i;
    const char *p = fmt;
    VALUE *var;
    va_list vargs;
    int f_var = 0, f_hash = 0, f_block = 0;
    int n_lead = 0, n_opt = 0, n_trail = 0, n_mand;
    int argi = 0;
    VALUE hash = Qnil;

    if (ISDIGIT(*p)) {
	n_lead = *p - '0';
	p++;
	if (ISDIGIT(*p)) {
	    n_opt = *p - '0';
	    p++;
	    if (ISDIGIT(*p)) {
		n_trail = *p - '0';
		p++;
		goto block_arg;
	    }
	}
    }
    if (*p == '*') {
	f_var = 1;
	p++;
	if (ISDIGIT(*p)) {
	    n_trail = *p - '0';
	    p++;
	}
    }
  block_arg:
    if (*p == ':') {
	f_hash = 1;
	p++;
    }
    if (*p == '&') {
	f_block = 1;
	p++;
    }
    if (*p != '\0') {
	rb_fatal("bad scan arg format: %s", fmt);
    }
    n_mand = n_lead + n_trail;

    if (argc < n_mand)
	goto argc_error;

    va_start(vargs, fmt);

    /* capture an option hash - phase 1: pop */
    if (f_hash && n_mand < argc) {
	VALUE last = argv[argc - 1];

	if (NIL_P(last)) {
	    /* nil is taken as an empty option hash only if it is not
	       ambiguous; i.e. '*' is not specified and arguments are
	       given more than sufficient */
	    if (!f_var && n_mand + n_opt < argc)
		argc--;
	}
	else {
	    hash = rb_check_convert_type(last, T_HASH, "Hash", "to_hash");
	    if (!NIL_P(hash))
		argc--;
	}
    }
    /* capture leading mandatory arguments */
    for (i = n_lead; i-- > 0; ) {
	var = va_arg(vargs, VALUE *);
	if (var) *var = argv[argi];
	argi++;
    }
    /* capture optional arguments */
    for (i = n_opt; i-- > 0; ) {
	var = va_arg(vargs, VALUE *);
	if (argi < argc - n_trail) {
	    if (var) *var = argv[argi];
	    argi++;
	}
	else {
	    if (var) *var = Qnil;
	}
    }
    /* capture variable length arguments */
    if (f_var) {
	int n_var = argc - argi - n_trail;

	var = va_arg(vargs, VALUE *);
	if (0 < n_var) {
	    if (var) *var = rb_ary_new4(n_var, &argv[argi]);
	    argi += n_var;
	}
	else {
	    if (var) *var = rb_ary_new();
	}
    }
    /* capture trailing mandatory arguments */
    for (i = n_trail; i-- > 0; ) {
	var = va_arg(vargs, VALUE *);
	if (var) *var = argv[argi];
	argi++;
    }
    /* capture an option hash - phase 2: assignment */
    if (f_hash) {
	var = va_arg(vargs, VALUE *);
	if (var) *var = hash;
    }
    /* capture iterator block */
    if (f_block) {
	var = va_arg(vargs, VALUE *);
	if (rb_block_given_p()) {
	    *var = rb_block_proc();
	}
	else {
	    *var = Qnil;
	}
    }
    va_end(vargs);

    if (argi < argc)
	goto argc_error;

    return argc;

  argc_error:
    if (0 < n_opt)
	rb_raise(rb_eArgError, "wrong number of arguments (%d for %d..%d%s)",
		 argc, n_mand, n_mand + n_opt, f_var ? "+" : "");
    else
	rb_raise(rb_eArgError, "wrong number of arguments (%d for %d%s)",
		 argc, n_mand, f_var ? "+" : "");
}
Esempio n. 18
0
/*
 *  call-seq:
 *     Dir.new( string ) -> aDir
 *
 *  Returns a new directory object for the named directory.
 */
static VALUE
dir_initialize(int argc, VALUE *argv, VALUE dir)
{
    struct dir_data *dp;
    static rb_encoding *fs_encoding;
    rb_encoding  *intencoding, *extencoding;
    VALUE dirname, opt;
    static VALUE sym_intenc, sym_extenc;

    if (!sym_intenc) {
	sym_intenc = ID2SYM(rb_intern("internal_encoding"));
	sym_extenc = ID2SYM(rb_intern("external_encoding"));
	fs_encoding = rb_filesystem_encoding();
    }

    intencoding = NULL;
    extencoding = fs_encoding;
    rb_scan_args(argc, argv, "11", &dirname, &opt);

    if (!NIL_P(opt)) {
        VALUE v, extenc=Qnil, intenc=Qnil;
        opt = rb_check_convert_type(opt, T_HASH, "Hash", "to_hash");

        v = rb_hash_aref(opt, sym_intenc);
        if (!NIL_P(v)) intenc = v;
        v = rb_hash_aref(opt, sym_extenc);
        if (!NIL_P(v)) extenc = v;

	if (!NIL_P(extenc)) {
	    extencoding = rb_to_encoding(extenc);
	    if (!NIL_P(intenc)) {
		intencoding = rb_to_encoding(intenc);
		if (extencoding == intencoding) {
		    rb_warn("Ignoring internal encoding '%s': it is identical to external encoding '%s'",
			    RSTRING_PTR(rb_inspect(intenc)),
			    RSTRING_PTR(rb_inspect(extenc)));
		    intencoding = NULL;
		}
	    }
	}
	else if (!NIL_P(intenc)) {
	    rb_raise(rb_eArgError, "External encoding must be specified when internal encoding is given");
	}
    }

    {
	rb_encoding  *dirname_encoding = rb_enc_get(dirname);
	if (rb_usascii_encoding() != dirname_encoding
	    && rb_ascii8bit_encoding() != dirname_encoding
#if defined __APPLE__
	    && rb_utf8_encoding() != dirname_encoding
#endif
	    && extencoding != dirname_encoding) {
	    if (!intencoding) intencoding = dirname_encoding;
	    dirname = rb_str_transcode(dirname, rb_enc_from_encoding(extencoding));
	}
    }
    FilePathValue(dirname);

    Data_Get_Struct(dir, struct dir_data, dp);
    if (dp->dir) closedir(dp->dir);
    if (dp->path) xfree(dp->path);
    dp->dir = NULL;
    dp->path = NULL;
    dp->intenc = intencoding;
    dp->extenc = extencoding;
    dp->dir = opendir(RSTRING_PTR(dirname));
    if (dp->dir == NULL) {
	if (errno == EMFILE || errno == ENFILE) {
	    rb_gc();
	    dp->dir = opendir(RSTRING_PTR(dirname));
	}
	if (dp->dir == NULL) {
	    rb_sys_fail(RSTRING_PTR(dirname));
	}
    }
    dp->path = strdup(RSTRING_PTR(dirname));

    return dir;
}
Esempio n. 19
0
static VALUE so_check_convert_type(VALUE self, VALUE obj) {
  return rb_check_convert_type(obj, T_ARRAY, "Array", "to_ary");
}
Esempio n. 20
0
static VALUE
rhash_try_convert(VALUE dummy, SEL sel, VALUE hash)
{
    return rb_check_convert_type(hash, T_HASH, "Hash", "to_hash");
}
Esempio n. 21
0
static VALUE
rb_io_check_io(VALUE io)
{
    return rb_check_convert_type(io, T_FILE, "IO", "to_io");
}
Esempio n. 22
0
static inline int
caller_setup_args(const rb_thread_t *th, rb_control_frame_t *cfp, VALUE flag,
		  int argc, rb_iseq_t *blockiseq, rb_block_t **block)
{
    rb_block_t *blockptr = 0;

    if (block) {
	if (flag & VM_CALL_ARGS_BLOCKARG_BIT) {
	    rb_proc_t *po;
	    VALUE proc;

	    proc = *(--cfp->sp);

	    if (proc != Qnil) {
		if (!rb_obj_is_proc(proc)) {
		    VALUE b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
		    if (NIL_P(b) || !rb_obj_is_proc(b)) {
			rb_raise(rb_eTypeError,
				 "wrong argument type %s (expected Proc)",
				 rb_obj_classname(proc));
		    }
		    proc = b;
		}
		GetProcPtr(proc, po);
		blockptr = &po->block;
		RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp)->proc = proc;
		*block = blockptr;
	    }
	}
	else if (blockiseq) {
	    blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
	    blockptr->iseq = blockiseq;
	    blockptr->proc = 0;
	    *block = blockptr;
	}
    }

    /* expand top of stack? */
    if (flag & VM_CALL_ARGS_SPLAT_BIT) {
	VALUE ary = *(cfp->sp - 1);
	VALUE *ptr;
	int i;
	VALUE tmp = rb_check_convert_type(ary, T_ARRAY, "Array", "to_a");

	if (NIL_P(tmp)) {
	    /* do nothing */
	}
	else {
	    long len = RARRAY_LEN(tmp);
	    ptr = RARRAY_PTR(tmp);
	    cfp->sp -= 1;

	    CHECK_STACK_OVERFLOW(cfp, len);

	    for (i = 0; i < len; i++) {
		*cfp->sp++ = ptr[i];
	    }
	    argc += i-1;
	}
    }

    return argc;
}
Esempio n. 23
0
/* @overload gsub(pattern, replacement)
 *
 *   Returns the receiver with all matches of PATTERN replaced by REPLACEMENT,
 *   inheriting any taint and untrust from the receiver and from REPLACEMENT.
 *
 *   The REPLACEMENT is used as a specification for what to replace matches
 *   with:
 *
 *   <table>
 *     <thead>
 *       <tr><th>Specification</th><th>Replacement</th></tr>
 *     </thead>
 *     <tbody>
 *       <tr>
 *         <td><code>\1</code>, <code>\2</code>, …, <code>\</code><em>n</em></td>
 *         <td>Numbered sub-match <em>n</em></td>
 *       </tr>
 *       <tr>
 *         <td><code>\k&lt;</code><em>name</em><code>></code></td>
 *         <td>Named sub-match <em>name</em></td>
 *       </tr>
 *     </tbody>
 *   </table>
 *
 *   The Regexp special variables `$&`, `$'`, <code>$\`</code>, `$1`, `$2`, …,
 *   `$`_n_ are updated accordingly.
 *
 *   @param [Regexp, #to_str] pattern
 *   @param [#to_str] replacement
 *   @return [U::String]
 *
 * @overload gsub(pattern, replacements)
 *
 *   Returns the receiver with all matches of PATTERN replaced by
 *   REPLACEMENTS#[_match_], where _match_ is the matched substring, inheriting
 *   any taint and untrust from the receiver and from the
 *   REPLACEMENTS#[_match_]es, as well as any taint on REPLACEMENTS.
 *
 *   The Regexp special variables `$&`, `$'`, <code>$\`</code>, `$1`, `$2`, …,
 *   `$`_n_ are updated accordingly.
 *
 *   @param [Regexp, #to_str] pattern
 *   @param [#to_hash] replacements
 *   @raise [RuntimeError] If any replacement is the result being constructed
 *   @raise [Exception] Any error raised by REPLACEMENTS#default, if it gets
 *     called
 *   @return [U::String]
 *
 * @overload gsub(pattern){ |match| … }
 *
 *   Returns the receiver with all matches of PATTERN replaced by the results
 *   of the given block, inheriting any taint and untrust from the receiver and
 *   from the results of the given block.
 *
 *   The Regexp special variables `$&`, `$'`, <code>$\`</code>, `$1`, `$2`, …,
 *   `$`_n_ are updated accordingly.
 *
 *   @param [Regexp, #to_str] pattern
 *   @yieldparam [U::String] match
 *   @yieldreturn [#to_str]
 *   @return [U::String]
 *
 * @overload gsub(pattern)
 *
 *   Returns an Enumerator over the matches of PATTERN in the receiver.
 *
 *   The Regexp special variables `$&`, `$'`, <code>$\`</code>, `$1`, `$2`, …,
 *   `$`_n_ will be updated accordingly.
 *
 *   @param [Regexp, #to_str] pattern
 *   @return [Enumerator] */
VALUE
rb_u_string_gsub(int argc, VALUE *argv, VALUE self)
{
        VALUE pattern, replacement;
        VALUE replacements = Qnil;
        bool use_block = false;
        bool tainted = false;

        if (argc == 1) {
                RETURN_ENUMERATOR(self, argc, argv);
                use_block = true;
        }

        if (rb_scan_args(argc, argv, "11", &pattern, &replacement) == 2) {
                replacements = rb_check_convert_type(replacement, T_HASH,
                                                     "Hash", "to_hash");
                if (NIL_P(replacements))
                        StringValue(replacement);
                if (OBJ_TAINTED(replacement))
                        tainted = true;
        }

        pattern = rb_u_pattern_argument(pattern, true);

        VALUE str = rb_str_to_str(self);
        long begin = rb_reg_search(pattern, str, 0, 0);
        if (begin < 0)
                return self;

        const char *base = RSTRING_PTR(str);
        const char *p = base;
        const char *end = RSTRING_END(str);
        VALUE substituted = rb_u_str_buf_new(RSTRING_LEN(str) + 30);
        do {
                VALUE match = rb_backref_get();
                struct re_registers *registers = RMATCH_REGS(match);
                VALUE result;

                if (use_block || !NIL_P(replacements)) {
                        if (use_block) {
                                VALUE ustr = rb_u_string_new_rb(rb_reg_nth_match(0, match));
                                result = rb_u_string_object_as_string(rb_yield(ustr));
                        } else {
                                VALUE ustr = rb_u_string_new_c(self,
                                                               base + registers->beg[0],
                                                               registers->end[0] - registers->beg[0]);
                                result = rb_u_string_object_as_string(rb_hash_aref(replacements, ustr));
                        }

                        if (result == substituted)
                                rb_u_raise(rb_eRuntimeError,
                                           "result of block is string being built; please try not to cheat");
                } else
                        result =
#ifdef HAVE_RB_REG_REGSUB4
                        rb_reg_regsub(replacement, str, registers, pattern);
#else
                        rb_reg_regsub(replacement, str, registers);
#endif

                if (OBJ_TAINTED(result))
                        tainted = true;

                const struct rb_u_string *value = RVAL2USTRING_ANY(result);

                rb_str_buf_cat(substituted, p, registers->beg[0] - (p - base));
                rb_str_buf_cat(substituted, USTRING_STR(value), USTRING_LENGTH(value));
                OBJ_INFECT(substituted, result);

                p = base + registers->end[0];
                if (registers->beg[0] == registers->end[0])
                        p = u_next(p);
                if (p >= end)
                        break;

                begin = rb_reg_search(pattern, str, registers->end[0], 0);
        } while (begin >= 0);

        if (p < end)
                rb_str_buf_cat(substituted, p, end - p);

        rb_reg_search(pattern, str, end - p, 0);

        RBASIC(substituted)->klass = rb_obj_class(str);
        OBJ_INFECT(substituted, str);
        if (tainted)
                OBJ_TAINT(substituted);

        return rb_u_string_new_rb(substituted);
}
Esempio n. 24
0
static int
str_transcode(int argc, VALUE *argv, VALUE *self)
{
    VALUE dest;
    VALUE str = *self;
    long blen, slen;
    unsigned char *buf, *bp, *sp, *fromp;
    rb_encoding *from_enc, *to_enc;
    const char *from_e, *to_e;
    int from_encidx, to_encidx;
    VALUE from_encval, to_encval;
    const rb_transcoder *my_transcoder;
    rb_transcoding my_transcoding;
    int final_encoding = 0;
    VALUE opt;
    int options = 0;

    opt = rb_check_convert_type(argv[argc-1], T_HASH, "Hash", "to_hash");
    if (!NIL_P(opt)) {
	VALUE v;

	argc--;
	v = rb_hash_aref(opt, sym_invalid);
	if (NIL_P(v)) {
	    rb_raise(rb_eArgError, "unknown value for invalid: setting");
	}
	else if (v==sym_ignore) {
	    options |= INVALID_IGNORE;
	}
    }
    if (argc < 1 || argc > 2) {
	rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..2)", argc);
    }
    if ((to_encidx = rb_to_encoding_index(to_encval = argv[0])) < 0) {
	to_enc = 0;
	to_encidx = 0;
	to_e = StringValueCStr(to_encval);
    }
    else {
	to_enc = rb_enc_from_index(to_encidx);
	to_e = rb_enc_name(to_enc);
    }
    if (argc==1) {
	from_encidx = rb_enc_get_index(str);
	from_enc = rb_enc_from_index(from_encidx);
	from_e = rb_enc_name(from_enc);
    }
    else if ((from_encidx = rb_to_encoding_index(from_encval = argv[1])) < 0) {
	from_enc = 0;
	from_e = StringValueCStr(from_encval);
    }
    else {
	from_enc = rb_enc_from_index(from_encidx);
	from_e = rb_enc_name(from_enc);
    }

    if (from_enc && from_enc == to_enc) {
	return -1;
    }
    if (from_enc && to_enc && rb_enc_asciicompat(from_enc) && rb_enc_asciicompat(to_enc)) {
	if (ENC_CODERANGE(str) == ENC_CODERANGE_7BIT) {
	    return to_encidx;
	}
    }
    if (encoding_equal(from_e, to_e)) {
	return -1;
    }

    do { /* loop for multistep transcoding */
	/* later, maybe use smaller intermediate strings for very long strings */
	if (!(my_transcoder = transcode_dispatch(from_e, to_e))) {
	    rb_raise(rb_eArgError, "transcoding not supported (from %s to %s)", from_e, to_e);
	}

	my_transcoding.transcoder = my_transcoder;

	if (my_transcoder->preprocessor) {
	    fromp = sp = (unsigned char *)RSTRING_PTR(str);
	    slen = RSTRING_LEN(str);
	    blen = slen + 30; /* len + margin */
	    dest = rb_str_tmp_new(blen);
	    bp = (unsigned char *)RSTRING_PTR(dest);
	    my_transcoding.ruby_string_dest = dest;
	    (*my_transcoder->preprocessor)(&fromp, &bp, (sp+slen), (bp+blen), &my_transcoding);
	    if (fromp != sp+slen) {
		rb_raise(rb_eArgError, "not fully converted, %td bytes left", sp+slen-fromp);
	    }
	    buf = (unsigned char *)RSTRING_PTR(dest);
	    *bp = '\0';
	    rb_str_set_len(dest, bp - buf);
	    str = dest;
	}
	fromp = sp = (unsigned char *)RSTRING_PTR(str);
	slen = RSTRING_LEN(str);
	blen = slen + 30; /* len + margin */
	dest = rb_str_tmp_new(blen);
	bp = (unsigned char *)RSTRING_PTR(dest);
	my_transcoding.ruby_string_dest = dest;
	my_transcoding.flush_func = str_transcoding_resize;

	transcode_loop(&fromp, &bp, (sp+slen), (bp+blen), my_transcoder, &my_transcoding, options);
	if (fromp != sp+slen) {
	    rb_raise(rb_eArgError, "not fully converted, %td bytes left", sp+slen-fromp);
	}
	buf = (unsigned char *)RSTRING_PTR(dest);
	*bp = '\0';
	rb_str_set_len(dest, bp - buf);
	if (my_transcoder->postprocessor) {
	    str = dest;
	    fromp = sp = (unsigned char *)RSTRING_PTR(str);
	    slen = RSTRING_LEN(str);
	    blen = slen + 30; /* len + margin */
	    dest = rb_str_tmp_new(blen);
	    bp = (unsigned char *)RSTRING_PTR(dest);
	    my_transcoding.ruby_string_dest = dest;
	    (*my_transcoder->postprocessor)(&fromp, &bp, (sp+slen), (bp+blen), &my_transcoding);
	    if (fromp != sp+slen) {
		rb_raise(rb_eArgError, "not fully converted, %td bytes left", sp+slen-fromp);
	    }
	    buf = (unsigned char *)RSTRING_PTR(dest);
	    *bp = '\0';
	    rb_str_set_len(dest, bp - buf);
	}

	if (encoding_equal(my_transcoder->to_encoding, to_e)) {
	    final_encoding = 1;
	}
	else {
	    from_e = my_transcoder->to_encoding;
	    str = dest;
	}
    } while (!final_encoding);
    /* set encoding */
    if (!to_enc) {
	to_encidx = rb_define_dummy_encoding(to_e);
    }
    *self = dest;

    return to_encidx;
}