ungetc(p1)
public
Pushes back one character (passed as a parameter) onto strio such
that a subsequent buffered read will
return it. There is no limitation for multiple pushbacks including pushing
back behind the beginning of the buffer string.
Show source
static VALUE
strio_ungetc(VALUE self, VALUE c)
{
struct StringIO *ptr = readable(StringIO(self));
long lpos, clen;
char *p, *pend;
rb_encoding *enc, *enc2;
if (NIL_P(c)) return Qnil;
if (FIXNUM_P(c)) {
int cc = FIX2INT(c);
char buf[16];
enc = rb_enc_get(ptr->string);
rb_enc_mbcput(cc, buf, enc);
c = rb_enc_str_new(buf, rb_enc_codelen(cc, enc), enc);
}
else {
SafeStringValue(c);
enc = rb_enc_get(ptr->string);
enc2 = rb_enc_get(c);
if (enc != enc2 && enc != rb_ascii8bit_encoding()) {
c = rb_str_conv_enc(c, enc2, enc);
}
}
if (RSTRING_LEN(ptr->string) < ptr->pos) {
long len = RSTRING_LEN(ptr->string);
rb_str_resize(ptr->string, ptr->pos - 1);
memset(RSTRING_PTR(ptr->string) + len, 0, ptr->pos - len - 1);
rb_str_concat(ptr->string, c);
ptr->pos--;
}
else {
/* get logical position */
lpos = 0; p = RSTRING_PTR(ptr->string); pend = p + ptr->pos;
for (;;) {
clen = rb_enc_mbclen(p, pend, enc);
if (p+clen >= pend) break;
p += clen;
lpos++;
}
clen = p - RSTRING_PTR(ptr->string);
rb_str_update(ptr->string, lpos, ptr->pos ? 1 : 0, c);
ptr->pos = clen;
}
return Qnil;
}