class StringIO

IO streams for strings, with access similar toIO; seeIO.

About the Examples

Examples on this page assume that StringIO has been required:

require'stringio'

And that these constants have been defined:

TEXT =<<EOTFirst lineSecond lineFourth lineFifth lineEOTRUSSIAN ='тест'DATA ="\u9990\u9991\u9992\u9993\u9994"

Constants

MAX_LENGTH

Maximum length that aStringIO instance can hold

VERSION

The version string

Public Class Methods

Source
static VALUEstrio_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);}

Returns a new StringIO instance formed fromstring andmode; the instance should be closed when no longer needed:

strio =StringIO.newstrio.string# => ""strio.closed_read?# => falsestrio.closed_write?# => falsestrio.close

Ifstring is frozen, the defaultmode is'r':

strio =StringIO.new('foo'.freeze)strio.string# => "foo"strio.closed_read?# => falsestrio.closed_write?# => truestrio.close

Argumentmode must be a validAccess Mode, which may be a string or an integer constant:

StringIO.new('foo','w+')StringIO.new('foo',File::RDONLY)

Related:StringIO.open (passes the StringIO object to the block; closes the object automatically on block exit).

Source
static VALUEstrio_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);}

Creates new StringIO instance by callingStringIO.new(string, mode).

With no block given, returns the new instance:

strio =StringIO.open# => #<StringIO>

With a block given, calls the block with the new instance and returns the block’s value; closes the instance on block exit:

StringIO.open('foo') {|strio|strio.string.upcase }# => "FOO"

Related:StringIO.new.

Public Instance Methods

Source
static VALUEstrio_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;}

Sets the data mode inself to binary mode; seeData Mode.

Source
static VALUEstrio_close(VALUE self){    StringIO(self);    RBASIC(self)->flags &= ~STRIO_READWRITE;    return Qnil;}

Closesself for both reading and writing; returnsnil:

strio =StringIO.newstrio.closed?# => falsestrio.close# => nilstrio.closed?# => truestrio.read# Raises IOError: not opened for readingstrio.write# Raises IOError: not opened for writing

Related:StringIO#close_read,StringIO#close_write,StringIO.closed?.

Source
static VALUEstrio_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;}

Closesself for reading; closed-write setting remains unchanged; returnsnil:

strio =StringIO.newstrio.closed_read?# => falsestrio.close_read# => nilstrio.closed_read?# => truestrio.closed_write?# => falsestrio.read# Raises IOError: not opened for reading

Related:StringIO#close,StringIO#close_write.

Source
static VALUEstrio_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;}

Closesself for writing; closed-read setting remains unchanged; returnsnil:

strio =StringIO.newstrio.closed_write?# => falsestrio.close_write# => nilstrio.closed_write?# => truestrio.closed_read?# => falsestrio.write('foo')# Raises IOError: not opened for writing

Related:StringIO#close,StringIO#close_read,StringIO#closed_write?.

Source
static VALUEstrio_closed(VALUE self){    StringIO(self);    if (!CLOSED(self)) return Qfalse;    return Qtrue;}

Returns whetherself is closed for both reading and writing:

strio =StringIO.newstrio.closed?# => false  # Open for reading and writing.strio.close_readstrio.closed?# => false  # Still open for writing.strio.close_writestrio.closed?# => true   # Now closed for both.

Related:StringIO.closed_read?,StringIO.closed_write?.

Source
static VALUEstrio_closed_read(VALUE self){    StringIO(self);    if (READABLE(self)) return Qfalse;    return Qtrue;}

Returns whetherself is closed for reading:

strio =StringIO.newstrio.closed_read?# => falsestrio.close_readstrio.closed_read?# => true

Related:StringIO#closed?,StringIO#closed_write?,StringIO#close_read.

Source
static VALUEstrio_closed_write(VALUE self){    StringIO(self);    if (WRITABLE(self)) return Qfalse;    return Qtrue;}

Returns whetherself is closed for writing:

strio =StringIO.newstrio.closed_write?# => falsestrio.close_writestrio.closed_write?# => true

Related:StringIO#close_write,StringIO#closed?,StringIO#closed_read?.

Source
Also aliased as:each_line
Source
static VALUEstrio_each_byte(VALUE self){    struct StringIO *ptr;    RETURN_ENUMERATOR(self, 0, 0);    while ((ptr = strio_to_read(self)) != NULL) {        char c = RSTRING_PTR(ptr->string)[ptr->pos++];        rb_yield(CHR2FIX(c));    }    return self;}

