summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--io.c49
-rw-r--r--test/objspace/test_objspace.rb2
-rw-r--r--test/ruby/test_argf.rb23
3 files changed, 43 insertions, 31 deletions
diff --git a/io.c b/io.c
index 864cf955680..17e33d8cb95 100644
--- a/io.c
+++ b/io.c
@@ -181,7 +181,7 @@ struct argf {
long last_lineno; /* $. */
long lineno;
VALUE argv;
- char *inplace;
+ VALUE inplace;
struct rb_io_enc_t encs;
int8_t init_p, next_p, binmode;
};
@@ -8067,29 +8067,21 @@ argf_mark(void *ptr)
rb_gc_mark(p->filename);
rb_gc_mark(p->current_file);
rb_gc_mark(p->argv);
+ rb_gc_mark(p->inplace);
rb_gc_mark(p->encs.ecopts);
}
-static void
-argf_free(void *ptr)
-{
- struct argf *p = ptr;
- xfree(p->inplace);
- xfree(p);
-}
-
static size_t
argf_memsize(const void *ptr)
{
const struct argf *p = ptr;
size_t size = sizeof(*p);
- if (p->inplace) size += strlen(p->inplace) + 1;
return size;
}
static const rb_data_type_t argf_type = {
"ARGF",
- {argf_mark, argf_free, argf_memsize},
+ {argf_mark, RUBY_TYPED_DEFAULT_FREE, argf_memsize},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};
@@ -8131,11 +8123,6 @@ argf_initialize_copy(VALUE argf, VALUE orig)
if (!OBJ_INIT_COPY(argf, orig)) return argf;
ARGF = argf_of(orig);
ARGF.argv = rb_obj_dup(ARGF.argv);
- if (ARGF.inplace) {
- const char *inplace = ARGF.inplace;
- ARGF.inplace = 0;
- ARGF.inplace = ruby_strdup(inplace);
- }
return argf;
}
@@ -8278,10 +8265,14 @@ argf_next_argv(VALUE argf)
}
fstat(fr, &st);
str = filename;
- if (*ARGF.inplace) {
+ if (!NIL_P(ARGF.inplace)) {
+ VALUE suffix = ARGF.inplace;
str = rb_str_dup(str);
- rb_str_cat2(str, ARGF.inplace);
- /* TODO: encoding of ARGF.inplace */
+ if (NIL_P(rb_str_cat_conv_enc_opts(str, RSTRING_LEN(str),
+ RSTRING_PTR(suffix), RSTRING_LEN(suffix),
+ rb_enc_get(suffix), 0, Qnil))) {
+ rb_str_append(str, suffix);
+ }
#ifdef NO_SAFE_RENAME
(void)close(fr);
(void)unlink(RSTRING_PTR(str));
@@ -12191,7 +12182,8 @@ static VALUE
argf_inplace_mode_get(VALUE argf)
{
if (!ARGF.inplace) return Qnil;
- return rb_str_new2(ARGF.inplace);
+ if (NIL_P(ARGF.inplace)) return rb_str_new(0, 0);
+ return rb_str_dup(ARGF.inplace);
}
static VALUE
@@ -12227,14 +12219,13 @@ argf_inplace_mode_set(VALUE argf, VALUE val)
rb_insecure_operation();
if (!RTEST(val)) {
- if (ARGF.inplace) free(ARGF.inplace);
- ARGF.inplace = 0;
+ ARGF.inplace = Qfalse;
+ }
+ else if (StringValueCStr(val), !RSTRING_LEN(val)) {
+ ARGF.inplace = Qnil;
}
else {
- const char *suffix = StringValueCStr(val);
- if (ARGF.inplace) free(ARGF.inplace);
- ARGF.inplace = 0;
- ARGF.inplace = strdup(suffix);
+ ARGF.inplace = rb_str_new_frozen(val);
}
return argf;
}
@@ -12248,15 +12239,13 @@ opt_i_set(VALUE val, ID id, VALUE *var)
const char *
ruby_get_inplace_mode(void)
{
- return ARGF.inplace;
+ return RSTRING_PTR(ARGF.inplace);
}
void
ruby_set_inplace_mode(const char *suffix)
{
- if (ARGF.inplace) free(ARGF.inplace);
- ARGF.inplace = 0;
- if (suffix) ARGF.inplace = strdup(suffix);
+ ARGF.inplace = !suffix ? Qfalse : !*suffix ? Qnil : rb_fstring_cstr(suffix);
}
/*
diff --git a/test/objspace/test_objspace.rb b/test/objspace/test_objspace.rb
index 9c706f2736c..0e1ad327b9d 100644
--- a/test/objspace/test_objspace.rb
+++ b/test/objspace/test_objspace.rb
@@ -45,7 +45,7 @@ class TestObjSpace < Test::Unit::TestCase
argf.inplace_mode = nil
size = ObjectSpace.memsize_of(argf)
argf.inplace_mode = "inplace_mode_suffix"
- assert_equal(size + 20, ObjectSpace.memsize_of(argf))
+ assert_equal(size, ObjectSpace.memsize_of(argf))
end
def test_memsize_of_all
diff --git a/test/ruby/test_argf.rb b/test/ruby/test_argf.rb
index 26fe16061ea..311469aad95 100644
--- a/test/ruby/test_argf.rb
+++ b/test/ruby/test_argf.rb
@@ -344,6 +344,29 @@ class TestArgf < Test::Unit::TestCase
$stdout = stdout
end
+ def test_inplace_suffix_encoding
+ base = "argf-\u{30c6 30b9 30c8}"
+ name = "#{@tmpdir}/#{base}"
+ suffix = "-bak"
+ File.write(name, "foo")
+ stdout = $stdout
+ argf = ARGF.class.new(name)
+ argf.inplace_mode = suffix.encode(Encoding::UTF_16LE)
+ begin
+ argf.each do |s|
+ puts "+"+s
+ end
+ ensure
+ $stdout.close unless $stdout == stdout
+ $stdout = stdout
+ end
+ assert_file.exist?(name)
+ assert_equal("+foo\n", File.read(name))
+ assert_file.not_exist?(name+"-")
+ assert_file.exist?(name+suffix)
+ assert_equal("foo", File.read(name+suffix))
+ end
+
def test_encoding
ruby('-e', "#{<<~"{#"}\n#{<<~'};'}", @t1.path, @t2.path, @t3.path) do |f|
{#