/*
* call-seq:
* mtch.inspect => str
*
* Returns a printable version of <i>mtch</i>.
*
* puts /.$/.match("foo").inspect
* #=> #<MatchData "o">
*
* puts /(.)(.)(.)/.match("foo").inspect
* #=> #<MatchData "foo" 1:"f" 2:"o" 3:"o">
*
* puts /(.)(.)?(.)/.match("fo").inspect
* #=> #<MatchData "fo" 1:"f" 2:nil 3:"o">
*
* puts /(?<foo>.)(?<bar>.)(?<baz>.)/.match("hoge").inspect
* #=> #<MatchData "hog" foo:"h" bar:"o" baz:"g">
*
*/
static VALUE
match_inspect(VALUE match)
{
const char *cname = rb_obj_classname(match);
VALUE str;
int i;
struct re_registers *regs = RMATCH_REGS(match);
int num_regs = regs->num_regs;
struct backref_name_tag *names;
VALUE regexp = RMATCH(match)->regexp;
if (regexp == 0) {
return rb_sprintf("#<%s:%p>", cname, (void*)match);
}
names = ALLOCA_N(struct backref_name_tag, num_regs);
MEMZERO(names, struct backref_name_tag, num_regs);
onig_foreach_name(RREGEXP(regexp)->ptr,
match_inspect_name_iter, names);
str = rb_str_buf_new2("#<");
rb_str_buf_cat2(str, cname);
for (i = 0; i < num_regs; i++) {
VALUE v;
rb_str_buf_cat2(str, " ");
if (0 < i) {
if (names[i].name)
rb_str_buf_cat(str, (const char *)names[i].name, names[i].len);
else {
char buf[sizeof(i)*3+1];
snprintf(buf, sizeof(buf), "%d", i);
rb_str_buf_cat2(str, buf);
}
rb_str_buf_cat2(str, ":");
}
v = rb_reg_nth_match(i, match);
if (v == Qnil)
rb_str_buf_cat2(str, "nil");
else
rb_str_buf_append(str, rb_str_inspect(v));
}
rb_str_buf_cat2(str, ">");
return str;
}