add String#freeze to the core

parent 87e11676
...@@ -59,6 +59,10 @@ struct RString { ...@@ -59,6 +59,10 @@ struct RString {
#define RSTR_SET_NOFREE_FLAG(s) ((s)->flags |= MRB_STR_NOFREE) #define RSTR_SET_NOFREE_FLAG(s) ((s)->flags |= MRB_STR_NOFREE)
#define RSTR_UNSET_NOFREE_FLAG(s) ((s)->flags &= ~MRB_STR_NOFREE) #define RSTR_UNSET_NOFREE_FLAG(s) ((s)->flags &= ~MRB_STR_NOFREE)
#define RSTR_FROZEN_P(s) ((s)->flags & MRB_STR_FROZEN)
#define RSTR_SET_FROZEN_FLAG(s) ((s)->flags |= MRB_STR_FROZEN)
#define RSTR_UNSET_FROZEN_FLAG(s) ((s)->flags &= ~MRB_STR_FROZEN)
#define mrb_str_ptr(s) ((struct RString*)(mrb_ptr(s))) #define mrb_str_ptr(s) ((struct RString*)(mrb_ptr(s)))
#define RSTRING(s) mrb_str_ptr(s) #define RSTRING(s) mrb_str_ptr(s)
#define RSTRING_PTR(s) RSTR_PTR(RSTRING(s)) #define RSTRING_PTR(s) RSTR_PTR(RSTRING(s))
...@@ -70,9 +74,10 @@ mrb_int mrb_str_strlen(mrb_state*, struct RString*); ...@@ -70,9 +74,10 @@ mrb_int mrb_str_strlen(mrb_state*, struct RString*);
#define MRB_STR_SHARED 1 #define MRB_STR_SHARED 1
#define MRB_STR_NOFREE 2 #define MRB_STR_NOFREE 2
#define MRB_STR_EMBED 4 #define MRB_STR_FROZEN 4
#define MRB_STR_EMBED_LEN_MASK 0xf8 #define MRB_STR_EMBED 8
#define MRB_STR_EMBED_LEN_SHIFT 3 #define MRB_STR_EMBED_LEN_MASK 0x1f0
#define MRB_STR_EMBED_LEN_SHIFT 4
void mrb_gc_free_str(mrb_state*, struct RString*); void mrb_gc_free_str(mrb_state*, struct RString*);
MRB_API void mrb_str_modify(mrb_state*, struct RString*); MRB_API void mrb_str_modify(mrb_state*, struct RString*);
......
...@@ -75,9 +75,18 @@ str_decref(mrb_state *mrb, mrb_shared_string *shared) ...@@ -75,9 +75,18 @@ str_decref(mrb_state *mrb, mrb_shared_string *shared)
} }
} }
static void
check_frozen(mrb_state *mrb, struct RString *s)
{
if (RSTR_FROZEN_P(s)) {
mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen string");
}
}
MRB_API void MRB_API void
mrb_str_modify(mrb_state *mrb, struct RString *s) mrb_str_modify(mrb_state *mrb, struct RString *s)
{ {
check_frozen(mrb, s);
if (RSTR_SHARED_P(s)) { if (RSTR_SHARED_P(s)) {
mrb_shared_string *shared = s->as.heap.aux.shared; mrb_shared_string *shared = s->as.heap.aux.shared;
...@@ -119,6 +128,15 @@ mrb_str_modify(mrb_state *mrb, struct RString *s) ...@@ -119,6 +128,15 @@ mrb_str_modify(mrb_state *mrb, struct RString *s)
} }
} }
static mrb_value
mrb_str_freeze(mrb_state *mrb, mrb_value str)
{
struct RString *s = mrb_str_ptr(str);
RSTR_SET_FROZEN_FLAG(s);
return str;
}
MRB_API mrb_value MRB_API mrb_value
mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len) mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len)
{ {
...@@ -1345,6 +1363,7 @@ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2) ...@@ -1345,6 +1363,7 @@ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2)
{ {
long len; long len;
check_frozen(mrb, s1);
len = RSTR_LEN(s2); len = RSTR_LEN(s2);
if (RSTR_SHARED_P(s1)) { if (RSTR_SHARED_P(s1)) {
str_decref(mrb, s1->as.heap.aux.shared); str_decref(mrb, s1->as.heap.aux.shared);
...@@ -2514,4 +2533,6 @@ mrb_init_string(mrb_state *mrb) ...@@ -2514,4 +2533,6 @@ mrb_init_string(mrb_state *mrb)
mrb_define_method(mrb, s, "upcase!", mrb_str_upcase_bang, MRB_ARGS_NONE()); /* 15.2.10.5.43 */ mrb_define_method(mrb, s, "upcase!", mrb_str_upcase_bang, MRB_ARGS_NONE()); /* 15.2.10.5.43 */
mrb_define_method(mrb, s, "inspect", mrb_str_inspect, MRB_ARGS_NONE()); /* 15.2.10.5.46(x) */ mrb_define_method(mrb, s, "inspect", mrb_str_inspect, MRB_ARGS_NONE()); /* 15.2.10.5.46(x) */
mrb_define_method(mrb, s, "bytes", mrb_str_bytes, MRB_ARGS_NONE()); mrb_define_method(mrb, s, "bytes", mrb_str_bytes, MRB_ARGS_NONE());
mrb_define_method(mrb, s, "freeze", mrb_str_freeze, MRB_ARGS_NONE());
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment