summaryrefslogtreecommitdiff
path: root/ext/stringio/stringio.c
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
commitb7d153699153629f037a059b930d8e928c42a4a1 (patch)
tree3017b951de574832fc145ff7773322f739bc114c /ext/stringio/stringio.c
parent07f53e483042f8d154912b9414808ad40973cd44 (diff)
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
Diffstat (limited to 'ext/stringio/stringio.c')
-rw-r--r--ext/stringio/stringio.c22
1 files changed, 15 insertions, 7 deletions
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;