/* * call-seq: * str.index(substring [, offset]) => fixnum or nil * str.index(fixnum [, offset]) => fixnum or nil * str.index(regexp [, offset]) => fixnum or nil * * Returns the index of the first occurrence of the given <i>substring</i>, * character (<i>fixnum</i>), or pattern (<i>regexp</i>) in <i>str</i>. Returns * <code>nil</code> if not found. If the second parameter is present, it * specifies the position in the string to begin the search. * * "hello".index('e') #=> 1 * "hello".index('lo') #=> 3 * "hello".index('a') #=> nil * "hello".index(101) #=> 1 * "hello".index(/[aeiou]/, -3) #=> 4 */ static VALUE rb_str_index_m(argc, argv, str) int argc; VALUE *argv; VALUE str; { VALUE sub; VALUE initpos; long pos; if (rb_scan_args(argc, argv, "11", &sub, &initpos) == 2) { pos = NUM2LONG(initpos); } else { pos = 0; } if (pos < 0) { pos += RSTRING(str)->len; if (pos < 0) { if (TYPE(sub) == T_REGEXP) { rb_backref_set(Qnil); } return Qnil; } } switch (TYPE(sub)) { case T_REGEXP: pos = rb_reg_adjust_startpos(sub, str, pos, 0); pos = rb_reg_search(sub, str, pos, 0); break; case T_FIXNUM: { int c = FIX2INT(sub); long len = RSTRING(str)->len; unsigned char *p = (unsigned char*)RSTRING(str)->ptr; for (;pos<len;pos++) { if (p[pos] == c) return LONG2NUM(pos); } return Qnil; } default: { VALUE tmp; tmp = rb_check_string_type(sub); if (NIL_P(tmp)) { rb_raise(rb_eTypeError, "type mismatch: %s given", rb_obj_classname(sub)); } sub = tmp; } /* fall through */ case T_STRING: pos = rb_str_index(str, sub, pos); break; } if (pos == -1) return Qnil; return LONG2NUM(pos); }