31 uint64_t
refcnt:
sizeof(uint64_t) * 8 - 1;
38 "refstr_t.s is not at an even offset, breaking lib/cgraph/id.c code");
50 return strcmp(a, b->
s) == 0;
68static uint64_t
hash(
const void *key,
size_t len, uint8_t extra) {
69 assert(key !=
NULL ||
len == 0);
85 static const uint64_t
seed = 0;
87 const uint64_t m = UINT64_C(0xc6a4a7935bd1e995);
88 const unsigned r = 47;
92 const unsigned char *
data = key;
93 const unsigned char *end =
data +
len /
sizeof(uint64_t) *
sizeof(uint64_t);
98 memcpy(&k,
data,
sizeof(k));
109 const unsigned char *data2 =
data;
112 h ^= (uint64_t)extra << 56;
116 h ^= (uint64_t)data2[6] << 48;
118 h ^= (uint64_t)data2[5] << 40;
120 h ^= (uint64_t)data2[4] << 32;
122 h ^= (uint64_t)data2[3] << 24;
124 h ^= (uint64_t)data2[2] << 16;
126 h ^= (uint64_t)data2[1] << 8;
128 h ^= (uint64_t)data2[0];
153 return (
size_t)
hash(
s, strlen(
s), is_html);
162 assert(dict !=
NULL);
167 static const size_t OCCUPANCY_THRESHOLD_PERCENT = 70;
171 const bool grow = 100 * dict->
size >= OCCUPANCY_THRESHOLD_PERCENT * capacity;
174 const size_t new_c = capacity == 0 ? 10 : dict->
capacity_exp + 1;
181 for (
size_t i = 0; i < capacity; ++i) {
200 assert(capacity > dict->
size);
204 for (
size_t i = 0; i < capacity; ++i) {
205 const size_t candidate = (h + i) % capacity;
226 assert(dict !=
NULL);
232 for (
size_t i = 0; i < capacity; ++i) {
233 const size_t candidate = (h + i) % capacity;
247 return dict->
buckets[candidate];
257 assert(dict !=
NULL);
264 for (
size_t i = 0; i < capacity; ++i) {
265 const size_t candidate = (h + i) % capacity;
279 assert(dict->
size > 0);
290 assert(dict !=
NULL);
292 if (*dict !=
NULL && (*dict)->buckets !=
NULL) {
293 for (
size_t i = 0; i < 1ul << (*dict)->capacity_exp; ++i) {
295 free((*dict)->buckets[i]);
298 free((*dict)->buckets);
316 if (*dictref ==
NULL) {
358 if (sz > 0 && r ==
NULL) {
386 if (r && r->
s ==
s) {
412static int refstrprint(
const refstr_t *r) {
413 fprintf(stderr,
"%s\n", r->
s);
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
static void * gv_alloc(size_t size)
static double len(glCompPoint p)
int aghtmlstr(const char *s)
int agstrfree(Agraph_t *g, const char *s, bool is_html)
char * agstrdup(Agraph_t *g, const char *s)
returns a pointer to a reference-counted copy of the argument string, creating one if necessary
char * agstrbind(Agraph_t *g, const char *s)
char * agstrdup_html(Agraph_t *g, const char *s)
static refstr_t * strdict_find(strdict_t *dict, const char *s, bool is_html)
int agstrclose(Agraph_t *g)
static void strdict_add(strdict_t *dict, refstr_t *r)
add a reference-counted string to a dictionary
static strdict_t * Refdict_default
static void strdict_remove(strdict_t *dict, const refstr_t *key)
remove a reference-counted string from a dictionary
static char * agstrdup_internal(Agraph_t *g, const char *s, bool is_html)
static strdict_t * strdict_new(void)
create a new string dictionary
static strdict_t ** refdict(Agraph_t *g)
static void strdict_free(strdict_t **dict)
destroy a string dictionary
static bool refstr_eq(const char *a, bool is_html, const refstr_t *b)
static char * refstrbind(strdict_t *strdict, const char *s)
static size_t strdict_hash(const char *s, bool is_html)
static refstr_t *const TOMBSTONE
void * strdict
shared string dict
Agclos_t * clos
shared resources
size_t capacity_exp
log₂ size of buckets
refstr_t ** buckets
backing store of elements
size_t size
number of elements in the dictionary