summaryrefslogtreecommitdiff
path: root/ext/stringio
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-12-18 06:40:00 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-12-18 06:40:00 +0000
commit21973c01ab5da205aa261cc41d0639642b8aaf15 (patch)
tree1703f5a940c8c82d294cdad05f1bdade6a4bc4b9 /ext/stringio
parenta6e055f4a151a6f6dbbba0cd7231c699ec022ad7 (diff)
stringio.c: strio_unget_bytes
* ext/stringio/stringio.c (strio_unget_bytes): extract from strio_ungetbyte to share with strio_ungetc. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53185 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/stringio')
-rw-r--r--ext/stringio/stringio.c52
1 files changed, 21 insertions, 31 deletions
diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c
index 23d7deb..28e6295 100644
--- a/ext/stringio/stringio.c
+++ b/ext/stringio/stringio.c
@@ -29,6 +29,7 @@ struct StringIO {
};
static void strio_init(int, VALUE *, struct StringIO *, VALUE);
+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))
@@ -723,19 +724,17 @@ static VALUE
strio_ungetc(VALUE self, VALUE c)
{
struct StringIO *ptr = readable(self);
- long lpos, clen;
- char *p, *pend;
rb_encoding *enc, *enc2;
- if (NIL_P(c)) return Qnil;
check_modifiable(ptr);
+ if (NIL_P(c)) return Qnil;
if (FIXNUM_P(c)) {
int cc = FIX2INT(c);
char buf[16];
enc = rb_enc_get(ptr->string);
rb_enc_mbcput(cc, buf, enc);
- c = rb_enc_str_new(buf, rb_enc_codelen(cc, enc), enc);
+ return strio_unget_bytes(ptr, buf, rb_enc_codelen(cc, enc));
}
else {
SafeStringValue(c);
@@ -744,29 +743,10 @@ strio_ungetc(VALUE self, VALUE 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;
}
- if (RSTRING_LEN(ptr->string) < ptr->pos) {
- long len = RSTRING_LEN(ptr->string);
- rb_str_resize(ptr->string, ptr->pos - 1);
- memset(RSTRING_PTR(ptr->string) + len, 0, ptr->pos - len - 1);
- rb_str_concat(ptr->string, c);
- ptr->pos--;
- }
- else {
- /* get logical position */
- lpos = 0; p = RSTRING_PTR(ptr->string); pend = p + ptr->pos;
- for (;;) {
- clen = rb_enc_mbclen(p, pend, enc);
- if (p+clen >= pend) break;
- p += clen;
- lpos++;
- }
- clen = p - RSTRING_PTR(ptr->string);
- rb_str_update(ptr->string, lpos, ptr->pos ? 1 : 0, c);
- ptr->pos = clen;
- }
-
- return Qnil;
}
/*
@@ -780,21 +760,32 @@ strio_ungetbyte(VALUE self, VALUE c)
{
struct StringIO *ptr = readable(self);
char buf[1], *cp = buf;
- long pos = ptr->pos, cl = 1, len, rest;
- VALUE str = ptr->string;
- char *s;
+ long cl = 1;
+ check_modifiable(ptr);
if (NIL_P(c)) return Qnil;
if (FIXNUM_P(c)) {
buf[0] = (char)FIX2INT(c);
+ return strio_unget_bytes(ptr, buf, 1);
}
else {
SafeStringValue(c);
cp = RSTRING_PTR(c);
cl = RSTRING_LEN(c);
if (cl == 0) return Qnil;
+ strio_unget_bytes(ptr, cp, cl);
+ RB_GC_GUARD(c);
+ return Qnil;
}
- check_modifiable(ptr);
+}
+
+static VALUE
+strio_unget_bytes(struct StringIO *ptr, const char *cp, long cl)
+{
+ long pos = ptr->pos, len, rest;
+ VALUE str = ptr->string;
+ char *s;
+
len = RSTRING_LEN(str);
rest = pos - len;
if (cl > pos) {
@@ -816,7 +807,6 @@ strio_ungetbyte(VALUE self, VALUE c)
}
memcpy(s + pos, cp, cl);
ptr->pos = pos;
- RB_GC_GUARD(c);
return Qnil;
}