12 #include "hashtable.h"
13 #include "ptr_array.h"
15 static struct hashtable
*quark_string_hash
= NULL
; /* const char * -> int */
16 static ptr_array quark_string_index
= NULL
;
19 static CRITICAL_SECTION quark_static_cs
;
20 static bool cs_initialized
= false;
22 static void mutex_lock()
24 if (!cs_initialized
) {
25 InitializeCriticalSection(&quark_static_cs
);
27 cs_initialized
= true;
30 EnterCriticalSection(&quark_static_cs
);
33 static void mutex_unlock()
35 LeaveCriticalSection(&quark_static_cs
);
38 static pthread_mutex_t quark_static_lock
= PTHREAD_MUTEX_INITIALIZER
;
40 static void mutex_lock()
42 pthread_mutex_lock(&quark_static_lock
);
45 static void mutex_unlock()
47 pthread_mutex_unlock(&quark_static_lock
);
51 enum {QUARK_NOT_FOUND
= ~0L};
53 /* djb2 hash function */
54 static unsigned int string_hash(const void *val
)
56 unsigned int hash
= 5381;
57 const char *str
= (const char *)val
;
61 hash
= ((hash
<< 5) + hash
) + c
; /* hash * 33 + c */
66 static int string_eq(const void* a1
, const void* a2
)
68 return strcmp((const char*) a1
, (const char*) a2
) == 0;
71 /* assumes static lock is held */
72 static inline bool quark_init_if_needed()
74 if (quark_string_hash
== NULL
)
76 quark_string_hash
= create_hashtable(31, string_hash
, string_eq
);
77 quark_string_index
= ptr_array_new(10);
78 ptr_array_append(quark_string_index
, NULL
);
84 quark
quark_from_string(const char *string
)
86 if (string
== NULL
) return 0;
88 if (!quark_init_if_needed())
90 uintptr_t value
= (uintptr_t)hashtable_search(quark_string_hash
, string
);
97 string
= strdup(string
);
98 if (!ptr_array_append(quark_string_index
, string
))
101 return QUARK_NOT_FOUND
;
103 size_t index
= ptr_array_length(quark_string_index
) - 1;
104 hashtable_insert(quark_string_hash
, (char*) string
, (void*) index
);
109 quark
quark_from_static_string(const char *string
)
111 if (string
== NULL
) return 0;
113 if (!quark_init_if_needed())
115 uintptr_t value
= (uintptr_t)hashtable_search(quark_string_hash
, string
);
122 if (!ptr_array_append(quark_string_index
, string
))
125 return QUARK_NOT_FOUND
;
127 size_t index
= ptr_array_length(quark_string_index
) - 1;
128 hashtable_insert(quark_string_hash
, (char *)string
, (void*) index
);
133 const char * quark_to_string(quark q
)
136 if (q
== 0) return NULL
;
138 if (quark_init_if_needed() || q
>= ptr_array_length(quark_string_index
))
143 retval
= ptr_array_get_index(quark_string_index
, q
);