Example #1
0
/* @overload rindex(pattern, offset = -1)
 *
 *   Returns the maximal index of the receiver where PATTERN matches, equal to
 *   or less than _i_, where _i_ = OFFSET if OFFSET ≥ 0, _i_ = {#length} -
 *   abs(OFFSET) otherwise, or nil if there is no match.
 *
 *   If PATTERN is a Regexp, the Regexp special variables `$&`, `$'`,
 *   <code>$\`</code>, `$1`, `$2`, …, `$`_n_ are updated accordingly.
 *
 *   If PATTERN responds to `#to_str`, the matching is performed by a byte
 *   comparison.
 *
 *   @param [Regexp, #to_str] pattern
 *   @param [#to_int] offset
 *   @return [Integer, nil]
 *   @see #index */
VALUE
rb_u_string_rindex_m(int argc, VALUE *argv, VALUE self)
{
        const struct rb_u_string *string = RVAL2USTRING(self);

        VALUE sub, rboffset;
        long offset;
        if (rb_scan_args(argc, argv, "11", &sub, &rboffset) == 2)
                offset = NUM2LONG(rboffset);
        else
                /* TODO: Why not simply use -1?  Benchmark which is faster. */
                offset = u_n_chars_n(USTRING_STR(string), USTRING_LENGTH(string));

        const char *begin = rb_u_string_begin_from_offset(string, offset);
        const char *end = USTRING_END(string);
        if (begin == NULL) {
                if (offset <= 0) {
                        if (TYPE(sub) == T_REGEXP)
                                rb_backref_set(Qnil);

                        return Qnil;
                }

                begin = end;
                /* TODO: this converting back and forward can be optimized away
                 * if rb_u_string_index_regexp() and rb_u_string_rindex() were split up
                 * into two additional functions, adding
                 * rb_u_string_index_regexp_pointer() and rb_u_string_rindex_pointer(),
                 * so that one can pass a pointer to start at immediately
                 * instead of an offset that gets calculated into a pointer. */
                offset = u_n_chars_n(USTRING_STR(string), USTRING_LENGTH(string));
        }

        switch (TYPE(sub)) {
        case T_REGEXP:
                /* TODO: What’s this first test for, exactly? */
                if (RREGEXP(sub)->ptr == NULL || RREGEXP_SRC_LEN(sub) > 0)
                        offset = rb_u_string_index_regexp(self, begin, sub, true);
                break;
        default: {
                VALUE tmp = rb_check_string_type(sub);
                if (NIL_P(tmp))
                        rb_u_raise(rb_eTypeError, "type mismatch: %s given",
                                   rb_obj_classname(sub));

                sub = tmp;
        }
                /* fall through */
        case T_STRING:
                offset = rb_u_string_rindex(self, sub, offset);
                break;
        }

        if (offset < 0)
                return Qnil;

        return LONG2NUM(offset);
}
Example #2
0
/*
 * call-seq:
 *    str.to_c  ->  complex
 *
 * Returns a complex which denotes the string form.  The parser
 * ignores leading whitespaces and trailing garbage.  Any digit
 * sequences can be separated by an underscore.  Returns zero for null
 * or garbage string.
 *
 * For example:
 *
 *    '9'.to_c           #=> (9+0i)
 *    '2.5'.to_c         #=> (2.5+0i)
 *    '2.5/1'.to_c       #=> ((5/2)+0i)
 *    '-3/2'.to_c        #=> ((-3/2)+0i)
 *    '-i'.to_c          #=> (0-1i)
 *    '45i'.to_c         #=> (0+45i)
 *    '3-4i'.to_c        #=> (3-4i)
 *    '-4e2-4e-2i'.to_c  #=> (-400.0-0.04i)
 *    '-0.0-0.0i'.to_c   #=> (-0.0-0.0i)
 *    '1/2+3/4i'.to_c    #=> ((1/2)+(3/4)*i)
 *    'ruby'.to_c        #=> (0+0i)
 */
static VALUE
string_to_c(VALUE self)
{
    VALUE s, a, backref;

    backref = rb_backref_get();
    rb_match_busy(backref);

    s = f_gsub(self, underscores_pat, an_underscore);
    a = string_to_c_internal(s);

    rb_backref_set(backref);

    if (!NIL_P(RARRAY_PTR(a)[0]))
	return RARRAY_PTR(a)[0];
    return rb_complex_new1(INT2FIX(0));
}
Example #3
0
/* @overload index(pattern, offset = 0)
 *
 *   Returns the minimal index of the receiver where PATTERN matches, equal to or
 *   greater than _i_, where _i_ = OFFSET if OFFSET ≥ 0, _i_ = {#length} -
 *   abs(OFFSET) otherwise, or nil if there is no match.
 *
 *   If PATTERN is a Regexp, the Regexp special variables `$&`, `$'`,
 *   <code>$\`</code>, `$1`, `$2`, …, `$`_n_ are updated accordingly.
 *
 *   If PATTERN responds to #to_str, the matching is performed by byte
 *   comparison.
 *
 *   @param [Regexp, #to_str] pattern
 *   @param [#to_int] offset
 *   @return [Integer, nil]
 *   @see #rindex */
