StringIO 類別

類似於 IO 的字串 IO 串流,存取方式請參閱 IO

關於範例

此頁面的範例假設已載入 StringIO

require 'stringio'

常數

VERSION

公開類別方法

new(string = '', mode = 'r+') → new_stringio 按一下以切換來源

請注意,如果 string 已凍結,mode 預設為 'r'

傳回由 stringmode 組成的新的 StringIO 實例;請參閱 存取模式

strio = StringIO.new # => #<StringIO>
strio.close

不再需要時,應關閉實例。

相關:StringIO.open(接受區塊;自動關閉)。

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);
}
open(string = '', mode = 'r+') {|strio| ... } 按一下以切換來源

請注意,如果 string 已凍結,mode 預設為 'r'

stringmode 建立新的 StringIO 實例;請參閱 存取模式

沒有區塊時,傳回新的實例

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

有區塊時,呼叫區塊並傳回區塊的值;區塊結束時關閉實例。

StringIO.open {|strio| p strio }
# => #<StringIO>

相關:StringIO.new

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);
}

公開實例方法

binmode → self 按一下以切換來源

self 中的資料模式設定為二進位模式;請參閱 資料模式

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 按一下以切換來源

關閉 self 以進行讀取和寫入。

如果嘗試讀取或寫入,會引發 IOError

相關:StringIO#close_readStringIO#close_write

static VALUE
strio_close(VALUE self)
{
    StringIO(self);
    RBASIC(self)->flags &= ~STRIO_READWRITE;
    return Qnil;
}
close_read → nil 按一下以切換來源

關閉 self 以進行讀取;關閉寫入設定保持不變。

如果嘗試讀取,會引發 IOError

相關:StringIO#closeStringIO#close_write

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 按一下以切換來源

關閉 self 以進行寫入;關閉讀取設定保持不變。

如果嘗試寫入,會引發 IOError

相關:StringIO#closeStringIO#close_read

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;
}
closed? → true 或 false 按一下以切換來源

如果 self 已關閉以進行讀取和寫入,傳回 true,否則傳回 false

static VALUE
strio_closed(VALUE self)
{
    StringIO(self);
    if (!CLOSED(self)) return Qfalse;
    return Qtrue;
}
closed_read? → true 或 false 按一下以切換來源

如果 self 已關閉以進行讀取,傳回 true,否則傳回 false

static VALUE
strio_closed_read(VALUE self)
{
    StringIO(self);
    if (READABLE(self)) return Qfalse;
    return Qtrue;
}
closed_write? → true 或 false 按一下以切換來源

如果 self 已關閉寫入,傳回 true,否則傳回 false

static VALUE
strio_closed_write(VALUE self)
{
    StringIO(self);
    if (WRITABLE(self)) return Qfalse;
    return Qtrue;
}
each
別名:each_line
each_byte {|byte| ... } → self 按一下以切換來源

如果提供區塊,會呼叫區塊並傳入串流中每個剩餘的位元組;請參閱 位元組 IO

如果未提供區塊,會傳回列舉器。

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 按一下以切換來源

如果提供區塊,會呼叫區塊並傳入串流中每個剩餘的字元;請參閱 字元 IO

如果未提供區塊,會傳回列舉器。

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 按一下以切換來源

如果提供區塊,會呼叫區塊並傳入串流中每個剩餘的碼點;請參閱 碼點 IO

如果未提供區塊,會傳回列舉器。

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。請參閱 行 IO

別名:each
eof
別名:eof?
eof? → true 或 false

如果已定位到串流結尾,傳回 true,否則傳回 false;請參閱 位置

如果未開啟串流以進行讀取,會引發 IOError

別名:eof
external_encoding → encoding 按一下以切換來源

傳回代表檔案編碼的 Encoding 物件。如果串流為寫入模式且未指定編碼,會傳回 nil

static VALUE
strio_external_encoding(VALUE self)
{
    struct StringIO *ptr = StringIO(self);
    return rb_enc_from_encoding(get_enc(ptr));
}
fcntl(*args) 按一下以切換來源

引發 NotImplementedError

static VALUE
strio_unimpl(int argc, VALUE *argv, VALUE self)
{
    StringIO(self);
    rb_notimplement();

    UNREACHABLE;
}
fileno() 按一下以切換來源

傳回 nil。僅與 IO 相容。

static VALUE
strio_nil(VALUE self)
{
    StringIO(self);
    return Qnil;
}
flush() 按一下以切換原始碼

傳回物件本身。僅為了與 IO 相容。

static VALUE
strio_self(VALUE self)
{
    StringIO(self);
    return self;
}
fsync() 按一下以切換原始碼

傳回 0。僅為了與 IO 相容。

static VALUE
strio_0(VALUE self)
{
    StringIO(self);
    return INT2FIX(0);
}
getbyte → 位元組或 nil 按一下以切換原始碼

從串流中讀取並傳回下一個 8 位元組位元組;請參閱 位元組 IO

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);
}
getc → 字元或 nil 按一下以切換原始碼

從串流中讀取並傳回下一個字元;請參閱 字元 IO

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);
}
gets(sep = $/, chomp: false) → 字串或 nil 按一下以切換原始碼
gets(limit, chomp: false) → 字串或 nil
gets(sep, limit, chomp: false) → 字串或 nil

從串流中讀取並傳回一行;將傳回值指定給 $_;請參閱 行 IO

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) {
        return rb_enc_str_new(0, 0, get_enc(ptr));
    }

    str = strio_getline(&arg, ptr);
    rb_lastline_set(str);
    return str;
}
internal_encoding → 編碼 按一下以切換原始碼

