/*
 * call-seq:
 *   strio.ungetc(integer)   -> nil
 *
 * Pushes back one character (passed as a parameter) onto *strio*
 * such that a subsequent buffered read will return it.  Pushing back 
 * behind the beginning of the buffer string is not possible.  Nothing
 * will be done if such an attempt is made.
 * In other case, there is no limitation for multiple pushbacks.
 */
static VALUE
strio_ungetc(self, ch)
    VALUE self, ch;
{
    struct StringIO *ptr = readable(StringIO(self));
    int cc = NUM2INT(ch);
    long len, pos = ptr->pos;

    if (cc != EOF) {
        len = RSTRING(ptr->string)->len;
        if (pos == 0) {
            char *p;
            rb_str_resize(ptr->string, len + 1);
            p = RSTRING(ptr->string)->ptr;
            memmove(p + 1, p, len);
        }
        else {
            if (len < pos-- ||
                (unsigned char)RSTRING(ptr->string)->ptr[pos] !=
                (unsigned char)cc) {
                strio_extend(ptr, pos, 1);
            }
            --ptr->pos;
        }
        RSTRING(ptr->string)->ptr[pos] = cc;
        OBJ_INFECT(ptr->string, self);
        ptr->flags &= ~STRIO_EOF;
    }
    return Qnil;
}