VALUE
rb_u_string_index_m(int argc, VALUE *argv, VALUE self)
{
        VALUE sub, rboffset;
        long offset = 0;
        if (rb_scan_args(argc, argv, "11", &sub, &rboffset) == 2)
                offset = NUM2LONG(rboffset);

        const struct rb_u_string *string = RVAL2USTRING(self);

        const char *begin = rb_u_string_begin_from_offset(string, offset);
        if (begin == NULL) {
                if (TYPE(sub) == T_REGEXP)
                        rb_backref_set(Qnil);

                return Qnil;
        }

        switch (TYPE(sub)) {
        case T_REGEXP:
                offset = rb_u_string_index_regexp(self, begin, sub, false);
                break;
        default: {
                VALUE tmp = rb_check_string_type(sub);
                if (NIL_P(tmp))
                        rb_u_raise(rb_eTypeError, "type mismatch: %s given",
                                   rb_obj_classname(sub));

                sub = tmp;
        }
                /* fall through */
        case T_STRING:
                offset = rb_u_string_index(self, sub, offset);
                break;
        }

        if (offset < 0)
                return Qnil;

        return LONG2NUM(offset);
}
Example #4
0
static VALUE
nucomp_s_convert(int argc, VALUE *argv, VALUE klass)
{
    VALUE a1, a2, backref;

    rb_scan_args(argc, argv, "11", &a1, &a2);

    if (NIL_P(a1) || (argc == 2 && NIL_P(a2)))
	rb_raise(rb_eTypeError, "can't convert nil into Complex");

    backref = rb_backref_get();
    rb_match_busy(backref);

    if (RB_TYPE_P(a1, T_STRING)) {
	a1 = string_to_c_strict(a1);
    }

    if (RB_TYPE_P(a2, T_STRING)) {
	a2 = string_to_c_strict(a2);
    }

    rb_backref_set(backref);

    if (RB_TYPE_P(a1, T_COMPLEX)) {
	{
	    get_dat1(a1);

	    if (k_exact_zero_p(dat->imag))
		a1 = dat->real;
	}
    }

    if (RB_TYPE_P(a2, T_COMPLEX)) {
	{
	    get_dat1(a2);

	    if (k_exact_zero_p(dat->imag))
		a2 = dat->real;
	}
    }

    if (RB_TYPE_P(a1, T_COMPLEX)) {
	if (argc == 1 || (k_exact_zero_p(a2)))
	    return a1;
    }

    if (argc == 1) {
	if (k_numeric_p(a1) && !f_real_p(a1))
	    return a1;
	/* should raise exception for consistency */
	if (!k_numeric_p(a1))
	    return rb_convert_type(a1, T_COMPLEX, "Complex", "to_c");
    }
    else {
	if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
	    (!f_real_p(a1) || !f_real_p(a2)))
	    return f_add(a1,
			 f_mul(a2,
			       f_complex_new_bang2(rb_cComplex, ZERO, ONE)));
    }

    {
	VALUE argv2[2];
	argv2[0] = a1;
	argv2[1] = a2;
	return nucomp_s_new(argc, argv2, klass);
    }
}
Example #5
0
static VALUE
nurat_s_convert(VALUE klass, SEL sel, int argc, VALUE *argv)
{
    VALUE a1, a2, backref;

    rb_scan_args(argc, argv, "11", &a1, &a2);

    if (NIL_P(a1) || (argc == 2 && NIL_P(a2)))
	rb_raise(rb_eTypeError, "can't convert nil into Rational");

    switch (TYPE(a1)) {
      case T_COMPLEX:
	if (k_exact_zero_p(RCOMPLEX(a1)->imag))
	    a1 = RCOMPLEX(a1)->real;
    }

    switch (TYPE(a2)) {
      case T_COMPLEX:
	if (k_exact_zero_p(RCOMPLEX(a2)->imag))
	    a2 = RCOMPLEX(a2)->real;
    }

    backref = rb_backref_get();
    rb_match_busy(backref);

    switch (TYPE(a1)) {
      case T_FIXNUM:
      case T_BIGNUM:
	break;
      case T_FLOAT:
	a1 = f_to_r(a1);
	break;
      case T_STRING:
	a1 = string_to_r_strict(a1);
	break;
    }

    switch (TYPE(a2)) {
      case T_FIXNUM:
      case T_BIGNUM:
	break;
      case T_FLOAT:
	a2 = f_to_r(a2);
	break;
      case T_STRING:
	a2 = string_to_r_strict(a2);
	break;
    }

    rb_backref_set(backref);

    switch (TYPE(a1)) {
      case T_RATIONAL:
	if (argc == 1 || (k_exact_one_p(a2)))
	    return a1;
    }

    if (argc == 1) {
	if (!(k_numeric_p(a1) && k_integer_p(a1)))
	    return rb_convert_type(a1, T_RATIONAL, "Rational", "to_r");
    }
    else {
	if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
	    (!f_integer_p(a1) || !f_integer_p(a2)))
	    return f_div(a1, a2);
    }

    {
	VALUE argv2[2];
	argv2[0] = a1;
	argv2[1] = a2;
	return nurat_s_new(argc, argv2, klass);
    }
}
Example #6
0
static VALUE
nurat_s_convert(int argc, VALUE *argv, VALUE klass)
{
    VALUE a1, a2, backref;

    rb_scan_args(argc, argv, "11", &a1, &a2);

    switch (TYPE(a1)) {
      case T_COMPLEX:
	if (k_exact_p(RCOMPLEX(a1)->imag) && f_zero_p(RCOMPLEX(a1)->imag))
	    a1 = RCOMPLEX(a1)->real;
    }

    switch (TYPE(a2)) {
      case T_COMPLEX:
	if (k_exact_p(RCOMPLEX(a2)->imag) && f_zero_p(RCOMPLEX(a2)->imag))
	    a2 = RCOMPLEX(a2)->real;
    }

    backref = rb_backref_get();
    rb_match_busy(backref);

    switch (TYPE(a1)) {
      case T_FIXNUM:
      case T_BIGNUM:
	break;
      case T_FLOAT:
	a1 = f_to_r(a1);
	break;
      case T_STRING:
	a1 = string_to_r_strict(a1);
	break;
    }

    switch (TYPE(a2)) {
      case T_FIXNUM:
      case T_BIGNUM:
	break;
      case T_FLOAT:
	a2 = f_to_r(a2);
	break;
      case T_STRING:
	a2 = string_to_r_strict(a2);
	break;
    }

    rb_backref_set(backref);

    switch (TYPE(a1)) {
      case T_RATIONAL:
	if (argc == 1 || (k_exact_p(a2) && f_one_p(a2)))
	    return a1;
    }

    if (argc == 1) {
	if (k_numeric_p(a1) && !f_integer_p(a1))
	    return a1;
    }
    else {
	if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
	    (!f_integer_p(a1) || !f_integer_p(a2)))
	    return f_div(a1, a2);
    }

    {
	VALUE argv2[2];
	argv2[0] = a1;
	argv2[1] = a2;
	return nurat_s_new(argc, argv2, klass);
    }
}
Example #7
0
static VALUE
nucomp_s_convert(int argc, VALUE *argv, VALUE klass)
{
    VALUE a1, a2, backref;

    rb_scan_args(argc, argv, "11", &a1, &a2);

    backref = rb_backref_get();
    rb_match_busy(backref);

    switch (TYPE(a1)) {
      case T_FIXNUM:
      case T_BIGNUM:
      case T_FLOAT:
	break;
      case T_STRING:
	a1 = string_to_c_strict(a1);
	break;
    }

    switch (TYPE(a2)) {
      case T_FIXNUM:
      case T_BIGNUM:
      case T_FLOAT:
	break;
      case T_STRING:
	a2 = string_to_c_strict(a2);
	break;
    }

    rb_backref_set(backref);

    switch (TYPE(a1)) {
      case T_COMPLEX:
	{
	    get_dat1(a1);

	    if (k_exact_p(dat->imag) && f_zero_p(dat->imag))
		a1 = dat->real;
	}
    }

    switch (TYPE(a2)) {
      case T_COMPLEX:
	{
	    get_dat1(a2);

	    if (k_exact_p(dat->imag) && f_zero_p(dat->imag))
		a2 = dat->real;
	}
    }

    switch (TYPE(a1)) {
      case T_COMPLEX:
	if (argc == 1 || (k_exact_p(a2) && f_zero_p(a2)))
	    return a1;
    }

    if (argc == 1) {
	if (k_numeric_p(a1) && !f_real_p(a1))
	    return a1;
    }
    else {
	if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
	    (!f_real_p(a1) || !f_real_p(a2)))
	    return f_add(a1,
			 f_mul(a2,
			       f_complex_new_bang2(rb_cComplex, ZERO, ONE)));
    }

    {
	VALUE argv2[2];
	argv2[0] = a1;
	argv2[1] = a2;
	return nucomp_s_new(argc, argv2, klass);
    }
}