With a block given, calls the block with each remaining byte in the stream; positions the stream at end-of-file; returnsself:

bytes = []strio =StringIO.new('hello')#  Five 1-byte characters.strio.each_byte {|byte|bytes.push(byte) }strio.eof?# => truebytes# => [104, 101, 108, 108, 111]bytes = []strio =StringIO.new('тест')# Four 2-byte characters.strio.each_byte {|byte|bytes.push(byte) }bytes# => [209, 130, 208, 181, 209, 129, 209, 130]bytes = []strio =StringIO.new('こんにちは')# Five 3-byte characters.strio.each_byte {|byte|bytes.push(byte) }bytes# => [227, 129, 147, 227, 130, 147, 227, 129, 171, 227, 129, 161, 227, 129, 175]

The position in the stream matters:

bytes = []strio =StringIO.new('こんにちは')strio.getc# => "こ"strio.pos# => 3  # 3-byte character was read.strio.each_byte {|byte|bytes.push(byte) }bytes# => [227, 130, 147, 227, 129, 171, 227, 129, 161, 227, 129, 175]

If at end-of-file, does not call the block:

strio.eof?# => truestrio.each_byte {|byte|fail'Boo!' }strio.eof?# => true

With no block given, returns a newEnumerator.

Related:StringIO#each_char,StringIO#each_codepoint,StringIO#each_line.

Source
static VALUEstrio_each_char(VALUE self){    VALUE c;    RETURN_ENUMERATOR(self, 0, 0);    while (!NIL_P(c = strio_getc(self))) {        rb_yield(c);    }    return self;}

With a block given, calls the block with each remaining character in the stream; positions the stream at end-of-file; returnsself:

chars = []strio =StringIO.new('hello')strio.each_char {|char|chars.push(char) }strio.eof?# => truechars# => ["h", "e", "l", "l", "o"]chars = []strio =StringIO.new('тест')strio.each_char {|char|chars.push(char) }chars# => ["т", "е", "с", "т"]chars = []strio =StringIO.new('こんにちは')strio.each_char {|char|chars.push(char) }chars# => ["こ", "ん", "に", "ち", "は"]

Stream position matters:

chars = []strio =StringIO.new('こんにちは')strio.getc# => "こ"strio.pos# => 3  # 3-byte character was read.strio.each_char {|char|chars.push(char) }chars# => ["ん", "に", "ち", "は"]

When at end-of-stream does not call the block:

strio.eof?# => truestrio.each_char {|char|fail'Boo!' }strio.eof?# => true

With no block given, returns a newEnumerator.

Related:StringIO#each_byte,StringIO#each_codepoint,StringIO#each_line.

Source
static VALUEstrio_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);    while ((ptr = strio_to_read(self)) != NULL) {        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;}

With a block given, calls the block with each successive codepoint from self; sets the position to end-of-stream; returnsself.

Each codepoint is the integer value for a character; returns self:

codepoints = []strio =StringIO.new('hello')strio.each_codepoint {|codepoint|codepoints.push(codepoint) }strio.eof?# => truecodepoints# => [104, 101, 108, 108, 111]codepoints = []strio =StringIO.new('тест')strio.each_codepoint {|codepoint|codepoints.push(codepoint) }codepoints# => [1090, 1077, 1089, 1090]codepoints = []strio =StringIO.new('こんにちは')strio.each_codepoint {|codepoint|codepoints.push(codepoint) }codepoints# => [12371, 12435, 12395, 12385, 12399]

Position in the stream matters:

codepoints = []strio =StringIO.new('こんにちは')strio.getc# => "こ"strio.pos# => 3strio.each_codepoint {|codepoint|codepoints.push(codepoint) }codepoints# => [12435, 12395, 12385, 12399]

When at end-of-stream, the block is not called:

strio.eof?# => truestrio.each_codepoint {|codepoint|fail'Boo!' }strio.eof?# => true

With no block given, returns a newEnumerator.

Related:StringIO#each_byte,StringIO#each_char,StringIO#each_line.

With a block given calls the block with each remaining line (see “Position” below) in the stream; returnsself.

Leaves stream position as end-of-stream.

No Arguments

With no arguments given, reads lines using the default record separator global variable$/, whose initial value is"\n".

strio =StringIO.new(TEXT)strio.each_line {|line|pline }strio.eof?# => true

Output:

"First line\n""Second line\n""\n""Fourth line\n""Fifth line\n"

Argumentsep

With only string argumentsep given, reads lines using that string as the record separator:

strio =StringIO.new(TEXT)strio.each_line(' ') {|line|pline }

Output:

"First ""line\nSecond ""line\n\nFourth ""line\nFifth ""line\n"

Argumentlimit

With only integer argumentlimit given, reads lines using the default record separator global variable$/, whose initial value is"\n"; also limits the size (in characters) of each line to the given limit:

strio =StringIO.new(TEXT)strio.each_line(10) {|line|pline }

Output:

"First line""\n""Second lin""e\n""\n""Fourth lin""e\n""Fifth line""\n"

Argumentssep andlimit

With argumentssep andlimit both given, honors both:

strio =StringIO.new(TEXT)strio.each_line(' ',10) {|line|pline }

Output:

"First ""line\nSecon""d ""line\n\nFour""th ""line\nFifth"" ""line\n"

Position

As stated above, methodeachremaining line in the stream.

In the examples above eachstrio object starts with its position at beginning-of-stream; but in other cases the position may be anywhere (seeStringIO#pos):

strio =StringIO.new(TEXT)strio.pos =30# Set stream position to character 30.strio.each_line {|line|pline }

Output:

" line\n""Fifth line\n"

Special Record Separators

Like some methds in classIO,StringIO.each honors two special record separators; seeSpecial Line Separators.

strio =StringIO.new(TEXT)strio.each_line('') {|line|pline }# Read as paragraphs (separated by blank lines).

Output:

"First line\nSecond line\n\n""Fourth line\nFifth line\n"
strio =StringIO.new(TEXT)strio.each_line(nil) {|line|pline }# "Slurp"; read it all.

Output:

"First line\nSecond line\n\nFourth line\nFifth line\n"

Keyword Argumentchomp

With keyword argumentchomp given astrue (the default isfalse), removes trailing newline (if any) from each line:

strio =StringIO.new(TEXT)strio.each_line(chomp:true) {|line|pline }

Output:

"First line""Second line""""Fourth line""Fifth line"

With no block given, returns a newEnumerator.

Related:StringIO.each_byte,StringIO.each_char,StringIO.each_codepoint.

Alias for:each
Source
Also aliased as:eof?

Returns whetherself is positioned at end-of-stream:

strio =StringIO.new('foo')strio.pos# => 0strio.eof?# => falsestrio.read# => "foo"strio.pos# => 3strio.eof?# => truestrio.close_readstrio.eof?# Raises IOError: not opened for reading

Related:StringIO#pos.

Alias for:eof
Source
static VALUEstrio_external_encoding(VALUE self){    struct StringIO *ptr = StringIO(self);    return rb_enc_from_encoding(get_enc(ptr));}

Returns anEncoding object that represents the encoding of the string; seeEncoding:

strio =StringIO.new('foo')strio.external_encoding# => #<Encoding:UTF-8>

Returnsnil ifself has no string and is in write mode:

strio =StringIO.new(nil,'w+')strio.external_encoding# => nil
Source
static VALUEstrio_unimpl(int argc, VALUE *argv, VALUE self){    StringIO(self);    rb_notimplement();    UNREACHABLE;}

RaisesNotImplementedError.

Source
static VALUEstrio_nil(VALUE self){    StringIO(self);    return Qnil;}

Returnsnil; for compatibility withIO.

Source
static VALUEstrio_self(VALUE self){    StringIO(self);    return self;}

Returnsself; for compatibility withIO.

Source
static VALUEstrio_0(VALUE self){    StringIO(self);    return INT2FIX(0);}

Returns 0; for compatibility withIO.

Source
static VALUEstrio_getbyte(VALUE self){    struct StringIO *ptr = readable(self);    int c;    if (eos_p(ptr)) {        return Qnil;    }    c = RSTRING_PTR(ptr->string)[ptr->pos++];    return CHR2FIX(c);}

Reads and returns the next integer byte (not character) from the stream:

s ='foo's.bytes# => [102, 111, 111]strio =StringIO.new(s)strio.getbyte# => 102strio.getbyte# => 111strio.getbyte# => 111

Returnsnil if at end-of-stream:

strio.eof?# => truestrio.getbyte# => nil

Returns a byte, not a character:

s ='тест's.bytes# => [209, 130, 208, 181, 209, 129, 209, 130]strio =StringIO.new(s)strio.getbyte# => 209strio.getbyte# => 130s ='こんにちは's.bytes# => [227, 129, 147, 227, 130, 147, 227, 129, 171, 227, 129, 161, 227, 129, 175]strio =StringIO.new(s)strio.getbyte# => 227strio.getbyte# => 129

Related:StringIO.getc.

Source
static VALUEstrio_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 (eos_p(ptr)) {        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);}

Reads and returns the next character (or byte; see below) from the stream:

strio =StringIO.new('foo')strio.getc# => "f"strio.getc# => "o"strio.getc# => "o"

Returnsnil if at end-of-stream:

strio.eof?# => truestrio.getc# => nil

Returns characters, not bytes:

strio =StringIO.new('тест')strio.getc# => "т"strio.getc# => "е"strio =StringIO.new('こんにちは')strio.getc# => "こ"strio.getc# => "ん"

In each of the examples above, the stream is positioned at the beginning of a character; in other cases that need not be true:

strio =StringIO.new('こんにちは')# Five 3-byte characters.strio.pos =3# => 3     # At beginning of second character; returns character.strio.getc# => "ん"strio.pos =4# => 4     # At second byte of second character; returns byte.strio.getc# => "\x82"strio.pos =5# => 5     # At third byte of second character; returns byte.strio.getc# => "\x93"

Related:StringIO.getbyte.

Source
static VALUEstrio_gets(int argc, VALUE *argv, VALUE self){    struct StringIO *ptr = readable(self);    struct getline_arg arg;    VALUE str;    if (prepare_getline_args(ptr, &arg, argc, argv)->limit == 0) {        if (NIL_P(ptr->string)) return Qnil;        return rb_enc_str_new(0, 0, get_enc(ptr));    }    str = strio_getline(&arg, ptr);    rb_lastline_set(str);    return str;}

Reads and returns a line from the stream; returnsnil if at end-of-stream.

Side effects:

  • Increments stream position by the number of bytes read.

  • Assigns the return value to global variable$_.

With no arguments given, reads a line using the default record separator (global variable$/,* whose initial value is"\n"):

strio =StringIO.new(TEXT)strio.pos# => 0strio.gets# => "First line\n"strio.pos# => 11$_# => "First line\n"strio.gets# => "Second line\n"strio.read# => "\nFourth line\nFifth line\n"strio.eof?# => truestrio.gets# => nilstrio =StringIO.new('тест')# Four 2-byte characters.strio.pos# => 0strio.gets# => "тест"strio.pos# => 8

Argumentsep

With only string argumentsep given, reads a line using that string as the record separator:

strio =StringIO.new(TEXT)strio.gets(' ')# => "First "strio.gets(' ')# => "line\nSecond "strio.gets(' ')# => "line\n\nFourth "

Argumentlimit

With only integer argumentlimit given, reads a line using the default record separator; limits the size (in characters) of each line to the given limit:

strio =StringIO.new(TEXT)strio.gets(10)# => "First line"strio.gets(10)# => "\n"strio.gets(10)# => "Second lin"strio.gets(10)# => "e\n"

Argumentssep andlimit

With argumentssep andlimit both given, honors both:

strio =StringIO.new(TEXT)strio.gets(' ',10)# => "First "strio.gets(' ',10)# => "line\nSecon"strio.gets(' ',10)# => "d "

Position

As stated above, methodgets reads and returns the next line in the stream.

In the examples above eachstrio object starts with its position at beginning-of-stream; but in other cases the position may be anywhere:

strio =StringIO.new(TEXT)strio.pos =12strio.gets# => "econd line\n"

The position need not be at a character boundary:

strio =StringIO.new('тест')# Four 2-byte characters.strio.pos =2# At beginning of second character.strio.gets# => "ест"strio.pos =3# In middle of second character.strio.gets# => "\xB5ст"

Special Record Separators

Like some methods in classIO, methodgets honors two special record separators; seeSpecial Line Separators:

strio =StringIO.new(TEXT)strio.gets('')# Read "paragraph" (up to empty line).# => "First line\nSecond line\n\n"strio =StringIO.new(TEXT)strio.gets(nil)# "Slurp": read all.# => "First line\nSecond line\n\nFourth line\nFifth line\n"

Keyword Argumentchomp

With keyword argumentchomp given astrue (the default isfalse), removes the trailing newline (if any) from the returned line:

strio =StringIO.new(TEXT)strio.gets# => "First line\n"strio.gets(chomp:true)# => "Second line"

Related:StringIO.each_line.

Source
static VALUEstrio_internal_encoding(VALUE self){    return Qnil;}

Returnsnil; for compatibility withIO.

Source
static VALUEstrio_false(VALUE self){    StringIO(self);    return Qfalse;}

Returnsfalse; for compatibility withIO.

Also aliased as:tty?

Returns the size of the buffer string.

Alias for:size
Source
static VALUEstrio_get_lineno(VALUE self){    return LONG2NUM(StringIO(self)->lineno);}

Returns the current line number inself; seeLine Number.

Source
static VALUEstrio_set_lineno(VALUE self, VALUE lineno){    StringIO(self)->lineno = NUM2LONG(lineno);    return lineno;}

Sets the current line number inself to the givennew_line_number; seeLine Number.

Source
static VALUEstrio_nil(VALUE self){    StringIO(self);    return Qnil;}

Returnsnil; for compatibility withIO.

Source
static VALUEstrio_get_pos(VALUE self){    return LONG2NUM(StringIO(self)->pos);}

Returns the current position (in bytes); seePosition.

Source
static VALUEstrio_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;}

Sets the current position (in bytes); seePosition.

Source
static VALUEstrio_pread(int argc, VALUE *argv, VALUE self){    VALUE rb_len, rb_offset, rb_buf;    rb_scan_args(argc, argv, "21", &rb_len, &rb_offset, &rb_buf);    long len = NUM2LONG(rb_len);    long offset = NUM2LONG(rb_offset);    if (len < 0) {        rb_raise(rb_eArgError, "negative string size (or size too big): %" PRIsVALUE, rb_len);    }    if (len == 0) {        if (NIL_P(rb_buf)) {            return rb_str_new("", 0);        }        return rb_buf;    }    if (offset < 0) {        rb_syserr_fail_str(EINVAL, rb_sprintf("pread: Invalid offset argument: %" PRIsVALUE, rb_offset));    }    struct StringIO *ptr = readable(self);    if (outside_p(ptr, offset)) {        rb_eof_error();    }    if (NIL_P(rb_buf)) {        return strio_substr(ptr, offset, len, rb_ascii8bit_encoding());    }    long rest = RSTRING_LEN(ptr->string) - offset;    if (len > rest) len = rest;    rb_str_resize(rb_buf, len);    rb_enc_associate(rb_buf, rb_ascii8bit_encoding());    MEMCPY(RSTRING_PTR(rb_buf), RSTRING_PTR(ptr->string) + offset, char, len);    return rb_buf;}

SeeIO#pread.

Source
static VALUEstrio_putc(VALUE self, VALUE ch){    struct StringIO *ptr = writable(self);    VALUE str;    check_modifiable(ptr);    if (RB_TYPE_P(ch, T_STRING)) {        if (NIL_P(ptr->string)) return ch;        str = rb_str_substr(ch, 0, 1);    }    else {        char c = NUM2CHR(ch);        if (NIL_P(ptr->string)) return ch;        str = rb_str_new(&c, 1);    }    strio_write(self, str);    return ch;}

SeeIO#putc.

Source
static VALUEstrio_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 (eos_p(ptr)) {                if (!NIL_P(str)) rb_str_resize(str, 0);                return len > 0 ? Qnil : rb_str_new(0, 0);            }            binary = 1;            break;        }        /* fall through */      case 0:        if (NIL_P(ptr->string)) return Qnil;        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_copy(str, ptr->string);        }    }    ptr->pos += RSTRING_LEN(str);    return str;}

SeeIO#read.

Source
static VALUEstrio_readlines(int argc, VALUE *argv, VALUE self){    VALUE ary, line;    struct StringIO *ptr = readable(self);    struct getline_arg arg;    if (prepare_getline_args(ptr, &arg, argc, argv)->limit == 0) {        rb_raise(rb_eArgError, "invalid limit: 0 for readlines");    }    ary = rb_ary_new();    while (!NIL_P(line = strio_getline(&arg, ptr))) {        rb_ary_push(ary, line);    }    return ary;}

SeeIO#readlines.

Source
static VALUEstrio_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 givenother (string orStringIO) andmode; seeIO.new:

StringIO.open('foo')do|strio|pstrio.stringstrio.reopen('bar')pstrio.stringother_strio =StringIO.new('baz')strio.reopen(other_strio)pstrio.stringother_strio.closeend

Output:

"foo""bar""baz"
Source
static VALUEstrio_rewind(VALUE self){    struct StringIO *ptr = StringIO(self);    ptr->pos = 0;    ptr->lineno = 0;    return INT2FIX(0);}

Sets the current position and line number to zero; seePosition andLine Number.

Source
static VALUEstrio_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:        if (NIL_P(ptr->string)) {            offset = 0;        } else {            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);}

Sets the current position to the given integeroffset (in bytes), with respect to a given constantwhence; seePosition.

Source
static VALUEstrio_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_find_encoding(ext_enc);        if (!enc) {            rb_io_enc_t convconfig;            int oflags;            rb_io_mode_t fmode;            VALUE vmode = rb_str_append(rb_str_new_cstr("r:"), ext_enc);            rb_io_extract_modeenc(&vmode, 0, Qnil, &oflags, &fmode, &convconfig);            enc = convconfig.enc2;        }    }    ptr->enc = enc;    if (!NIL_P(ptr->string) && WRITABLE(self) && !str_chilled_p(ptr->string)) {        rb_enc_associate(ptr->string, enc);    }    return self;}

Specify the encoding of theStringIO asext_enc. Use the default external encoding ifext_enc is nil. 2nd argumentint_enc and optional hashopt argument are ignored; they are for API compatibility toIO.

Source
static VALUEstrio_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);}

Sets the encoding according to the BOM (Byte Order Mark) in the string.

Returnsself if the BOM is found, otherwise +nil.

Source
static VALUEstrio_size(VALUE self){    VALUE string = StringIO(self)->string;    if (NIL_P(string)) {        return INT2FIX(0);    }    return ULONG2NUM(RSTRING_LEN(string));}

Returns the size of the buffer string.

Also aliased as:length
Source
static VALUEstrio_get_string(VALUE self){    return StringIO(self)->string;}

Returns underlying string:

StringIO.open('foo')do|strio|pstrio.stringstrio.string ='bar'pstrio.stringend

Output:

"foo""bar"

Related:StringIO#string= (assigns the underlying string).

Source
static VALUEstrio_set_string(VALUE self, VALUE string){    struct StringIO *ptr = StringIO(self);    rb_io_taint_check(self);    ptr->flags &= ~FMODE_READWRITE;    StringValue(string);    ptr->flags = readonly_string_p(string) ? FMODE_READABLE : FMODE_READWRITE;    ptr->pos = 0;    ptr->lineno = 0;    RB_OBJ_WRITE(self, &ptr->string, string);    return string;}

Replaces the stored string withother_string, and sets the position to zero; returnsother_string:

StringIO.open('foo')do|strio|pstrio.stringstrio.string ='bar'pstrio.stringend

Output:

"foo""bar"

Related:StringIO#string (returns the stored string).

Source
static VALUEstrio_get_sync(VALUE self){    StringIO(self);    return Qtrue;}

Returnstrue; implemented only for compatibility with other stream classes.

Source
static VALUEstrio_first(VALUE self, VALUE arg){    StringIO(self);    return arg;}

Returns the argument unchanged. Just for compatibility toIO.

Source
static VALUEstrio_get_pos(VALUE self){    return LONG2NUM(StringIO(self)->pos);}

Returns the current position (in bytes); seePosition.

Source
static VALUEstrio_truncate(VALUE self, VALUE len){    VALUE string = writable(self)->string;    long l = NUM2LONG(len);    long plen;    if (l < 0) {        error_inval("negative length");    }    if (NIL_P(string)) return 0;    plen = RSTRING_LEN(string);    rb_str_resize(string, l);    if (plen < l) {        MEMZERO(RSTRING_PTR(string) + plen, char, l - plen);    }    return INT2FIX(0);}

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

Returnsfalse; for compatibility withIO.

Alias for:isatty
Source
static VALUEstrio_ungetbyte(VALUE self, VALUE c){    struct StringIO *ptr = readable(self);    check_modifiable(ptr);    if (NIL_P(ptr->string)) return Qnil;    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 {        StringValue(c);        strio_unget_string(ptr, c);    }    return Qnil;}

Pushes back (“unshifts”) an 8-bit byte onto the stream; seeByte IO.

Source
static VALUEstrio_ungetc(VALUE self, VALUE c){    struct StringIO *ptr = readable(self);    rb_encoding *enc, *enc2;    check_modifiable(ptr);    if (NIL_P(ptr->string)) return Qnil;    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); /* to raise an exception */            UNREACHABLE;        }        rb_enc_mbcput(cc, buf, enc);        return strio_unget_bytes(ptr, buf, len);    }    else {        StringValue(c);        if (RSTRING_LEN(c) == 0) return Qnil;        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_string(ptr, c);        return Qnil;    }}

Pushes back (“unshifts”) a character or integer onto the stream; seeCharacter IO.

Source
static VALUEstrio_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 usingto_s. Returns the number of bytes written. SeeIO#write.