aboutsummaryrefslogtreecommitdiffhomepage
path: root/mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'mem.c')
-rw-r--r--mem.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/mem.c b/mem.c
index eefe96a..85fe28f 100644
--- a/mem.c
+++ b/mem.c
@@ -38,7 +38,7 @@ void *
/** string interning **/
internstr
-intern(const char *s)
+intern_(const char *s, uint len)
{
static uint N, n;
static struct ht {
@@ -53,13 +53,15 @@ intern(const char *s)
arena = (void *)amem.m, arena->cap = sizeof amem.m - sizeof(struct arena);
}
- for (size_t h = hashs(0, s), i = h;;) {
+ for (size_t h = len ? hashb(0, s, len) : hashs(0, s), i = h;;) {
i &= N - 1;
if (!ht[i].s) { /* insert */
if (n < N/4*3 /*load factor 75%*/) {
++n;
ht[i].h = h;
- return ht[i].s = alloccopy(&arena, s, strlen(s)+1, 1);
+ ht[i].s = alloccopy(&arena, s, (len ? len : strlen(s))+1, 1);
+ if (len) ((char *)ht[i].s)[len] = 0;
+ return ht[i].s;
}
/* resize */
size_t nnew = N * 2;
@@ -75,8 +77,11 @@ intern(const char *s)
N = nnew;
i = h;
continue;
- } else if (h == ht[i].h && !strcmp(s, &ht[i].s->c)) {
- return ht[i].s;
+ } else if (h == ht[i].h) {
+ if (!len && !strcmp(s, &ht[i].s->c))
+ return ht[i].s;
+ else if (len && !strncmp(s, &ht[i].s->c, len) && ht[i].s[len].c == 0)
+ return ht[i].s;
}
++i;
}