class StringIO

Parent:
Object
Included modules:
Enumerable, IO::generic_readable, IO::generic_writable

Pseudo I/O on String object, with interface corresponding to IO.

Commonly used to simulate $stdio or $stderr

Examples

require 'stringio'

# Writing stream emulation
io = StringIO.new
io.puts "Hello World"
io.string #=> "Hello World\n"

# Reading stream emulation
io = StringIO.new "first\nsecond\nlast\n"
io.getc #=> "f"
io.gets #=> "irst\n"
io.read #=> "second\nlast\n"

Constants

VERSION

Public Class Methods

new(string=""[, mode]) Show source
static VALUE
strio_initialize(int argc, VALUE *argv, VALUE self)
{
    struct StringIO *ptr = check_strio(self);

    if (!ptr) {
        DATA_PTR(self) = ptr = strio_alloc();
    }
    rb_call_super(0, 0);
    return strio_init(argc, argv, ptr, self);
}

Creates new StringIO instance from with string and mode.

open(string=""[, mode]) {|strio| ...} Show source
static VALUE
strio_s_open(int argc, VALUE *argv, VALUE klass)
{
    VALUE obj = rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);
    if (!rb_block_given_p()) return obj;
    return rb_ensure(rb_yield, obj, strio_finalize, obj);
}

Equivalent to StringIO.new except that when it is called with a block, it yields with the new instance and closes it, and returns the result which returned from the block.

Public Instance Methods

binmode → stringio Show source
static VALUE
strio_binmode(VALUE self)
{
    struct StringIO *ptr = StringIO(self);
    rb_encoding *enc = rb_ascii8bit_encoding();

    ptr->enc = enc;
    if (WRITABLE(self)) {
        rb_enc_associate(ptr->string, enc);
    }
    return self;
}

Puts stream into binary mode. See IO#binmode.

close → nil Show source
static VALUE
strio_close(VALUE self)
{
    StringIO(self);
    RBASIC(self)->flags &= ~STRIO_READWRITE;
    return Qnil;
}

Closes a StringIO. The stream is unavailable for any further data operations; an IOError is raised if such an attempt is made.

close_read → nil Show source
static VALUE
strio_close_read(VALUE self)
{
    struct StringIO *ptr = StringIO(self);
    if (!(ptr->flags & FMODE_READABLE)) {
        rb_raise(rb_eIOError, "closing non-duplex IO for reading");
    }
    RBASIC(self)->flags &= ~STRIO_READABLE;
    return Qnil;
}

Closes the read end of a StringIO. Will raise an IOError if the receiver is not readable.

close_write → nil Show source
static VALUE
strio_close_write(VALUE self)
{
    struct StringIO *ptr = StringIO(self);
    if (!(ptr->flags & FMODE_WRITABLE)) {
        rb_raise(rb_eIOError, "closing non-duplex IO for writing");
    }
    RBASIC(self)->flags &= ~STRIO_WRITABLE;
    return Qnil;
}

Closes the write end of a StringIO. Will raise an IOError if the receiver is not writeable.

closed? → true or false Show source
static VALUE
strio_closed(VALUE self)
{
    StringIO(self);
    if (!CLOSED(self)) return Qfalse;
    return Qtrue;
}

Returns true if the stream is completely closed, false otherwise.

closed_read? → true or false Show source
static VALUE
strio_closed_read(VALUE self)
{
    StringIO(self);
    if (READABLE(self)) return Qfalse;
    return Qtrue;
}

Returns true if the stream is not readable, false otherwise.

closed_write? → true or false Show source
static VALUE
strio_closed_write(VALUE self)
{
    StringIO(self);
    if (WRITABLE(self)) return Qfalse;
    return Qtrue;
}

Returns true if the stream is not writable, false otherwise.

each(sep=$/, chomp: false) {|line| block } → strio Show source
each(limit, chomp: false) {|line| block } → strio
each(sep, limit, chomp: false) {|line| block } → strio
each(...) → anEnumerator
static VALUE
strio_each(int argc, VALUE *argv, VALUE self)
{
    VALUE line;
    struct getline_arg arg;

    StringIO(self);
    RETURN_ENUMERATOR(self, argc, argv);

    if (prepare_getline_args(&arg, argc, argv)->limit == 0) {
        rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
    }

    while (!NIL_P(line = strio_getline(&arg, readable(self)))) {
        rb_yield(line);
    }
    return self;
}

