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 a
StringIOinstance 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.
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
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.
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.
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.
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.
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.
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.