Class: StringIO
| Relationships & Source Files | |
| Super Chains via Extension / Inclusion / Inheritance | |
| Instance Chain: 
          self,
          Enumerable,
           ::IO::generic_readable,::IO::generic_writable | |
| Inherits: | Object | 
| Defined in: | ext/stringio/stringio.c | 
Overview
Constant Summary
- 
    MAX_LENGTH =
    # File 'ext/stringio/stringio.c', line 1914Maximum length that a StringIOinstance can holdLONG2NUM(LONG_MAX) 
- 
    VERSION =
    # File 'ext/stringio/stringio.c', line 1908The version string rb_str_new_cstr(STRINGIO_VERSION) 
Class Method Summary
- 
    
      .open(string = '', mode = 'r+') {|strio| ... } 
    
    Note that modedefaults to'r'if #string is frozen.
- .new(*args) constructor Internal use only
Instance Attribute Summary
- 
    
      #closed?  ⇒ Boolean 
    
    readonly
    Returns trueifselfis closed for both reading and writing,falseotherwise.
- 
    
      #closed_read?  ⇒ Boolean 
    
    readonly
    Returns trueifselfis closed for reading,falseotherwise.
- 
    
      #closed_write?  ⇒ Boolean 
    
    readonly
    Returns trueifselfis closed for writing,falseotherwise.
