diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2013-12-24 08:27:42 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2013-12-24 08:27:42 +0900 |
| commit | bc7a6e88a17e89e14de7cb4cbbd6ca19c4daa620 (patch) | |
| tree | 07ed8473d511e903f8463cb7045160da1a3e58d0 /src/symbol.c | |
| parent | 9fab01caeed5697e30e30daef3a845f33dcfefaf (diff) | |
| download | mruby-bc7a6e88a17e89e14de7cb4cbbd6ca19c4daa620.tar.gz mruby-bc7a6e88a17e89e14de7cb4cbbd6ca19c4daa620.zip | |
zero copy C literal strings in symbol table
Diffstat (limited to 'src/symbol.c')
| -rw-r--r-- | src/symbol.c | 47 |
1 files changed, 39 insertions, 8 deletions
diff --git a/src/symbol.c b/src/symbol.c index 12f65d7e5..5ced22461 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -13,7 +13,8 @@ /* ------------------------------------------------------ */ typedef struct symbol_name { - size_t len; + mrb_bool lit; + uint16_t len; const char *name; } symbol_name; @@ -34,8 +35,8 @@ sym_hash_func(mrb_state *mrb, const symbol_name s) KHASH_DECLARE(n2s, symbol_name, mrb_sym, 1) KHASH_DEFINE (n2s, symbol_name, mrb_sym, 1, sym_hash_func, sym_hash_equal) /* ------------------------------------------------------ */ -mrb_sym -mrb_intern(mrb_state *mrb, const char *name, size_t len) +static mrb_sym +sym_intern(mrb_state *mrb, const char *name, size_t len, int lit) { khash_t(n2s) *h = mrb->name2sym; symbol_name sname; @@ -43,6 +44,10 @@ mrb_intern(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, mrb, h, sname); @@ -50,10 +55,15 @@ mrb_intern(mrb_state *mrb, const char *name, size_t len) 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; + 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; @@ -61,6 +71,18 @@ mrb_intern(mrb_state *mrb, const char *name, size_t len) } mrb_sym +mrb_intern(mrb_state *mrb, const char *name, size_t len) +{ + return sym_intern(mrb, name, len, 0); +} + +mrb_sym +mrb_intern_literal(mrb_state *mrb, const char *name, size_t len) +{ + return sym_intern(mrb, name, len, 1); +} + +mrb_sym mrb_intern_cstr(mrb_state *mrb, const char *name) { return mrb_intern(mrb, name, strlen(name)); @@ -79,6 +101,9 @@ mrb_check_intern(mrb_state *mrb, const char *name, size_t len) symbol_name sname; khiter_t k; + if (len > UINT16_MAX) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "symbol length too long"); + } sname.len = len; sname.name = name; @@ -129,7 +154,13 @@ 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); + 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); } |
