summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/symbol.c91
1 files changed, 45 insertions, 46 deletions
diff --git a/src/symbol.c b/src/symbol.c
index e60fa56f5..2a4a0c15a 100644
--- a/src/symbol.c
+++ b/src/symbol.c
@@ -20,21 +20,21 @@ typedef struct symbol_name {
} symbol_name;
static inline khint_t
-sym_hash_func(mrb_state *mrb, const symbol_name s)
+sym_hash_func(mrb_state *mrb, mrb_sym s)
{
khint_t h = 0;
- size_t i;
- const char *p = s.name;
+ size_t i, len = mrb->symtbl[s].len;;
+ const char *p = mrb->symtbl[s].name;
- for (i=0; i<s.len; i++) {
+ for (i=0; i<len; i++) {
h = (h << 5) - h + *p++;
}
return h;
}
-#define sym_hash_equal(mrb,a, b) (a.len == b.len && memcmp(a.name, b.name, a.len) == 0)
+#define sym_hash_equal(mrb,a, b) (mrb->symtbl[a].len == mrb->symtbl[b].len && memcmp(mrb->symtbl[a].name, mrb->symtbl[b].name, mrb->symtbl[a].len) == 0)
-KHASH_DECLARE(n2s, symbol_name, mrb_sym, TRUE)
-KHASH_DEFINE (n2s, symbol_name, mrb_sym, TRUE, sym_hash_func, sym_hash_equal)
+KHASH_DECLARE(n2s, mrb_sym, mrb_sym, FALSE)
+KHASH_DEFINE (n2s, mrb_sym, mrb_sym, FALSE, sym_hash_func, sym_hash_equal)
/* ------------------------------------------------------ */
static void
@@ -49,31 +49,42 @@ 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;
+ symbol_name *sname = mrb->symtbl; /* symtbl[0] for working memory */
khiter_t k;
mrb_sym sym;
char *p;
sym_validate_len(mrb, len);
- sname.lit = lit;
- sname.len = (uint16_t)len;
- sname.name = name;
- k = kh_get(n2s, mrb, h, sname);
- if (k != kh_end(h))
- return kh_value(h, k);
+ if (sname) {
+ sname->lit = lit;
+ sname->len = (uint16_t)len;
+ sname->name = name;
+ k = kh_get(n2s, mrb, h, 0);
+ if (k != kh_end(h))
+ return kh_key(h, k);
+ }
+ /* registering a new symbol */
sym = ++mrb->symidx;
+ if (mrb->symcapa < sym) {
+ if (mrb->symcapa == 0) mrb->symcapa = 100;
+ else mrb->symcapa *= 1.2;
+ mrb->symtbl = (symbol_name*)mrb_realloc(mrb, mrb->symtbl, sizeof(symbol_name)*(mrb->symcapa+1));
+ }
+ sname = &mrb->symtbl[sym];
+ sname->len = (uint16_t)len;
if (lit) {
- sname.name = name;
+ sname->name = name;
+ sname->lit = TRUE;
}
else {
p = (char *)mrb_malloc(mrb, len+1);
memcpy(p, name, len);
p[len] = 0;
- sname.name = (const char*)p;
+ sname->name = (const char*)p;
+ sname->lit = FALSE;
}
- k = kh_put(n2s, mrb, h, sname);
- kh_value(h, k) = sym;
+ kh_put(n2s, mrb, h, sym);
return sym;
}
@@ -106,16 +117,16 @@ MRB_API mrb_value
mrb_check_intern(mrb_state *mrb, const char *name, size_t len)
{
khash_t(n2s) *h = mrb->name2sym;
- symbol_name sname = { 0 };
+ symbol_name *sname = mrb->symtbl;
khiter_t k;
sym_validate_len(mrb, len);
- sname.len = (uint16_t)len;
- sname.name = name;
+ sname->len = (uint16_t)len;
+ sname->name = name;
- k = kh_get(n2s, mrb, h, sname);
+ k = kh_get(n2s, mrb, h, 0);
if (k != kh_end(h)) {
- return mrb_symbol_value(kh_value(h, k));
+ return mrb_symbol_value(kh_key(h, k));
}
return mrb_nil_value();
}
@@ -136,37 +147,25 @@ mrb_check_intern_str(mrb_state *mrb, mrb_value str)
MRB_API const char*
mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, mrb_int *lenp)
{
- khash_t(n2s) *h = mrb->name2sym;
- khiter_t k;
- symbol_name sname;
-
- for (k = kh_begin(h); k != kh_end(h); k++) {
- if (kh_exist(h, k)) {
- if (kh_value(h, k) == sym) {
- sname = kh_key(h, k);
- if (lenp) *lenp = sname.len;
- return sname.name;
- }
- }
+ if (sym == 0 || mrb->symidx < sym) {
+ return NULL;
}
- if (lenp) *lenp = 0;
- return NULL; /* missing */
+
+ if (lenp) *lenp = mrb->symtbl[sym].len;
+ return mrb->symtbl[sym].name;
}
void
mrb_free_symtbl(mrb_state *mrb)
{
- khash_t(n2s) *h = mrb->name2sym;
- khiter_t k;
+ mrb_sym i, lim;
- for (k = kh_begin(h); k != kh_end(h); k++)
- if (kh_exist(h, k)) {
- symbol_name s = kh_key(h, k);
-
- if (!s.lit) {
- mrb_free(mrb, (char*)s.name);
- }
+ for (i=1, lim=mrb->symidx+1; i<lim; i++) {
+ if (!mrb->symtbl[i].lit) {
+ mrb_free(mrb, (char*)mrb->symtbl[i].name);
}
+ }
+ mrb_free(mrb, mrb->symtbl);
kh_destroy(n2s, mrb, mrb->name2sym);
}