- 
    
      #eof?  ⇒ Boolean 
      (also: #eof?)
    
    readonly
    Returns trueif positioned at end-of-stream,falseotherwise; see Position.
- 
    
      #eof?  ⇒ Boolean 
    
    readonly
    Alias for #eof. 
- 
    
      #lineno  ⇒ current_line_number 
    
    rw
    Returns the current line number in self; see Line Number.
- 
    
      #lineno=(new_line_number)  ⇒ new_line_number 
    
    rw
    Sets the current line number in selfto the givennew_line_number; see Line Number.
- 
    
      #pos  ⇒ stream_position 
    
    rw
    Returns the current position (in bytes); see Position. 
- 
    
      #pos=(new_position)  ⇒ new_position 
    
    rw
    Sets the current position (in bytes); see Position. 
- 
    
      #string  ⇒ String 
    
    rw
    Returns underlying string: 
- 
    
      #string=(other_string)  ⇒ other_string 
    
    rw
    Assigns the underlying string as other_string, and sets position to zero; returnsother_string:
- #tty? ⇒ Boolean readonly
Instance Method Summary
- 
    
      #binmode  ⇒ self 
    
    Sets the data mode in selfto binary mode; see Data Mode.
- 
    
      #close  ⇒ nil 
    
    Closes selffor both reading and writing.
- 
    
      #close_read  ⇒ nil 
    
    Closes selffor reading; closed-write setting remains unchanged.
- 
    
      #close_write  ⇒ nil 
    
    Closes selffor writing; closed-read setting remains unchanged.
- 
    
      #each_line(sep = $/, chomp: false) {|line| ... } ⇒ self 
      (also: #each_line)
    
    Calls the block with each remaining line read from the stream; does nothing if already at end-of-file; returns self.
- 
    
      #each_byte {|byte| ... } ⇒ self 
    
    With a block given, calls the block with each remaining byte in the stream; see Byte IO. 
- 
    
      #each_char {|c| ... } ⇒ self 
    
    With a block given, calls the block with each remaining character in the stream; see Character IO. 
- 
    
      #each_codepoint {|codepoint| ... } ⇒ self 
    
    With a block given, calls the block with each remaining codepoint in the stream; see Codepoint IO. 
- 
    
      #each_line(sep = $/, chomp: false) {|line| ... } ⇒ self 
    
    Alias for #each. 
- 
    
      #external_encoding  ⇒ Encoding 
    
    Returns the Encoding object that represents the encoding of the file. 
- #fcntl
- #fileno
- #flush
- #fsync
- 
    
      #getbyte  ⇒ byte? 
    
    Reads and returns the next 8-bit byte from the stream; see Byte IO. 
- 
    
      #getc  ⇒ character? 
    
    Reads and returns the next character from the stream; see Character IO. 
- 
    
      #gets(sep = $/, chomp: false)  ⇒ String? 
    
    Reads and returns a line from the stream; assigns the return value to $_; see Line IO.
- 
    
      #new(string = '', mode = 'r+')  ⇒ StringIO 
    
    constructor
    Note that modedefaults to'r'if #string is frozen.
- 
    
      #internal_encoding  ⇒ Encoding 
    
    Returns the Encoding of the internal string if conversion is specified. 
- #isatty
- 
    
      #length  ⇒ Integer 
      (also: #size)
    
    Returns the size of the buffer string. 
- #pid
- 
    
      #pread(maxlen, offset)  ⇒ String 
    
    See IO#pread.
- 
    
      #putc(obj)  ⇒ Object 
    
    See IO#putc.
- 
    
      #read([length [, outbuf]])  ⇒ String, ... 
    
    See IO#read.
- 
    
      #readlines(sep = $/, chomp: false)  ⇒ Array 
    
    See IO#readlines.
- 
    
      #reopen(other, mode = 'r+')  ⇒ self 
    
    Reinitializes the stream with the given other(string orStringIO) andmode; seeIO.new:
- 
    
      #rewind  ⇒ 0 
    
    Sets the current position and line number to zero; see Position and Line Number. 
- 
    
      #seek(offset, whence = SEEK_SET)  ⇒ 0 
    
    Sets the current position to the given integer offset(in bytes), with respect to a given constantwhence; see Position.
- 
    
      #set_encoding(ext_enc, [int_enc[, opt]])  ⇒ strio 
    
    Specify the encoding of the StringIOas ext_enc.
- 
    
      #set_encoding_by_bom  ⇒ strio? 
    
    Sets the encoding according to the BOM (Byte Order Mark) in the string. 
- 
    
      #size  ⇒ Integer 
    
    Alias for #length. 
- 
    
      #sync  ⇒ true 
    
    Returns true; implemented only for compatibility with other stream classes.
- #sync=
- #tell
- 
    
      #truncate(integer)  ⇒ 0 
    
    Truncates the buffer string to at most integer bytes. 
- 
    
      #ungetbyte(byte)  ⇒ nil 
    
    Pushes back (“unshifts”) an 8-bit byte onto the stream; see Byte IO. 
- 
    
      #ungetc(character)  ⇒ nil 
    
    Pushes back (“unshifts”) a character or integer onto the stream; see Character IO. 
- 
    
      #write(string, ...)  ⇒ Integer 
    
    Appends the given string to the underlying buffer string. 
- #initialize_copy(orig) Internal use only
::IO::generic_readable - Included
| #read_nonblock | Similar to #read, but raises  | 
| #readbyte | |
| #readchar | Like #getc, but raises an exception if already at end-of-stream; see Character IO. | 
| #readline | Reads a line as with  | 
| #readpartial | Alias for IO::generic_readable#sysread. | 
| #sysread | Similar to #read, but raises  | 
::IO::generic_writable - Included
Constructor Details
.new(*args)
# File 'ext/stringio/stringio.c', line 369
static VALUE
strio_s_new(int argc, VALUE *argv, VALUE klass)
{
    if (rb_block_given_p()) {
	VALUE cname = rb_obj_as_string(klass);
	rb_warn("%"PRIsVALUE"::new() does not take block; use %"PRIsVALUE"::open() instead",
		cname, cname);
    }
    return rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);
}
  
    #new(string = '', mode = 'r+')  ⇒ StringIO   
# File 'ext/stringio/stringio.c', line 207
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);
}
  Class Method Details
.open(string = '', mode = 'r+') {|strio| ... }
Note that mode defaults to 'r' if #string is frozen.
Creates a new StringIO instance formed from #string and mode; see Access Modes.
With no block, returns the new instance:
strio = StringIO.open # => #<StringIO>With a block, calls the block with the new instance and returns the block’s value; closes the instance on block exit.
StringIO.open {|strio| p strio }
# => #<StringIO>Related: .new.
# File 'ext/stringio/stringio.c', line 360
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);
}
  Instance Attribute Details
    #closed?  ⇒ Boolean  (readonly)  
Returns true if self is closed for both reading and writing, false otherwise.
# File 'ext/stringio/stringio.c', line 570
static VALUE
strio_closed(VALUE self)
{
    StringIO(self);
    if (!CLOSED(self)) return Qfalse;
    return Qtrue;
}
  
    #closed_read?  ⇒ Boolean  (readonly)  
Returns true if self is closed for reading, false otherwise.
# File 'ext/stringio/stringio.c', line 584
static VALUE
strio_closed_read(VALUE self)
{
    StringIO(self);
    if (READABLE(self)) return Qfalse;
    return Qtrue;
}
  
    #closed_write?  ⇒ Boolean  (readonly)  