See IO#each.

Also aliased as: each_line
each_byte {|byte| block } → strio Show source
each_byte → anEnumerator
static VALUE
strio_each_byte(VALUE self)
{
    struct StringIO *ptr = readable(self);

    RETURN_ENUMERATOR(self, 0, 0);

    while (ptr->pos < RSTRING_LEN(ptr->string)) {
        char c = RSTRING_PTR(ptr->string)[ptr->pos++];
        rb_yield(CHR2FIX(c));
    }
    return self;
}

See IO#each_byte.

each_char {|char| block } → strio Show source
each_char → anEnumerator
static VALUE
strio_each_char(VALUE self)
{
    VALUE c;

    RETURN_ENUMERATOR(self, 0, 0);

    while (!NIL_P(c = strio_getc(self))) {
        rb_yield(c);
    }
    return self;
}

See IO#each_char.

each_codepoint {|c| block } → strio Show source
each_codepoint → anEnumerator
static VALUE
strio_each_codepoint(VALUE self)
{
    struct StringIO *ptr;
    rb_encoding *enc;
    unsigned int c;
    int n;

    RETURN_ENUMERATOR(self, 0, 0);

    ptr = readable(self);
    enc = get_enc(ptr);
    for (;;) {
        if (ptr->pos >= RSTRING_LEN(ptr->string)) {
            return self;
        }

        c = rb_enc_codepoint_len(RSTRING_PTR(ptr->string)+ptr->pos,
                                 RSTRING_END(ptr->string), &n, enc);
        ptr->pos += n;
        rb_yield(UINT2NUM(c));
    }
    return self;
}

See IO#each_codepoint.

See IO#each.

Alias for: each
eof → true or false Show source
static VALUE
strio_eof(VALUE self)
{
    struct StringIO *ptr = readable(self);
    if (ptr->pos < RSTRING_LEN(ptr->string)) return Qfalse;
    return Qtrue;
}

Returns true if the stream is at the end of the data (underlying string). The stream must be opened for reading or an IOError will be raised.

Also aliased as: eof?

Returns true if the stream is at the end of the data (underlying string). The stream must be opened for reading or an IOError will be raised.

Alias for: eof
external_encoding → encoding Show source
static VALUE
strio_external_encoding(VALUE self)
{
    struct StringIO *ptr = StringIO(self);
    return rb_enc_from_encoding(get_enc(ptr));
}

Returns the Encoding object that represents the encoding of the file. If the stream is write mode and no encoding is specified, returns nil.

fcntl(*args) Show source
static VALUE
strio_unimpl(int argc, VALUE *argv, VALUE self)
{
    StringIO(self);
    rb_notimplement();

    UNREACHABLE;
}

Raises NotImplementedError.

fileno() Show source
static VALUE
strio_nil(VALUE self)
{
    StringIO(self);
    return Qnil;
}

Returns nil. Just for compatibility to IO.

flush() Show source
static VALUE
strio_self(VALUE self)
{
    StringIO(self);
    return self;
}

Returns an object itself. Just for compatibility to IO.

fsync() Show source
static VALUE
strio_0(VALUE self)
{
    StringIO(self);
    return INT2FIX(0);
}

Returns 0. Just for compatibility to IO.

getbyte → fixnum or nil Show source
static VALUE
strio_getbyte(VALUE self)
{
    struct StringIO *ptr = readable(self);
    int c;
    if (ptr->pos >= RSTRING_LEN(ptr->string)) {
        return Qnil;
    }
    c = RSTRING_PTR(ptr->string)[ptr->pos++];
    return CHR2FIX(c);
}

See IO#getbyte.

getc → string or nil Show source
static VALUE
strio_getc(VALUE self)
{
    struct StringIO *ptr = readable(self);
    rb_encoding *enc = get_enc(ptr);
    VALUE str = ptr->string;
    long pos = ptr->pos;
    int len;
    char *p;

    if (pos >= RSTRING_LEN(str)) {
        return Qnil;
    }
    p = RSTRING_PTR(str)+pos;
    len = rb_enc_mbclen(p, RSTRING_END(str), enc);
    ptr->pos += len;
    return enc_subseq(str, pos, len, enc);
}

See IO#getc.

