X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=util.c;h=91447785fbf6a06eea3801be35942f00dd0b5b81;hb=38f509077826ded67870f23d6b38f7c1e80cfa69;hp=a900889e57b90f983d776c44326e02935d9eee7b;hpb=0dc4febb9112967d5438f16a6dfbd0e403462d47;p=xonotic%2Fgmqcc.git diff --git a/util.c b/util.c index a900889..9144778 100644 --- a/util.c +++ b/util.c @@ -270,8 +270,8 @@ void util_endianswap(void *m, int s, int l) { if(*((char *)&s)) return; - for(; w < l; w++) { - for(; i < s << 1; i++) { + for(; w < (size_t)l; w++) { + for(; i < (size_t)(s << 1); i++) { unsigned char *p = (unsigned char *)m+w*s; unsigned char t = p[i]; p[i] = p[s-i-1]; @@ -450,16 +450,10 @@ int util_getline(char **lineptr, size_t *n, FILE *stream) { int c = getc(stream); if (chr < 2) { - char *tmp = (char*)mem_a((*n+=(*n>16)?*n:64)); - if (!tmp) - return -1; - - memcpy(tmp, *lineptr, pos - *lineptr); + *n += (*n > 16) ? *n : 64; chr = *n + *lineptr - pos; - if (!(*lineptr = tmp)) { - mem_d (tmp); + if (!(*lineptr = (char*)mem_r(*lineptr,*n))) return -1; - } pos = *n - chr + *lineptr; } @@ -483,32 +477,21 @@ int util_getline(char **lineptr, size_t *n, FILE *stream) { size_t util_strtocmd(const char *in, char *out, size_t outsz) { size_t sz = 1; - for (; *in && sz < outsz; ++in, ++out, ++sz) { - if (*in == '-') - *out = '_'; - else if (isalpha(*in) && !isupper(*in)) - *out = *in + 'A' - 'a'; - else - *out = *in; - } + for (; *in && sz < outsz; ++in, ++out, ++sz) + *out = (*in == '-') ? '_' : (isalpha(*in) && !isupper(*in)) ? *in + 'A' - 'a': *in; *out = 0; return sz-1; } size_t util_strtononcmd(const char *in, char *out, size_t outsz) { size_t sz = 1; - for (; *in && sz < outsz; ++in, ++out, ++sz) { - if (*in == '_') - *out = '-'; - else if (isalpha(*in) && isupper(*in)) - *out = *in + 'a' - 'A'; - else - *out = *in; - } + for (; *in && sz < outsz; ++in, ++out, ++sz) + *out = (*in == '_') ? '-' : (isalpha(*in) && isupper(*in)) ? *in + 'a' - 'A' : *in; *out = 0; return sz-1; } + FILE *util_fopen(const char *filename, const char *mode) { #ifdef WIN32 @@ -521,15 +504,6 @@ FILE *util_fopen(const char *filename, const char *mode) #endif } -bool util_filexists(const char *file) { - FILE *fp = fopen(file, "rb"); - if (!fp) return false; - - /* it exists */ - fclose(fp); - return true; -} - void _util_vec_grow(void **a, size_t i, size_t s) { size_t m = *a ? 2*_vec_beg(*a)+i : i+1; void *p = mem_r((*a ? _vec_raw(*a) : NULL), s * m + sizeof(size_t)*2); @@ -538,3 +512,149 @@ void _util_vec_grow(void **a, size_t i, size_t s) { *a = (void*)((size_t*)p + 2); _vec_beg(*a) = m; } + +/* + * Hash table for generic data, based on dynamic memory allocations + * all around. This is the internal interface, please look for + * EXPOSED INTERFACE comment below + */ +typedef struct hash_node_t { + char *key; /* the key for this node in table */ + void *value; /* allocated memory storing data */ + size_t size; /* size of data */ + struct hash_node_t *next; /* next node (linked list) */ +} hash_node_t; + + +size_t _util_hthash(hash_table_t *ht, const char *key) { + uint64_t val = 0; + size_t len = strlen(key); + size_t itr = 0; + + + while (val < ((uint64_t)~1) /* MAX SIZE OF UINT64 */ && itr < len) { + val = val << 8; + val += key[itr]; + + itr++; + } + + return val % ht->size; +} + +hash_node_t *_util_htnewpair(const char *key, void *value, size_t size) { + hash_node_t *node; + if (!(node = mem_a(sizeof(hash_node_t)))) + return NULL; + + if (!(node->key = util_strdup(key))) { + mem_d(node); + return NULL; + } + + if (!(node->value = mem_a(size))) { + mem_d(node->key); + mem_d(node); + return NULL; + } + + memcpy(node->value, value, size); + node->size = size; + node->next = NULL; + + return node; +} + +/* + * EXPOSED INTERFACE for the hashtable implementation + * util_htnew(size) -- to make a new hashtable + * util_htset(table, key, value, sizeof(value)) -- to set something in the table + * util_htget(table, key) -- to get something from the table + * util_htdel(table) -- to delete the table + */ +hash_table_t *util_htnew(size_t size) { + hash_table_t *hashtable = NULL; + if (size < 1) + return NULL; + + if (!(hashtable = mem_a(sizeof(hash_table_t)))) + return NULL; + + if (!(hashtable->table = mem_a(sizeof(hash_node_t*) * size))) { + mem_d(hashtable); + return NULL; + } + + hashtable->size = size; + memset(hashtable->table, 0, sizeof(hash_node_t*) * size); + + return hashtable; +} + +void util_htset(hash_table_t *ht, const char *key, void *value, size_t size) { + size_t bin = 0; + hash_node_t *newnode = NULL; + hash_node_t *next = NULL; + hash_node_t *last = NULL; + + bin = _util_hthash(ht, key); + next = ht->table[bin]; + + while (next && next->key && strcmp(key, next->key)) + last = next, next = next->next; + + /* already in table, do a replace */ + if (next && next->key && !strcmp(key, next->key)) { + mem_d(next->value); + next->value = mem_a(size); + next->size = size; + memcpy(next->value, value, size); + } else { + /* not found, grow a pair man :P */ + newnode = _util_htnewpair(key, value, size); + if (next == ht->table[bin]) { + newnode->next = next; + ht->table[bin] = newnode; + } else if (!next) { + last->next = newnode; + } else { + newnode->next = next; + last->next = newnode; + } + } +} + +void *util_htget(hash_table_t *ht, const char *key) { + size_t bin = _util_hthash(ht, key); + hash_node_t *pair = ht->table[bin]; + + while (pair && pair->key && strcmp(key, pair->key) > 0) + pair = pair->next; + + if (!pair || !pair->key || strcmp(key, pair->key) != 0) + return NULL; + + return pair->value; +} + +/* + * Free all allocated data in a hashtable, this is quite the amount + * of work. + */ +void util_htdel(hash_table_t *ht) { + size_t i = 0; + for (; i < ht->size; i++) { + hash_node_t *n = ht->table[i]; + + /* free in list */ + while (n) { + if (n->key) mem_d(n->key); + if (n->value) mem_d(n->value); + n = n->next; + } + + } + /* free table */ + mem_d(ht->table); + mem_d(ht); +}