Returns true if self is closed for writing, false otherwise.
# File 'ext/stringio/stringio.c', line 598
static VALUE
strio_closed_write(VALUE self)
{
    StringIO(self);
    if (WRITABLE(self)) return Qfalse;
    return Qtrue;
}
  
    #eof?  ⇒ Boolean  (readonly)    Also known as: #eof?
  
Returns true if positioned at end-of-stream, false otherwise; see Position.
Raises IOError if the stream is not opened for reading.
# File 'ext/stringio/stringio.c', line 624
static VALUE
strio_eof(VALUE self)
{
    if (strio_to_read(self)) return Qfalse;
    return Qtrue;
}
  
    
      #eof?  ⇒ Boolean  (readonly)
      #eof?  ⇒ Boolean 
    
  
Boolean  (readonly)
      #eof?  ⇒ Boolean 
    Alias for #eof.
    #lineno  ⇒ current_line_number  (rw)  
Returns the current line number in self; see Line Number.
# File 'ext/stringio/stringio.c', line 661
static VALUE
strio_get_lineno(VALUE self)
{
    return LONG2NUM(StringIO(self)->lineno);
}
  
    #lineno=(new_line_number)  ⇒ new_line_number  (rw)  
Sets the current line number in self to the given new_line_number; see Line Number.
# File 'ext/stringio/stringio.c', line 674
static VALUE
strio_set_lineno(VALUE self, VALUE lineno)
{
    StringIO(self)->lineno = NUM2LONG(lineno);
    return lineno;
}
  
    #pos  ⇒ stream_position  (rw)  
Returns the current position (in bytes); see Position.
# File 'ext/stringio/stringio.c', line 749
static VALUE
strio_get_pos(VALUE self)
{
    return LONG2NUM(StringIO(self)->pos);
}
  
    #pos=(new_position)  ⇒ new_position  (rw)  
Sets the current position (in bytes); see Position.
# File 'ext/stringio/stringio.c', line 762
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;
}
  
    #string  ⇒ String  (rw)  
# File 'ext/stringio/stringio.c', line 462
static VALUE
strio_get_string(VALUE self)
{
    return StringIO(self)->string;
}
  
    #string=(other_string)  ⇒ other_string  (rw)  
# File 'ext/stringio/stringio.c', line 488
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 = readonly_string_p(string) ? FMODE_READABLE : FMODE_READWRITE;
    ptr->pos = 0;
    ptr->lineno = 0;
    RB_OBJ_WRITE(self, &ptr->string, string);
    return string;
}
  
    #tty?  ⇒ Boolean  (readonly)
  
  [ GitHub ]
Instance Method Details
    #binmode  ⇒ self   
Sets the data mode in self to binary mode; see Data Mode.
# File 'ext/stringio/stringio.c', line 689
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;
}
  
    #close  ⇒ nil   
Closes self for both reading and writing.
Raises IOError if reading or writing is attempted.
Related: #close_read, #close_write.
# File 'ext/stringio/stringio.c', line 513
static VALUE
strio_close(VALUE self)
{
    StringIO(self);
    RBASIC(self)->flags &= ~STRIO_READWRITE;
    return Qnil;
}
  
    #close_read  ⇒ nil   
Closes self for reading; closed-write setting remains unchanged.
Raises IOError if reading is attempted.
Related: #close, #close_write.
# File 'ext/stringio/stringio.c', line 531
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;
}
  
    #close_write  ⇒ nil   
Closes self for writing; closed-read setting remains unchanged.
Raises IOError if writing is attempted.
Related: #close, #close_read.
# File 'ext/stringio/stringio.c', line 552
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;
}
  
    
      #each_line(sep = $/, chomp: false) {|line| ... } ⇒ self 
      #each_line(limit, chomp: false) {|line| ... } ⇒ self 
      #each_line(sep, limit, chomp: false) {|line| ... } ⇒ self 
    
    Also known as: #each_line
  
self 
      #each_line(limit, chomp: false) {|line| ... } ⇒ self 
      #each_line(sep, limit, chomp: false) {|line| ... } ⇒ self 
    Calls the block with each remaining line read from the stream; does nothing if already at end-of-file; returns self. See Line IO.
# File 'ext/stringio/stringio.c', line 1388
static VALUE
strio_each(int argc, VALUE *argv, VALUE self)
{
    VALUE line;
    struct StringIO *ptr = readable(self);
    struct getline_arg arg;
    RETURN_ENUMERATOR(self, argc, argv);
    if (prepare_getline_args(ptr, &arg, argc, argv)->limit == 0) {
	rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
    }
    while (!NIL_P(line = strio_getline(&arg, ptr))) {
	rb_yield(line);
    }
    return self;
}
  
    #each_byte {|byte| ... } ⇒ self   