gets(sep=$/, chomp: false) → string or nil Show source
gets(limit, chomp: false) → string or nil
gets(sep, limit, chomp: false) → string or nil
static VALUE
strio_gets(int argc, VALUE *argv, VALUE self)
{
    struct getline_arg arg;
    VALUE str;

    if (prepare_getline_args(&arg, argc, argv)->limit == 0) {
        struct StringIO *ptr = readable(self);
        return rb_enc_str_new(0, 0, get_enc(ptr));
    }

    str = strio_getline(&arg, readable(self));
    rb_lastline_set(str);
    return str;
}

See IO#gets.

internal_encoding → encoding Show source
static VALUE
strio_internal_encoding(VALUE self)
{
    return Qnil;
}

Returns the Encoding of the internal string if conversion is specified. Otherwise returns nil.

isatty() Show source
static VALUE
strio_false(VALUE self)
{
    StringIO(self);
    return Qfalse;
}

Returns false. Just for compatibility to IO.

Also aliased as: tty?
length → integer

Returns the size of the buffer string.

Alias for: size
lineno → integer Show source
static VALUE
strio_get_lineno(VALUE self)
{
    return LONG2NUM(StringIO(self)->lineno);
}

Returns the current line number. The stream must be opened for reading. lineno counts the number of times gets is called, rather than the number of newlines encountered. The two values will differ if gets is called with a separator other than newline. See also the $. variable.

lineno = integer → integer Show source
static VALUE
strio_set_lineno(VALUE self, VALUE lineno)
{
    StringIO(self)->lineno = NUM2LONG(lineno);
    return lineno;
}

Manually sets the current line number to the given value. $. is updated only on the next read.

pid() Show source
static VALUE
strio_nil(VALUE self)
{
    StringIO(self);
    return Qnil;
}

Returns nil. Just for compatibility to IO.

pos → integer Show source
tell → integer
static VALUE
strio_get_pos(VALUE self)
{
    return LONG2NUM(StringIO(self)->pos);
}

Returns the current offset (in bytes).

pos = integer → integer Show source
static VALUE
strio_set_pos(VALUE self, VALUE pos)
{
    struct StringIO *ptr = StringIO(self);
    long p = NUM2LONG(pos);
    if (p < 0) {
        error_inval(0);
    }
    ptr->pos = p;
    return pos;
}

Seeks to the given position (in bytes).

putc(obj) → obj Show source
static VALUE
strio_putc(VALUE self, VALUE ch)
{
    struct StringIO *ptr = writable(self);
    VALUE str;

    check_modifiable(ptr);
    if (RB_TYPE_P(ch, T_STRING)) {
        str = rb_str_substr(ch, 0, 1);
    }
    else {
        char c = NUM2CHR(ch);
        str = rb_str_new(&c, 1);
    }
    strio_write(self, str);
    return ch;
}

See IO#putc.

read([length [, outbuf]]) → string, outbuf, or nil Show source
static VALUE
strio_read(int argc, VALUE *argv, VALUE self)
{
    struct StringIO *ptr = readable(self);
    VALUE str = Qnil;
    long len;
    int binary = 0;

    switch (argc) {
      case 2:
        str = argv[1];
        if (!NIL_P(str)) {
            StringValue(str);
            rb_str_modify(str);
        }
        /* fall through */
      case 1:
        if (!NIL_P(argv[0])) {
            len = NUM2LONG(argv[0]);
            if (len < 0) {
                rb_raise(rb_eArgError, "negative length %ld given", len);
            }
            if (len > 0 && ptr->pos >= RSTRING_LEN(ptr->string)) {
                if (!NIL_P(str)) rb_str_resize(str, 0);
                return Qnil;
            }
            binary = 1;
            break;
        }
        /* fall through */
      case 0:
        len = RSTRING_LEN(ptr->string);
        if (len <= ptr->pos) {
            rb_encoding *enc = get_enc(ptr);
            if (NIL_P(str)) {
                str = rb_str_new(0, 0);
            }
            else {
                rb_str_resize(str, 0);
            }
            rb_enc_associate(str, enc);
            return str;
        }
        else {
            len -= ptr->pos;
        }
        break;
      default:
        rb_error_arity(argc, 0, 2);
    }
    if (NIL_P(str)) {
        rb_encoding *enc = binary ? rb_ascii8bit_encoding() : get_enc(ptr);
        str = strio_substr(ptr, ptr->pos, len, enc);
    }
    else {
        long rest = RSTRING_LEN(ptr->string) - ptr->pos;
        if (len > rest) len = rest;
        rb_str_resize(str, len);
        MEMCPY(RSTRING_PTR(str), RSTRING_PTR(ptr->string) + ptr->pos, char, len);
        if (binary)
            rb_enc_associate(str, rb_ascii8bit_encoding());
        else
            rb_enc_copy(str, ptr->string);
    }
    ptr->pos += RSTRING_LEN(str);
    return str;
}