如果指定轉換,則傳回內部字串的 編碼。否則傳回 nil

static VALUE
strio_internal_encoding(VALUE self)
{
    return Qnil;
}
isatty() 按一下以切換原始碼

傳回 false。僅為了與 IO 相容。

static VALUE
strio_false(VALUE self)
{
    StringIO(self);
    return Qfalse;
}
別名為: tty?
length → 整數

傳回緩衝區字串的大小。

別名為: size
lineno → 目前行號 按一下以切換原始碼

傳回 self 中的目前行號;請參閱 行號

static VALUE
strio_get_lineno(VALUE self)
{
    return LONG2NUM(StringIO(self)->lineno);
}
lineno = new_line_number → new_line_number 按一下以切換原始碼

self 中的目前行號設定為指定的 new_line_number;請參閱 行號

static VALUE
strio_set_lineno(VALUE self, VALUE lineno)
{
    StringIO(self)->lineno = NUM2LONG(lineno);
    return lineno;
}
pid() 按一下以切換原始碼

傳回 nil。僅與 IO 相容。

static VALUE
strio_nil(VALUE self)
{
    StringIO(self);
    return Qnil;
}
pos → stream_position 按一下以切換來源

傳回目前位置(以位元組為單位);請參閱 位置

static VALUE
strio_get_pos(VALUE self)
{
    return LONG2NUM(StringIO(self)->pos);
}
pos = new_position → new_position 按一下以切換來源

設定目前位置(以位元組為單位);請參閱 位置

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;
}
pread(maxlen, offset) → string 按一下以切換來源
pread(maxlen, offset, out_string) → string

請參閱 IO#pread

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) → obj 按一下以切換來源

請參閱 IO#putc

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;
}
read([length [, outbuf]]) → string, outbuf, or nil 按一下以切換來源

請參閱 IO#read

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;
}
readlines(sep=$/, chomp: false) → array 按一下以切換來源
readlines(limit, chomp: false) → array
readlines(sep, limit, chomp: false) → array

請參閱 IO#readlines

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 按一下以切換來源

使用指定的 other(字串或 StringIO)和 mode 重新初始化串流;請參閱 IO.new

StringIO.open('foo') do |strio|
  p strio.string
  strio.reopen('bar')
  p strio.string
  other_strio = StringIO.new('baz')
  strio.reopen(other_strio)
  p strio.string
  other_strio.close
end

輸出

"foo"
"bar"
"baz"
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 按一下以切換來源

將目前位置和行號設定為零;請參閱 位置行號

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 按一下以切換來源

將目前位置設定為指定的整數 offset(以位元組為單位),相對於指定的常數 whence;請參閱 位置

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 按一下以切換來源

StringIO 的編碼指定為 ext_enc。如果 ext_enc 為 nil,請使用預設外部編碼。會忽略第 2 個參數 int_enc 和選用雜湊 opt 參數;它們是為了與 IO 的 API 相容。

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 (WRITABLE(self)) {
        rb_enc_associate(ptr->string, enc);
    }

    return self;
}
set_encoding_by_bom() 按一下以切換原始碼
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 → 整數 按一下以切換原始碼

傳回緩衝區字串的大小。

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));
}
別名為:length
字串 → 字串 按一下以切換原始碼

傳回底層字串

StringIO.open('foo') do |strio|
  p strio.string
  strio.string = 'bar'
  p strio.string
end

輸出

"foo"
"bar"

相關:StringIO#string=(指定底層字串)。

static VALUE
strio_get_string(VALUE self)
{
    return StringIO(self)->string;
}
string = other_string → other_string 按一下以切換原始碼

將底層字串指定為 other_string,並將位置設定為零;傳回 other_string

StringIO.open('foo') do |strio|
  p strio.string
  strio.string = 'bar'
  p strio.string
end

輸出

"foo"
"bar"

相關:StringIO#string(傳回底層字串)。

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;
    RB_OBJ_WRITE(self, &ptr->string, string);
    return string;
}
sync → true 按一下以切換原始碼

傳回 true;僅為與其他串流類別相容而實作。

static VALUE
strio_get_sync(VALUE self)
{
    StringIO(self);
    return Qtrue;
}
sync=(p1) 按一下以切換原始碼

傳回未變更的引數。僅為與 IO 相容。

static VALUE
strio_first(VALUE self, VALUE arg)
{
    StringIO(self);
    return arg;
}
pos → stream_position 按一下以切換來源

傳回目前位置(以位元組為單位);請參閱 位置

static VALUE
strio_get_pos(VALUE self)
{
    return LONG2NUM(StringIO(self)->pos);
}
truncate(integer) → 0 按一下以切換原始碼

將緩衝區字串截斷為最多 integer 位元組。串流必須開啟為寫入模式。

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 INT2FIX(0);
}
tty?()

傳回 false。僅為了與 IO 相容。

別名為:isatty
ungetbyte(byte) → nil 按一下以切換原始碼

將 8 位元組位元組推回(「取消位移」)到串流上;請參閱 位元組 IO

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;
}
ungetc(character) → nil 按一下以切換原始碼

將字元或整數推回(「取消位移」)到串流上;請參閱 字元 IO

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;
    }
}
write(string, ...) → integer 按一下以切換原始碼
syswrite(string) → integer

將指定的字串附加到底層緩衝區字串。串流必須開啟為寫入模式。如果引數不是字串,它將使用 to_s 轉換為字串。傳回寫入的位元組數。請參閱 IO#write

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);
}