With a block given, calls the block with each remaining byte in the stream; see Byte IO.
With no block given, returns an enumerator.
# File 'ext/stringio/stringio.c', line 857
static VALUE
strio_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;
}
  
    #each_char {|c| ... } ⇒ self   
With a block given, calls the block with each remaining character in the stream; see Character IO.
With no block given, returns an enumerator.
# File 'ext/stringio/stringio.c', line 1085
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;
}
  
    #each_codepoint {|codepoint| ... } ⇒ self   
With a block given, calls the block with each remaining codepoint in the stream; see Codepoint IO.
With no block given, returns an enumerator.
# File 'ext/stringio/stringio.c', line 1107
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);
    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;
}
  
    
      #each_line(sep = $/, chomp: false) {|line| ... } ⇒ self 
      #each_line(limit, chomp: false) {|line| ... } ⇒ self 
      #each_line(sep, limit, chomp: false) {|line| ... } ⇒ self 
    
  
self 
      #each_line(limit, chomp: false) {|line| ... } ⇒ self 
      #each_line(sep, limit, chomp: false) {|line| ... } ⇒ self 
    Alias for #each.
    #external_encoding  ⇒ Encoding   
Returns the Encoding object that represents the encoding of the file. If the stream is write mode and no encoding is specified, returns nil.
# File 'ext/stringio/stringio.c', line 1805
static VALUE
strio_external_encoding(VALUE self)
{
    struct StringIO *ptr = StringIO(self);
    return rb_enc_from_encoding(get_enc(ptr));
}
  #fcntl
[ GitHub ]#fileno
[ GitHub ]#flush
[ GitHub ]#fsync
[ GitHub ]
    #getbyte  ⇒ byte?   
Reads and returns the next 8-bit byte from the stream; see Byte IO.
# File 'ext/stringio/stringio.c', line 904
static VALUE
strio_getbyte(VALUE self)
{
    struct StringIO *ptr = readable(self);
    int c;
    if (NIL_P(ptr->string) || ptr->pos >= RSTRING_LEN(ptr->string)) {
	return Qnil;
    }
    c = RSTRING_PTR(ptr->string)[ptr->pos++];
    return CHR2FIX(c);
}
  
    #getc  ⇒ character?   
Reads and returns the next character from the stream; see Character IO.
# File 'ext/stringio/stringio.c', line 878
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 (NIL_P(str) || 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);
}
  
    
      #gets(sep = $/, chomp: false)  ⇒ String? 
      #gets(limit, chomp: false)  ⇒ String? 
      #gets(sep, limit, chomp: false)  ⇒ String? 
    
  
String? 
      #gets(limit, chomp: false)  ⇒ String? 
      #gets(sep, limit, chomp: false)  ⇒ String? 
    Reads and returns a line from the stream; assigns the return value to $_; see Line IO.
# File 'ext/stringio/stringio.c', line 1343
static VALUE
strio_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;
}
  #initialize_copy(orig)
# File 'ext/stringio/stringio.c', line 632
static VALUE
strio_copy(VALUE copy, VALUE orig)
{
    struct StringIO *ptr, *old_ptr;
    VALUE old_string = Qundef;
    orig = rb_convert_type(orig, T_DATA, "StringIO", "to_strio");
    if (copy == orig) return copy;
    ptr = StringIO(orig);
    old_ptr = check_strio(copy);
    if (old_ptr) {
	old_string = old_ptr->string;
	strio_free(old_ptr);
    }
    DATA_PTR(copy) = ptr;
    RB_OBJ_WRITTEN(copy, old_string, ptr->string);
    RBASIC(copy)->flags &= ~STRIO_READWRITE;
    RBASIC(copy)->flags |= RBASIC(orig)->flags & STRIO_READWRITE;
    ++ptr->count;
    return copy;
}
  
    #internal_encoding  ⇒ Encoding   
Returns the Encoding of the internal string if conversion is specified.  Otherwise returns nil.
# File 'ext/stringio/stringio.c', line 1820
static VALUE
strio_internal_encoding(VALUE self)
{
    return Qnil;
}
  #isatty
[ GitHub ]
    
      #length  ⇒ Integer 
      #size  ⇒ Integer 
    
    Also known as: #size
  
Integer 
      #size  ⇒ Integer 
    Returns the size of the buffer string.