See IO#read.

readlines(sep=$/, chomp: false) → array Show source
readlines(limit, chomp: false) → array
readlines(sep, limit, chomp: false) → array
static VALUE
strio_readlines(int argc, VALUE *argv, VALUE self)
{
    VALUE ary, line;
    struct getline_arg arg;

    StringIO(self);
    ary = rb_ary_new();
    if (prepare_getline_args(&arg, argc, argv)->limit == 0) {
        rb_raise(rb_eArgError, "invalid limit: 0 for readlines");
    }

    while (!NIL_P(line = strio_getline(&arg, readable(self)))) {
        rb_ary_push(ary, line);
    }
    return ary;
}

See IO#readlines.

reopen(other_StrIO) → strio Show source
reopen(string, mode) → strio
static VALUE
strio_reopen(int argc, VALUE *argv, VALUE self)
{
    rb_io_taint_check(self);
    if (argc == 1 && !RB_TYPE_P(*argv, T_STRING)) {
        return strio_copy(self, *argv);
    }
    return strio_init(argc, argv, StringIO(self), self);
}

Reinitializes the stream with the given other_StrIO or string and mode (see StringIO#new).

rewind → 0 Show source
static VALUE
strio_rewind(VALUE self)
{
    struct StringIO *ptr = StringIO(self);
    ptr->pos = 0;
    ptr->lineno = 0;
    return INT2FIX(0);
}

Positions the stream to the beginning of input, resetting lineno to zero.

seek(amount, whence=SEEK_SET) → 0 Show source
static VALUE
strio_seek(int argc, VALUE *argv, VALUE self)
{
    VALUE whence;
    struct StringIO *ptr = StringIO(self);
    long amount, offset;

    rb_scan_args(argc, argv, "11", NULL, &whence);
    amount = NUM2LONG(argv[0]);
    if (CLOSED(self)) {
        rb_raise(rb_eIOError, "closed stream");
    }
    switch (NIL_P(whence) ? 0 : NUM2LONG(whence)) {
      case 0:
        offset = 0;
        break;
      case 1:
        offset = ptr->pos;
        break;
      case 2:
        offset = RSTRING_LEN(ptr->string);
        break;
      default:
        error_inval("invalid whence");
    }
    if (amount > LONG_MAX - offset || amount + offset < 0) {
        error_inval(0);
    }
    ptr->pos = amount + offset;
    return INT2FIX(0);
}

Seeks to a given offset amount in the stream according to the value of whence (see IO#seek).

set_encoding(ext_enc, [int_enc[, opt]]) → strio Show source
static VALUE
strio_set_encoding(int argc, VALUE *argv, VALUE self)
{
    rb_encoding* enc;
    struct StringIO *ptr = StringIO(self);
    VALUE ext_enc, int_enc, opt;

    argc = rb_scan_args(argc, argv, "11:", &ext_enc, &int_enc, &opt);

    if (NIL_P(ext_enc)) {
        enc = rb_default_external_encoding();
    }
    else {
        enc = rb_to_encoding(ext_enc);
    }
    ptr->enc = enc;
    if (WRITABLE(self)) {
        rb_enc_associate(ptr->string, enc);
    }

    return self;
}

Specify the encoding of the StringIO as ext_enc. Use the default external encoding if ext_enc is nil. 2nd argument int_enc and optional hash opt argument are ignored; they are for API compatibility to IO.

set_encoding_by_bom() Show source
static VALUE
strio_set_encoding_by_bom(VALUE self)
{
    struct StringIO *ptr = StringIO(self);

    if (!set_encoding_by_bom(ptr)) return Qnil;
    return rb_enc_from_encoding(ptr->enc);
}
size → integer Show source
static VALUE
strio_size(VALUE self)
{
    VALUE string = StringIO(self)->string;
    if (NIL_P(string)) {
        rb_raise(rb_eIOError, "not opened");
    }
    return ULONG2NUM(RSTRING_LEN(string));
}

Returns the size of the buffer string.

Also aliased as: length
string → string Show source
static VALUE
strio_get_string(VALUE self)
{
    return StringIO(self)->string;
}

Returns underlying String object, the subject of IO.

string = string → string Show source
static VALUE
strio_set_string(VALUE self, VALUE string)
{
    struct StringIO *ptr = StringIO(self);

    rb_io_taint_check(self);
    ptr->flags &= ~FMODE_READWRITE;
    StringValue(string);
    ptr->flags = OBJ_FROZEN(string) ? FMODE_READABLE : FMODE_READWRITE;
    ptr->pos = 0;
    ptr->lineno = 0;
    return ptr->string = string;
}

Changes underlying String object, the subject of IO.

sync → true Show source
static VALUE
strio_get_sync(VALUE self)
{
    StringIO(self);
    return Qtrue;
}

Returns true always.

sync=(p1) Show source
static VALUE
strio_first(VALUE self, VALUE arg)
{
    StringIO(self);
    return arg;
}

Returns the argument unchanged. Just for compatibility to IO.

pos → integer Show source
tell → integer
static VALUE
strio_get_pos(VALUE self)
{
    return LONG2NUM(StringIO(self)->pos);
}

Returns the current offset (in bytes).

truncate(integer) → 0 Show source
static VALUE
strio_truncate(VALUE self, VALUE len)
{
    VALUE string = writable(self)->string;
    long l = NUM2LONG(len);
    long plen = RSTRING_LEN(string);
    if (l < 0) {
        error_inval("negative length");
    }
    rb_str_resize(string, l);
    if (plen < l) {
        MEMZERO(RSTRING_PTR(string) + plen, char, l - plen);
    }
    return len;
}

Truncates the buffer string to at most integer bytes. The stream must be opened for writing.

tty?()

Returns false. Just for compatibility to IO.

Alias for: isatty
ungetbyte(fixnum) → nil Show source
static VALUE
strio_ungetbyte(VALUE self, VALUE c)
{
    struct StringIO *ptr = readable(self);

    check_modifiable(ptr);
    if (NIL_P(c)) return Qnil;
    if (RB_INTEGER_TYPE_P(c)) {
        /* rb_int_and() not visible from exts */
        VALUE v = rb_funcall(c, '&', 1, INT2FIX(0xff));
        const char cc = NUM2INT(v) & 0xFF;
        strio_unget_bytes(ptr, &cc, 1);
    }
    else {
        long cl;
        SafeStringValue(c);
        cl = RSTRING_LEN(c);
        if (cl > 0) {
            strio_unget_bytes(ptr, RSTRING_PTR(c), cl);
            RB_GC_GUARD(c);
        }
    }
    return Qnil;
}

See IO#ungetbyte

ungetc(string) → nil Show source
static VALUE
strio_ungetc(VALUE self, VALUE c)
{
    struct StringIO *ptr = readable(self);
    rb_encoding *enc, *enc2;

    check_modifiable(ptr);
    if (NIL_P(c)) return Qnil;
    if (RB_INTEGER_TYPE_P(c)) {
        int len, cc = NUM2INT(c);
        char buf[16];

        enc = rb_enc_get(ptr->string);
        len = rb_enc_codelen(cc, enc);
        if (len <= 0) rb_enc_uint_chr(cc, enc);
        rb_enc_mbcput(cc, buf, enc);
        return strio_unget_bytes(ptr, buf, len);
    }
    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);
        }
        strio_unget_bytes(ptr, RSTRING_PTR(c), RSTRING_LEN(c));
        RB_GC_GUARD(c);
        return Qnil;
    }
}

Pushes back one character (passed as a parameter) 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.

write(string, ...) → integer Show source
syswrite(string) → integer
static VALUE
strio_write_m(int argc, VALUE *argv, VALUE self)
{
    long len = 0;
    while (argc-- > 0) {
        /* StringIO can't exceed long limit */
        len += strio_write(self, *argv++);
    }
    return LONG2NUM(len);
}

Appends the given string to the underlying buffer string. The stream must be opened for writing. If the argument is not a string, it will be converted to a string using to_s. Returns the number of bytes written. See IO#write.

Ruby Core © 1993–2020 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.