[ruby/stringio] Eagerly defrost chilled strings
[Feature #20390] https://github.com/ruby/stringio/commit/17ee957f34 Co-authored-by: Jean Boussier <byroot@ruby-lang.org>
This commit is contained in:
parent
db5686a8ba
commit
0f5ab4ad52
@ -15,6 +15,8 @@
|
|||||||
static const char *const
|
static const char *const
|
||||||
STRINGIO_VERSION = "3.1.1";
|
STRINGIO_VERSION = "3.1.1";
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "ruby.h"
|
#include "ruby.h"
|
||||||
#include "ruby/io.h"
|
#include "ruby/io.h"
|
||||||
#include "ruby/encoding.h"
|
#include "ruby/encoding.h"
|
||||||
@ -49,6 +51,13 @@ static long strio_write(VALUE self, VALUE str);
|
|||||||
#define IS_STRIO(obj) (rb_typeddata_is_kind_of((obj), &strio_data_type))
|
#define IS_STRIO(obj) (rb_typeddata_is_kind_of((obj), &strio_data_type))
|
||||||
#define error_inval(msg) (rb_syserr_fail(EINVAL, msg))
|
#define error_inval(msg) (rb_syserr_fail(EINVAL, msg))
|
||||||
#define get_enc(ptr) ((ptr)->enc ? (ptr)->enc : !NIL_P((ptr)->string) ? rb_enc_get((ptr)->string) : NULL)
|
#define get_enc(ptr) ((ptr)->enc ? (ptr)->enc : !NIL_P((ptr)->string) ? rb_enc_get((ptr)->string) : NULL)
|
||||||
|
#ifndef HAVE_RB_STR_CHILLED_P
|
||||||
|
static bool
|
||||||
|
rb_str_chilled_p(VALUE str)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct StringIO *
|
static struct StringIO *
|
||||||
strio_alloc(void)
|
strio_alloc(void)
|
||||||
@ -166,8 +175,14 @@ writable(VALUE strio)
|
|||||||
static void
|
static void
|
||||||
check_modifiable(struct StringIO *ptr)
|
check_modifiable(struct StringIO *ptr)
|
||||||
{
|
{
|
||||||
if (OBJ_FROZEN(ptr->string)) {
|
if (NIL_P(ptr->string)) {
|
||||||
rb_raise(rb_eIOError, "not modifiable string");
|
/* Null device StringIO */
|
||||||
|
}
|
||||||
|
else if (rb_str_chilled_p(ptr->string)) {
|
||||||
|
rb_str_modify(ptr->string);
|
||||||
|
}
|
||||||
|
else if (OBJ_FROZEN_RAW(ptr->string)) {
|
||||||
|
rb_raise(rb_eIOError, "not modifiable string");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,7 +302,8 @@ strio_init(int argc, VALUE *argv, struct StringIO *ptr, VALUE self)
|
|||||||
else if (!argc) {
|
else if (!argc) {
|
||||||
string = rb_enc_str_new("", 0, rb_default_external_encoding());
|
string = rb_enc_str_new("", 0, rb_default_external_encoding());
|
||||||
}
|
}
|
||||||
if (!NIL_P(string) && OBJ_FROZEN_RAW(string)) {
|
|
||||||
|
if (!NIL_P(string) && OBJ_FROZEN_RAW(string) && !rb_str_chilled_p(string)) {
|
||||||
if (ptr->flags & FMODE_WRITABLE) {
|
if (ptr->flags & FMODE_WRITABLE) {
|
||||||
rb_syserr_fail(EACCES, 0);
|
rb_syserr_fail(EACCES, 0);
|
||||||
}
|
}
|
||||||
@ -481,7 +497,7 @@ strio_set_string(VALUE self, VALUE string)
|
|||||||
rb_io_taint_check(self);
|
rb_io_taint_check(self);
|
||||||
ptr->flags &= ~FMODE_READWRITE;
|
ptr->flags &= ~FMODE_READWRITE;
|
||||||
StringValue(string);
|
StringValue(string);
|
||||||
ptr->flags = OBJ_FROZEN(string) ? FMODE_READABLE : FMODE_READWRITE;
|
ptr->flags = OBJ_FROZEN(string) && !rb_str_chilled_p(string) ? FMODE_READABLE : FMODE_READWRITE;
|
||||||
ptr->pos = 0;
|
ptr->pos = 0;
|
||||||
ptr->lineno = 0;
|
ptr->lineno = 0;
|
||||||
RB_OBJ_WRITE(self, &ptr->string, string);
|
RB_OBJ_WRITE(self, &ptr->string, string);
|
||||||
|
@ -978,6 +978,27 @@ class TestStringIO < Test::Unit::TestCase
|
|||||||
assert_predicate(s.string, :ascii_only?)
|
assert_predicate(s.string, :ascii_only?)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if eval(%{ "test".frozen? && !"test".equal?("test") }) # Ruby 3.4+ chilled strings
|
||||||
|
def test_chilled_string
|
||||||
|
chilled_string = eval(%{""})
|
||||||
|
io = StringIO.new(chilled_string)
|
||||||
|
assert_warning(/literal string will be frozen/) { io << "test" }
|
||||||
|
assert_equal("test", io.string)
|
||||||
|
assert_same(chilled_string, io.string)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_chilled_string_string_set
|
||||||
|
io = StringIO.new
|
||||||
|
chilled_string = eval(%{""})
|
||||||
|
io.string = chilled_string
|
||||||
|
assert_warning(/literal string will be frozen/) { io << "test" }
|
||||||
|
assert_equal("test", io.string)
|
||||||
|
assert_same(chilled_string, io.string)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
def assert_string(content, encoding, str, mesg = nil)
|
def assert_string(content, encoding, str, mesg = nil)
|
||||||
assert_equal([content, encoding], [str, str.encoding], mesg)
|
assert_equal([content, encoding], [str, str.encoding], mesg)
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user