char string[1]; /* Null-terminated string. */
};
/* All interned strings. */
static struct hmap interns = HMAP_INITIALIZER (interns);
char string[1]; /* Null-terminated string. */
};
/* All interned strings. */
static struct hmap interns = HMAP_INITIALIZER (interns);
static struct interned_string *
intern_lookup__ (const char *s, size_t length, unsigned int hash)
{
struct interned_string *is;
HMAP_FOR_EACH_WITH_HASH (is, struct interned_string, node, hash, &interns)
static struct interned_string *
intern_lookup__ (const char *s, size_t length, unsigned int hash)
{
struct interned_string *is;
HMAP_FOR_EACH_WITH_HASH (is, struct interned_string, node, hash, &interns)
is = xmalloc (length + sizeof *is);
hmap_insert (&interns, &is->node, hash);
is->ref_cnt = 1;
is = xmalloc (length + sizeof *is);
hmap_insert (&interns, &is->node, hash);
is->ref_cnt = 1;
struct interned_string *is = UP_CAST (s, struct interned_string, string);
assert (is->ref_cnt > 0);
return is;
struct interned_string *is = UP_CAST (s, struct interned_string, string);
assert (is->ref_cnt > 0);
return is;
/* Decreases the reference count on S, which must be an interned string
returned by intern_new(). If the reference count reaches 0, frees the
interned string. */
void
intern_unref (const char *s)
{
/* Decreases the reference count on S, which must be an interned string
returned by intern_new(). If the reference count reaches 0, frees the
interned string. */
void
intern_unref (const char *s)
{
- hmap_delete (&interns, &is->node);
- free (is);
+ struct interned_string *is = interned_string_from_string (s);
+ if (--is->ref_cnt == 0)
+ {
+ hmap_delete (&interns, &is->node);
+ free (is);
+ }
unsigned int hash = hash_bytes (s, length, 0);
return intern_lookup__ (s, length, hash) != NULL;
}
unsigned int hash = hash_bytes (s, length, 0);
return intern_lookup__ (s, length, hash) != NULL;
}