# File 'ext/stringio/stringio.c', line 1761
static VALUE
strio_size(VALUE self)
{
    VALUE string = StringIO(self)->string;
    if (NIL_P(string)) {
	return INT2FIX(0);
    }
    return ULONG2NUM(RSTRING_LEN(string));
}
  #pid
[ GitHub ]
    
      #pread(maxlen, offset)  ⇒ String 
      #pread(maxlen, offset, out_string)  ⇒ String 
    
  
String 
      #pread(maxlen, offset, out_string)  ⇒ String 
    See IO#pread.
# File 'ext/stringio/stringio.c', line 1641
static VALUE
strio_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 (offset >= RSTRING_LEN(ptr->string)) {
	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;
}
  #putc(obj) ⇒ Object
See IO#putc.
# File 'ext/stringio/stringio.c', line 1531
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)) {
	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;
}
  
    #read([length [, outbuf]])  ⇒ String, ...   
See IO#read.
# File 'ext/stringio/stringio.c', line 1565
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 &&
		(NIL_P(ptr->string) || ptr->pos >= RSTRING_LEN(ptr->string))) {
		if (!NIL_P(str)) rb_str_resize(str, 0);
		return Qnil;
	    }
	    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;
}
  
    
      #readlines(sep = $/, chomp: false)  ⇒ Array 
      #readlines(limit, chomp: false)  ⇒ Array 
      #readlines(sep, limit, chomp: false)  ⇒ Array 
    
  
Array 
      #readlines(limit, chomp: false)  ⇒ Array 
      #readlines(sep, limit, chomp: false)  ⇒ Array 
    See IO#readlines.
# File 'ext/stringio/stringio.c', line 1415
static VALUE
strio_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;
}
  
    #reopen(other, mode = 'r+')  ⇒ self   
# File 'ext/stringio/stringio.c', line 732
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);
}
  
    #rewind  ⇒ 0   
Sets the current position and line number to zero; see Position and Line Number.
# File 'ext/stringio/stringio.c', line 782
static VALUE
strio_rewind(VALUE self)
{
    struct StringIO *ptr = StringIO(self);
    ptr->pos = 0;
    ptr->lineno = 0;
    return INT2FIX(0);
}
  
    #seek(offset, whence = SEEK_SET)  ⇒ 0   
Sets the current position to the given integer offset (in bytes), with respect to a given constant whence; see Position.
# File 'ext/stringio/stringio.c', line 799
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);
}
  
    #set_encoding(ext_enc, [int_enc[, opt]])  ⇒ strio   
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.
# File 'ext/stringio/stringio.c', line 1836
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_find_encoding(ext_enc);
	if (!enc) {
	    rb_io_enc_t convconfig;
	    int oflags, 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)) {
	rb_enc_associate(ptr->string, enc);
    }
    return self;
}
  
    #set_encoding_by_bom  ⇒ strio?   
Sets the encoding according to the BOM (Byte Order Mark) in the string.
Returns self if the BOM is found, otherwise +nil.
# File 'ext/stringio/stringio.c', line 1875
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);
}
  
    
      #length  ⇒ Integer 
      #size  ⇒ Integer 
    
  
Integer 
      #size  ⇒ Integer 
    Alias for #length.
    #sync  ⇒ true   
Returns true; implemented only for compatibility with other stream classes.
# File 'ext/stringio/stringio.c', line 837
static VALUE
strio_get_sync(VALUE self)
{
    StringIO(self);
    return Qtrue;
}
  #sync=
[ GitHub ]#tell
[ GitHub ]
    #truncate(integer)  ⇒ 0   
Truncates the buffer string to at most integer bytes. The stream must be opened for writing.
# File 'ext/stringio/stringio.c', line 1778
static VALUE
strio_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);
}
  
    #ungetbyte(byte)  ⇒ nil   
Pushes back (“unshifts”) an 8-bit byte onto the stream; see Byte IO.
# File 'ext/stringio/stringio.c', line 994
static VALUE
strio_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;
}
  
    #ungetc(character)  ⇒ nil   
Pushes back (“unshifts”) a character or integer onto the stream; see Character IO.
# File 'ext/stringio/stringio.c', line 952
static VALUE
strio_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;
    }
}
  
    
      #write(string, ...)  ⇒ Integer 
      #syswrite(string)  ⇒ Integer 
    
  
Integer 
      #syswrite(string)  ⇒ Integer 
    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.
# File 'ext/stringio/stringio.c', line 1443
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);
}