forked from enlightenment/efl
124 lines
3.9 KiB
C
124 lines
3.9 KiB
C
#include "evas_common.h"
|
|
#include "evas_private.h"
|
|
|
|
typedef struct _Evas_Stringshare Evas_Stringshare;
|
|
typedef struct _Evas_Stringshare_El Evas_Stringshare_El;
|
|
|
|
struct _Evas_Stringshare
|
|
{
|
|
Evas_Stringshare_El *buckets[256];
|
|
};
|
|
|
|
struct _Evas_Stringshare_El
|
|
{
|
|
Evas_Stringshare_El *next;
|
|
int references;
|
|
};
|
|
|
|
static inline int
|
|
_evas_stringshare_hash_gen(const char *str, int *len)
|
|
{
|
|
unsigned int hash_num = 5381, i;
|
|
const unsigned char *ptr;
|
|
|
|
for (i = 0, ptr = (unsigned char *)str; *ptr; ptr++, i++)
|
|
hash_num = (hash_num * 33) ^ *ptr;
|
|
|
|
hash_num &= 0xff;
|
|
*len = i;
|
|
return (int)hash_num;
|
|
}
|
|
|
|
static Evas_Stringshare share =
|
|
{
|
|
{
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
|
}
|
|
};
|
|
|
|
EAPI const char *
|
|
evas_stringshare_add(const char *str)
|
|
{
|
|
int hash_num, slen;
|
|
char *el_str;
|
|
Evas_Stringshare_El *el, *pel = NULL;
|
|
|
|
if (!str) return NULL;
|
|
hash_num = _evas_stringshare_hash_gen(str, &slen);
|
|
for (el = share.buckets[hash_num]; el; pel = el, el = el->next)
|
|
{
|
|
el_str = ((char *)el) + sizeof(Evas_Stringshare_El);
|
|
if (!strcmp(el_str, str))
|
|
{
|
|
if (pel)
|
|
{
|
|
pel->next = el->next;
|
|
el->next = share.buckets[hash_num];
|
|
share.buckets[hash_num] = el;
|
|
}
|
|
el->references++;
|
|
// printf("SSHARE + \"%s\", ref %i\n", el_str, el->references);
|
|
return el_str;
|
|
}
|
|
}
|
|
if (!(el = malloc(sizeof(Evas_Stringshare_El) + slen + 1))) return NULL;
|
|
el_str = ((char *)el) + sizeof(Evas_Stringshare_El);
|
|
strcpy(el_str, str);
|
|
el->references = 1;
|
|
el->next = share.buckets[hash_num];
|
|
share.buckets[hash_num] = el;
|
|
return el_str;
|
|
}
|
|
|
|
EAPI void
|
|
evas_stringshare_del(const char *str)
|
|
{
|
|
int hash_num, slen;
|
|
char *el_str;
|
|
Evas_Stringshare_El *el, *pel = NULL;
|
|
|
|
if (!str) return;
|
|
hash_num = _evas_stringshare_hash_gen(str, &slen);
|
|
for (el = share.buckets[hash_num]; el; pel = el, el = el->next)
|
|
{
|
|
el_str = ((char *)el) + sizeof(Evas_Stringshare_El);
|
|
if (el_str == str)
|
|
{
|
|
el->references--;
|
|
if (el->references == 0)
|
|
{
|
|
if (pel) pel->next = el->next;
|
|
else share.buckets[hash_num] = el->next;
|
|
free(el);
|
|
}
|
|
else
|
|
{
|
|
if (pel)
|
|
{
|
|
pel->next = el->next;
|
|
el->next = share.buckets[hash_num];
|
|
share.buckets[hash_num] = el;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
printf("EEEK trying to del non-shared stringshare \"%s\"\n", str);
|
|
abort();
|
|
}
|