From 3e1c01ae463a8c9d8bbe9050251a2538ddb0292f Mon Sep 17 00:00:00 2001 From: nobu Date: Fri, 18 Dec 2015 07:54:33 +0000 Subject: stringio.c: separate encoding from buffer * ext/stringio/stringio.c (strio_set_encoding): add StringIO's own encoding and separate it from the buffer string to override the encoding of string when reading. [ruby-core:72189] [Bug #11827] note that setting the encoding of its buffer string may cause unpredictable behavior. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53188 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/stringio/stringio.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'ext/stringio') diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c index 28e629599f..3a14716fef 100644 --- a/ext/stringio/stringio.c +++ b/ext/stringio/stringio.c @@ -22,6 +22,7 @@ struct StringIO { VALUE string; + rb_encoding *enc; long pos; long lineno; int flags; @@ -33,6 +34,7 @@ static VALUE strio_unget_bytes(struct StringIO *, const char *, long); #define IS_STRIO(obj) (rb_typeddata_is_kind_of((obj), &strio_data_type)) #define error_inval(msg) (errno = EINVAL, rb_sys_fail(msg)) +#define get_enc(ptr) ((ptr)->enc ? (ptr)->enc : rb_enc_get((ptr)->string)) static struct StringIO * strio_alloc(void) @@ -97,7 +99,7 @@ static VALUE strio_substr(struct StringIO *ptr, long pos, long len) { VALUE str = ptr->string; - rb_encoding *enc = rb_enc_get(str); + rb_encoding *enc = get_enc(ptr); long rlen = RSTRING_LEN(str) - pos; if (len > rlen) len = rlen; @@ -210,6 +212,7 @@ strio_init(int argc, VALUE *argv, struct StringIO *ptr, VALUE self) break; } ptr->string = string; + ptr->enc = 0; ptr->pos = 0; ptr->lineno = 0; RBASIC(self)->flags |= (ptr->flags & FMODE_READWRITE) * (STRIO_READABLE / FMODE_READABLE); @@ -663,7 +666,7 @@ static VALUE strio_getc(VALUE self) { struct StringIO *ptr = readable(self); - rb_encoding *enc = rb_enc_get(ptr->string); + rb_encoding *enc = get_enc(ptr); int len; char *p; @@ -673,7 +676,7 @@ strio_getc(VALUE self) p = RSTRING_PTR(ptr->string)+ptr->pos; len = rb_enc_mbclen(p, RSTRING_END(ptr->string), enc); ptr->pos += len; - return rb_enc_str_new(p, len, rb_enc_get(ptr->string)); + return rb_enc_str_new(p, len, enc); } /* @@ -888,7 +891,7 @@ strio_each_codepoint(VALUE self) RETURN_ENUMERATOR(self, 0, 0); ptr = readable(self); - enc = rb_enc_get(ptr->string); + enc = get_enc(ptr); for (;;) { if (ptr->pos >= RSTRING_LEN(ptr->string)) { return self; @@ -987,7 +990,7 @@ strio_getline(int argc, VALUE *argv, struct StringIO *ptr) e = s + RSTRING_LEN(ptr->string); s += ptr->pos; if (limit > 0 && s + limit < e) { - e = rb_enc_right_char_head(s, s + limit, e, rb_enc_get(ptr->string)); + e = rb_enc_right_char_head(s, s + limit, e, get_enc(ptr)); } if (NIL_P(str)) { str = strio_substr(ptr, ptr->pos, e - s); @@ -1164,7 +1167,7 @@ strio_write(VALUE self, VALUE str) if (!RB_TYPE_P(str, T_STRING)) str = rb_obj_as_string(str); - enc = rb_enc_get(ptr->string); + enc = get_enc(ptr); enc2 = rb_enc_get(str); if (enc != enc2 && enc != ascii8bit) { str = rb_str_conv_enc(str, enc2, enc); @@ -1439,7 +1442,8 @@ strio_truncate(VALUE self, VALUE len) static VALUE strio_external_encoding(VALUE self) { - return rb_enc_from_encoding(rb_enc_get(StringIO(self)->string)); + struct StringIO *ptr = StringIO(self); + return rb_enc_from_encoding(get_enc(ptr)); } /* @@ -1470,7 +1474,7 @@ static VALUE strio_set_encoding(int argc, VALUE *argv, VALUE self) { rb_encoding* enc; - VALUE str = StringIO(self)->string; + struct StringIO *ptr = StringIO(self); VALUE ext_enc, int_enc, opt; argc = rb_scan_args(argc, argv, "11:", &ext_enc, &int_enc, &opt); @@ -1481,7 +1485,11 @@ strio_set_encoding(int argc, VALUE *argv, VALUE self) else { enc = rb_to_encoding(ext_enc); } - rb_enc_associate(str, enc); + ptr->enc = enc; + if (WRITABLE(self)) { + rb_enc_associate(ptr->string, enc); + } + return self; } -- cgit v1.2.3