diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2015-08-27 17:54:30 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2015-08-27 17:54:30 +0900 |
| commit | 1a45447b8b66159a4a7d0348c4a01a175b3778fd (patch) | |
| tree | 938ca06713b6833805a9f47b53ef8cf5e5470748 | |
| parent | 87e11676b3a49d0dc3758c899deeab820d744b36 (diff) | |
| download | mruby-1a45447b8b66159a4a7d0348c4a01a175b3778fd.tar.gz mruby-1a45447b8b66159a4a7d0348c4a01a175b3778fd.zip | |
add String#freeze to the core
| -rw-r--r-- | include/mruby/string.h | 11 | ||||
| -rw-r--r-- | src/string.c | 21 |
2 files changed, 29 insertions, 3 deletions
diff --git a/include/mruby/string.h b/include/mruby/string.h index 5228dcbca..c4b31216e 100644 --- a/include/mruby/string.h +++ b/include/mruby/string.h @@ -59,6 +59,10 @@ struct RString { #define RSTR_SET_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 RSTRING(s) mrb_str_ptr(s) #define RSTRING_PTR(s) RSTR_PTR(RSTRING(s)) @@ -70,9 +74,10 @@ mrb_int mrb_str_strlen(mrb_state*, struct RString*); #define MRB_STR_SHARED 1 #define MRB_STR_NOFREE 2 -#define MRB_STR_EMBED 4 -#define MRB_STR_EMBED_LEN_MASK 0xf8 -#define MRB_STR_EMBED_LEN_SHIFT 3 +#define MRB_STR_FROZEN 4 +#define MRB_STR_EMBED 8 +#define MRB_STR_EMBED_LEN_MASK 0x1f0 +#define MRB_STR_EMBED_LEN_SHIFT 4 void mrb_gc_free_str(mrb_state*, struct RString*); MRB_API void mrb_str_modify(mrb_state*, struct RString*); diff --git a/src/string.c b/src/string.c index 45ba38c9d..e5f446bde 100644 --- a/src/string.c +++ b/src/string.c @@ -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_str_modify(mrb_state *mrb, struct RString *s) { + check_frozen(mrb, s); if (RSTR_SHARED_P(s)) { mrb_shared_string *shared = s->as.heap.aux.shared; @@ -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_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) { long len; + check_frozen(mrb, s1); len = RSTR_LEN(s2); if (RSTR_SHARED_P(s1)) { str_decref(mrb, s1->as.heap.aux.shared); @@ -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, "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, "freeze", mrb_str_freeze, MRB_ARGS_NONE()); } |
