summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--ext/stringio/stringio.c60
2 files changed, 51 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index 227f9d20cd..7e9ee66052 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Thu Mar 14 12:32:59 2002 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * ext/stringio/stringio.c: fixed frozen string bug. ungetc no
+ longer raises on readonly stream unless modifies actually.
+
Thu Mar 14 08:57:41 2002 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
* dir.c (rb_push_glob): avoid SEGV when a block given.
diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c
index c3bf916657..25122dd1b5 100644
--- a/ext/stringio/stringio.c
+++ b/ext/stringio/stringio.c
@@ -4,6 +4,7 @@
$Author$
$Date$
+ $RoughId: stringio.c,v 1.13 2002/03/14 03:24:18 nobu Exp $
created at: Tue Feb 19 04:10:38 JST 2002
All the files in this distribution are covered under the Ruby's
@@ -89,11 +90,15 @@ get_strio(self)
#define StringIO(obj) get_strio(obj)
+#define CLOSED(ptr) NIL_P((ptr)->string)
+#define READABLE(ptr) (!CLOSED(ptr) && ((ptr)->flags & FMODE_READABLE))
+#define WRITABLE(ptr) (!CLOSED(ptr) && ((ptr)->flags & FMODE_WRITABLE))
+
static struct StringIO*
readable(ptr)
struct StringIO *ptr;
{
- if (NIL_P(ptr->string) || !(ptr->flags & FMODE_READABLE)) {
+ if (!READABLE(ptr)) {
rb_raise(rb_eIOError, "not opened for reading");
}
return ptr;
@@ -103,7 +108,7 @@ static struct StringIO*
writable(ptr)
struct StringIO *ptr;
{
- if (NIL_P(ptr->string) || !(ptr->flags & FMODE_WRITABLE)) {
+ if (!WRITABLE(ptr)) {
rb_raise(rb_eIOError, "not opened for writing");
}
if (!OBJ_TAINTED(ptr->string)) {
@@ -112,6 +117,16 @@ writable(ptr)
return ptr;
}
+static struct StringIO*
+check_modifiable(ptr)
+ struct StringIO *ptr;
+{
+ if (OBJ_FROZEN(ptr->string)) {
+ rb_raise(rb_eIOError, "not modifiable string");
+ }
+ rb_str_modify(ptr->string);
+}
+
static VALUE strio_s_allocate _((VALUE));
static VALUE strio_s_open _((int, VALUE *, VALUE));
static VALUE strio_initialize _((int, VALUE *, VALUE));
@@ -199,6 +214,10 @@ strio_initialize(argc, argv, self)
StringValue(mode);
StringValue(string);
ptr->flags = rb_io_mode_flags(RSTRING(mode)->ptr);
+ if (ptr->flags & FMODE_WRITABLE && OBJ_FROZEN(string)) {
+ errno = EACCES;
+ rb_sys_fail(0);
+ }
switch (*RSTRING(mode)->ptr) {
case 'a':
ptr->flags |= STRIO_APPEND;
@@ -210,7 +229,7 @@ strio_initialize(argc, argv, self)
break;
case 1:
StringValue(string);
- ptr->flags = FMODE_READWRITE;
+ ptr->flags = OBJ_FROZEN(string) ? FMODE_READABLE : FMODE_READWRITE;
break;
case 0:
string = rb_str_new("", 0);
@@ -310,7 +329,7 @@ strio_close(self)
VALUE self;
{
struct StringIO *ptr = StringIO(self);
- if (NIL_P(ptr->string)) {
+ if (CLOSED(ptr)) {
rb_raise(rb_eIOError, "closed stream");
}
ptr->string = Qnil;
@@ -322,7 +341,10 @@ static VALUE
strio_close_read(self)
VALUE self;
{
- struct StringIO *ptr = readable(StringIO(self));
+ struct StringIO *ptr = StringIO(self);
+ if (!READABLE(ptr)) {
+ rb_raise(rb_eIOError, "closing non-duplex IO for reading");
+ }
if (!((ptr->flags &= ~FMODE_READABLE) & FMODE_READWRITE)) {
ptr->string = Qnil;
}
@@ -333,7 +355,10 @@ static VALUE
strio_close_write(self)
VALUE self;
{
- struct StringIO *ptr = writable(StringIO(self));
+ struct StringIO *ptr = StringIO(self);
+ if (!WRITABLE(ptr)) {
+ rb_raise(rb_eIOError, "closing non-duplex IO for writing");
+ }
if (!((ptr->flags &= ~FMODE_WRITABLE) & FMODE_READWRITE)) {
ptr->string = Qnil;
}
@@ -345,7 +370,7 @@ strio_closed(self)
VALUE self;
{
struct StringIO *ptr = StringIO(self);
- if (!NIL_P(ptr->string)) return Qfalse;
+ if (!CLOSED(ptr)) return Qfalse;
return Qtrue;
}
@@ -354,7 +379,7 @@ strio_closed_read(self)
VALUE self;
{
struct StringIO *ptr = StringIO(self);
- if (ptr->flags & FMODE_READABLE) return Qfalse;
+ if (READABLE(ptr)) return Qfalse;
return Qtrue;
}
@@ -363,7 +388,7 @@ strio_closed_write(self)
VALUE self;
{
struct StringIO *ptr = StringIO(self);
- if (ptr->flags & FMODE_WRITABLE) return Qfalse;
+ if (WRITABLE(ptr)) return Qfalse;
return Qtrue;
}
@@ -371,9 +396,7 @@ static VALUE
strio_eof(self)
VALUE self;
{
- struct StringIO *ptr = StringIO(self);
- if (!(ptr->flags & FMODE_READABLE)) return Qtrue;
- if (NIL_P(ptr->string)) return Qtrue;
+ struct StringIO *ptr = readable(StringIO(self));
if (ptr->pos < RSTRING(ptr->string)->len) return Qfalse;
return Qtrue;
}
@@ -521,8 +544,11 @@ strio_ungetc(self, ch)
int cc = NUM2INT(ch);
if (cc != EOF && ptr->pos > 0) {
- rb_str_modify(ptr->string);
- RSTRING(ptr->string)->ptr[--ptr->pos] = cc;
+ if ((unsigned char)RSTRING(ptr->string)->ptr[--ptr->pos] !=
+ (unsigned char)cc) {
+ check_modifiable(ptr);
+ RSTRING(ptr->string)->ptr[ptr->pos] = cc;
+ }
}
return Qnil;
}
@@ -708,6 +734,8 @@ strio_write(self, str)
if (TYPE(str) != T_STRING)
str = rb_obj_as_string(str);
len = RSTRING(str)->len;
+ if (!len) return INT2FIX(0);
+ check_modifiable(ptr);
if (ptr->flags & STRIO_APPEND) {
ptr->pos = RSTRING(ptr->string)->len;
}
@@ -732,6 +760,10 @@ strio_putc(self, ch)
struct StringIO *ptr = writable(StringIO(self));
int c = NUM2CHR(ch);
+ check_modifiable(ptr);
+ if (ptr->flags & STRIO_APPEND) {
+ ptr->pos = RSTRING(ptr->string)->len;
+ }
if (ptr->pos >= RSTRING(ptr->string)->len) {
rb_str_resize(ptr->string, ptr->pos + 1);
}