aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-12-18 03:09:16 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-12-18 03:09:16 +0000
commit28f3a7e3d5da9cbb00a75d29dcacce3a82d2b975 (patch)
tree3017b951de574832fc145ff7773322f739bc114c
parente735475f54eb9ce035b7d8acef901c0bd7a4b483 (diff)
downloadruby-28f3a7e3d5da9cbb00a75d29dcacce3a82d2b975.tar.gz
stringio.c: padding in ungetbyte
* ext/stringio/stringio.c (strio_ungetbyte): pad with \000 when the current position is after the end. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53181 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog5
-rw-r--r--ext/stringio/stringio.c22
-rw-r--r--test/stringio/test_stringio.rb30
3 files changed, 50 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index ed442c63dc..b79c3d1bc5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Fri Dec 18 12:09:21 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/stringio/stringio.c (strio_ungetbyte): pad with \000 when
+ the current position is after the end.
+
Fri Dec 18 11:24:48 2015 Shugo Maeda <shugo@ruby-lang.org>
* vm_method.c (rb_method_entry_make, check_override_opt_method):
diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c
index 7c2c51dca8..23d7deba02 100644
--- a/ext/stringio/stringio.c
+++ b/ext/stringio/stringio.c
@@ -780,8 +780,9 @@ strio_ungetbyte(VALUE self, VALUE c)
{
struct StringIO *ptr = readable(self);
char buf[1], *cp = buf;
- long pos = ptr->pos, cl = 1;
+ long pos = ptr->pos, cl = 1, len, rest;
VALUE str = ptr->string;
+ char *s;
if (NIL_P(c)) return Qnil;
if (FIXNUM_P(c)) {
@@ -794,19 +795,26 @@ strio_ungetbyte(VALUE self, VALUE c)
if (cl == 0) return Qnil;
}
check_modifiable(ptr);
- rb_str_modify(str);
+ len = RSTRING_LEN(str);
+ rest = pos - len;
if (cl > pos) {
- char *s;
- long rest = RSTRING_LEN(str) - pos;
- rb_str_resize(str, rest + cl);
+ long ex = (rest < 0 ? cl-pos : cl+rest);
+ rb_str_modify_expand(str, ex);
+ rb_str_set_len(str, len + ex);
s = RSTRING_PTR(str);
- memmove(s + cl, s + pos, rest);
+ if (rest < 0) memmove(s + cl, s + pos, -rest);
pos = 0;
}
else {
+ if (rest > 0) {
+ rb_str_modify_expand(str, rest);
+ rb_str_set_len(str, len + rest);
+ }
+ s = RSTRING_PTR(str);
+ if (rest > cl) memset(s + len, 0, rest - cl);
pos -= cl;
}
- memcpy(RSTRING_PTR(str) + pos, cp, cl);
+ memcpy(s + pos, cp, cl);
ptr->pos = pos;
RB_GC_GUARD(c);
return Qnil;
diff --git a/test/stringio/test_stringio.rb b/test/stringio/test_stringio.rb
index af6efc684e..7b99d62f51 100644
--- a/test/stringio/test_stringio.rb
+++ b/test/stringio/test_stringio.rb
@@ -362,6 +362,11 @@ class TestStringIO < Test::Unit::TestCase
t.ungetbyte("\xe7")
t.ungetbyte("\xe7\xb4\x85")
assert_equal("\u7d05\u7389bar\n", t.gets)
+ assert_equal("q\u7d05\u7389bar\n", s)
+ t.pos = 1
+ t.ungetbyte("\u{30eb 30d3 30fc}")
+ assert_equal(0, t.pos)
+ assert_equal("\u{30eb 30d3 30fc}\u7d05\u7389bar\n", s)
end
def test_ungetc
@@ -582,6 +587,31 @@ class TestStringIO < Test::Unit::TestCase
assert_equal("b""\0""a", s.string)
end
+ def test_ungetbyte_pos
+ b = '\\b00010001 \\B00010001 \\b1 \\B1 \\b000100011'
+ s = StringIO.new( b )
+ expected_pos = 0
+ while n = s.getbyte
+ assert_equal( expected_pos + 1, s.pos )
+
+ s.ungetbyte( n )
+ assert_equal( expected_pos, s.pos )
+ assert_equal( n, s.getbyte )
+
+ expected_pos += 1
+ end
+ end
+
+ def test_ungetbyte_padding
+ s = StringIO.new()
+ s.pos = 2
+ s.ungetbyte("a".ord)
+ assert_equal("\0""a", s.string)
+ s.pos = 0
+ s.ungetbyte("b".ord)
+ assert_equal("b""\0""a", s.string)
+ end
+
def test_frozen
s = StringIO.new
s.freeze