VALUE
rb_str_inspect(VALUE str)
{
rb_encoding *enc = STR_ENC_GET(str);
char *p, *pend;
VALUE result = rb_str_buf_new(0);
if (!rb_enc_asciicompat(enc)) enc = rb_usascii_encoding();
rb_enc_associate(result, enc);
str_cat_char(result, '"', enc);
p = RSTRING_PTR(str); pend = RSTRING_END(str);
while (p < pend) {
unsigned int c, cc;
int n;
n = rb_enc_precise_mbclen(p, pend, enc);
if (!MBCLEN_CHARFOUND_P(n)) {
p++;
n = 1;
goto escape_codepoint;
}
n = MBCLEN_CHARFOUND_LEN(n);
c = rb_enc_codepoint(p, pend, enc);
n = rb_enc_codelen(c, enc);
p += n;
if (c == '"'|| c == '\\' ||
(c == '#' &&
p < pend &&
MBCLEN_CHARFOUND_P(rb_enc_precise_mbclen(p,pend,enc)) &&
(cc = rb_enc_codepoint(p,pend,enc),
(cc == '$' || cc == '@' || cc == '{')))) {
prefix_escape(result, c, enc);
}
else if (c == '\n') {
prefix_escape(result, 'n', enc);
}
else if (c == '\r') {
prefix_escape(result, 'r', enc);
}
else if (c == '\t') {
prefix_escape(result, 't', enc);
}
else if (c == '\f') {
prefix_escape(result, 'f', enc);
}
else if (c == '\013') {
prefix_escape(result, 'v', enc);
}
else if (c == '\010') {
prefix_escape(result, 'b', enc);
}
else if (c == '\007') {
prefix_escape(result, 'a', enc);
}
else if (c == 033) {
prefix_escape(result, 'e', enc);
}
else if (rb_enc_isprint(c, enc)) {
rb_enc_str_buf_cat(result, p-n, n, enc);
}
else {
char buf[5];
char *s;
char *q;
escape_codepoint:
for (q = p-n; q < p; q++) {
s = buf;
sprintf(buf, "\\x%02X", *q & 0377);
while (*s) {
str_cat_char(result, *s++, enc);
}
}
}
}
str_cat_char(result, '"', enc);
OBJ_INFECT(result, str);
return result;
}