diff options
Diffstat (limited to 'src/symbol.c')
| -rw-r--r-- | src/symbol.c | 108 |
1 files changed, 68 insertions, 40 deletions
diff --git a/src/symbol.c b/src/symbol.c index c145a4a1a..fd0b116bd 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -5,7 +5,6 @@ */ #include <ctype.h> -#include <limits.h> #include <string.h> #include "mruby.h" #include "mruby/khash.h" @@ -13,7 +12,8 @@ /* ------------------------------------------------------ */ typedef struct symbol_name { - size_t len; + mrb_bool lit : 1; + uint16_t len; const char *name; } symbol_name; @@ -31,11 +31,11 @@ sym_hash_func(mrb_state *mrb, const symbol_name s) } #define sym_hash_equal(mrb,a, b) (a.len == b.len && memcmp(a.name, b.name, a.len) == 0) -KHASH_DECLARE(n2s, symbol_name, mrb_sym, 1) -KHASH_DEFINE (n2s, symbol_name, mrb_sym, 1, sym_hash_func, sym_hash_equal) +KHASH_DECLARE(n2s, symbol_name, mrb_sym, TRUE) +KHASH_DEFINE (n2s, symbol_name, mrb_sym, TRUE, sym_hash_func, sym_hash_equal) /* ------------------------------------------------------ */ -mrb_sym -mrb_intern2(mrb_state *mrb, const char *name, size_t len) +static mrb_sym +sym_intern(mrb_state *mrb, const char *name, size_t len, mrb_bool lit) { khash_t(n2s) *h = mrb->name2sym; symbol_name sname; @@ -43,46 +43,70 @@ mrb_intern2(mrb_state *mrb, const char *name, size_t len) mrb_sym sym; char *p; + if (len > UINT16_MAX) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "symbol length too long"); + } + sname.lit = lit; sname.len = len; sname.name = name; - k = kh_get(n2s, h, sname); + k = kh_get(n2s, mrb, h, sname); if (k != kh_end(h)) return kh_value(h, k); sym = ++mrb->symidx; - p = (char *)mrb_malloc(mrb, len+1); - memcpy(p, name, len); - p[len] = 0; - sname.name = (const char*)p; - k = kh_put(n2s, h, sname); + if (lit) { + sname.name = name; + } + else { + p = (char *)mrb_malloc(mrb, len+1); + memcpy(p, name, len); + p[len] = 0; + sname.name = (const char*)p; + } + k = kh_put(n2s, mrb, h, sname); kh_value(h, k) = sym; return sym; } mrb_sym +mrb_intern(mrb_state *mrb, const char *name, size_t len) +{ + return sym_intern(mrb, name, len, FALSE); +} + +mrb_sym +mrb_intern_static(mrb_state *mrb, const char *name, size_t len) +{ + return sym_intern(mrb, name, len, TRUE); +} + +mrb_sym mrb_intern_cstr(mrb_state *mrb, const char *name) { - return mrb_intern2(mrb, name, strlen(name)); + return mrb_intern(mrb, name, strlen(name)); } mrb_sym mrb_intern_str(mrb_state *mrb, mrb_value str) { - return mrb_intern2(mrb, RSTRING_PTR(str), RSTRING_LEN(str)); + return mrb_intern(mrb, RSTRING_PTR(str), RSTRING_LEN(str)); } mrb_value mrb_check_intern(mrb_state *mrb, const char *name, size_t len) { khash_t(n2s) *h = mrb->name2sym; - symbol_name sname; + symbol_name sname = { 0 }; khiter_t k; + if (len > UINT16_MAX) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "symbol length too long"); + } sname.len = len; sname.name = name; - k = kh_get(n2s, h, sname); + k = kh_get(n2s, mrb, h, sname); if (k != kh_end(h)) { return mrb_symbol_value(kh_value(h, k)); } @@ -92,7 +116,7 @@ mrb_check_intern(mrb_state *mrb, const char *name, size_t len) mrb_value mrb_check_intern_cstr(mrb_state *mrb, const char *name) { - return mrb_check_intern(mrb, name, strlen(name)); + return mrb_check_intern(mrb, name, (mrb_int)strlen(name)); } mrb_value @@ -103,7 +127,7 @@ mrb_check_intern_str(mrb_state *mrb, mrb_value str) /* lenp must be a pointer to a size_t variable */ const char* -mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, size_t *lenp) +mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, mrb_int *lenp) { khash_t(n2s) *h = mrb->name2sym; khiter_t k; @@ -113,12 +137,12 @@ mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, size_t *lenp) if (kh_exist(h, k)) { if (kh_value(h, k) == sym) { sname = kh_key(h, k); - *lenp = sname.len; + if (lenp) *lenp = sname.len; return sname.name; } } } - *lenp = 0; + if (lenp) *lenp = 0; return NULL; /* missing */ } @@ -129,8 +153,14 @@ mrb_free_symtbl(mrb_state *mrb) khiter_t k; for (k = kh_begin(h); k != kh_end(h); k++) - if (kh_exist(h, k)) mrb_free(mrb, (char*)kh_key(h, k).name); - kh_destroy(n2s,mrb->name2sym); + if (kh_exist(h, k)) { + symbol_name s = kh_key(h, k); + + if (!s.lit) { + mrb_free(mrb, (char*)s.name); + } + } + kh_destroy(n2s, mrb, mrb->name2sym); } void @@ -210,7 +240,7 @@ mrb_sym_to_s(mrb_state *mrb, mrb_value sym) { mrb_sym id = mrb_symbol(sym); const char *p; - size_t len; + mrb_int len; p = mrb_sym2name_len(mrb, id, &len); return mrb_str_new_static(mrb, p, len); @@ -278,7 +308,7 @@ static mrb_bool symname_p(const char *name) { const char *m = name; - int localid = FALSE; + mrb_bool localid = FALSE; if (!m) return FALSE; switch (*m) { @@ -362,16 +392,20 @@ sym_inspect(mrb_state *mrb, mrb_value sym) { mrb_value str; const char *name; - size_t len; + mrb_int len; mrb_sym id = mrb_symbol(sym); + char *sp; name = mrb_sym2name_len(mrb, id, &len); str = mrb_str_new(mrb, 0, len+1); - RSTRING(str)->ptr[0] = ':'; - memcpy(RSTRING(str)->ptr+1, name, len); + sp = RSTRING_PTR(str); + RSTRING_PTR(str)[0] = ':'; + memcpy(sp+1, name, len); if (!symname_p(name) || strlen(name) != len) { str = mrb_str_dump(mrb, str); - memcpy(RSTRING(str)->ptr, ":\"", 2); + sp = RSTRING_PTR(str); + sp[0] = ':'; + sp[1] = '"'; } return str; } @@ -379,31 +413,26 @@ sym_inspect(mrb_state *mrb, mrb_value sym) mrb_value mrb_sym2str(mrb_state *mrb, mrb_sym sym) { - size_t len; + mrb_int len; const char *name = mrb_sym2name_len(mrb, sym, &len); - mrb_value str; if (!name) return mrb_undef_value(); /* can't happen */ - str = mrb_str_new_static(mrb, name, len); - if (symname_p(name) && strlen(name) == len) { - return str; - } - return mrb_str_dump(mrb, str); + return mrb_str_new_static(mrb, name, len); } const char* mrb_sym2name(mrb_state *mrb, mrb_sym sym) { - size_t len; + mrb_int len; const char *name = mrb_sym2name_len(mrb, sym, &len); if (!name) return NULL; - if (symname_p(name) && strlen(name) == len) { + if (symname_p(name) && strlen(name) == (size_t)len) { return name; } else { mrb_value str = mrb_str_dump(mrb, mrb_str_new_static(mrb, name, len)); - return RSTRING(str)->ptr; + return RSTRING_PTR(str); } } @@ -423,7 +452,7 @@ sym_cmp(mrb_state *mrb, mrb_value s1) else { const char *p1, *p2; int retval; - size_t len, len1, len2; + mrb_int len, len1, len2; p1 = mrb_sym2name_len(mrb, sym1, &len1); p2 = mrb_sym2name_len(mrb, sym2, &len2); @@ -452,5 +481,4 @@ mrb_init_symbol(mrb_state *mrb) mrb_define_method(mrb, sym, "to_sym", sym_to_sym, MRB_ARGS_NONE()); /* 15.2.11.3.4 */ mrb_define_method(mrb, sym, "inspect", sym_inspect, MRB_ARGS_NONE()); /* 15.2.11.3.5(x) */ mrb_define_method(mrb, sym, "<=>", sym_cmp, MRB_ARGS_REQ(1)); - mrb->init_sym = mrb_intern2(mrb, "initialize", 10); } |
