Copyright (c) 2001,2002,2003,2004 Matthias Kramm <kramm@quiss.org>
- This program is free software; you can redistribute it and/or modify
+ This program is rfx_free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the rfx_free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
+ along with this program; if not, write to the rfx_free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <assert.h>
#include <memory.h>
+#include "mem.h"
#include "q.h"
// ------------------------------- malloc, alloc routines ---------------------
#ifndef STRNDUP
char* strdup_n(const char*str, int size)
{
- char*m = (char*)malloc(size+1);
+ char*m = (char*)rfx_alloc(size+1);
memcpy(m, str, size);
m[size] = 0;
return m;
}
void mem_clear(mem_t*mem)
{
- free(mem->buffer);mem->buffer = 0;
+ rfx_free(mem->buffer);mem->buffer = 0;
}
void mem_destroy(mem_t*mem)
{
mem_clear(mem);
- free(mem);
+ rfx_free(mem);
}
static int mem_put_(mem_t*m,const void*data, int length, int null)
{
m->pos += length + (null?1:0);
if(m->pos > m->len) {
m->len = (m->pos+63)&~63;
- m->buffer = m->buffer?(char*)realloc(m->buffer,m->len):(char*)malloc(m->len);
+ m->buffer = m->buffer?(char*)rfx_realloc(m->buffer,m->len):(char*)rfx_alloc(m->len);
}
+ assert(n+length <= m->len);
memcpy(&m->buffer[n], data, length);
if(null)
m->buffer[n + length] = 0;
void ringbuffer_init(ringbuffer_t*r)
{
- ringbuffer_internal_t*i = (ringbuffer_internal_t*)malloc(sizeof(ringbuffer_internal_t));
+ ringbuffer_internal_t*i = (ringbuffer_internal_t*)rfx_calloc(sizeof(ringbuffer_internal_t));
memset(r, 0, sizeof(ringbuffer_t));
- memset(i, 0, sizeof(ringbuffer_internal_t));
r->internal = i;
- i->buffer = (unsigned char*)malloc(1024);
+ i->buffer = (unsigned char*)rfx_alloc(1024);
i->buffersize = 1024;
}
int ringbuffer_read(ringbuffer_t*r, void*buf, int len)
if(newbuffersize < r->available + len)
newbuffersize = r->available + len + 1024;
- buf2 = (unsigned char*)malloc(newbuffersize);
+ buf2 = (unsigned char*)rfx_alloc(newbuffersize);
ringbuffer_read(r, buf2, r->available);
- free(i->buffer);
+ rfx_free(i->buffer);
i->buffer = buf2;
i->buffersize = newbuffersize;
i->readpos = 0;
void ringbuffer_clear(ringbuffer_t*r)
{
ringbuffer_internal_t*i = (ringbuffer_internal_t*)r->internal;
- free(i->buffer);i->buffer = 0;
- free(i);
+ rfx_free(i->buffer);i->buffer = 0;
+ rfx_free(i);
}
// ------------------------------- heap_t -------------------------------
h->size = 0;
h->elem_size = elem_size;
h->compare = compare;
- h->elements = (void**)malloc(n*sizeof(void*));memset(h->elements, 0, n*sizeof(void*));
- h->data = (char*)malloc(h->max_size*h->elem_size);memset(h->data, 0, h->max_size*h->elem_size);
+ h->elements = (void**)rfx_calloc(n*sizeof(void*));
+ h->data = (char*)rfx_calloc(h->max_size*h->elem_size);
}
void heap_clear(heap_t*h)
{
- free(h->elements);
- free(h->data);
+ rfx_free(h->elements);
+ rfx_free(h->data);
}
#define HEAP_NODE_SMALLER(h,node1,node2) ((h)->compare((node1),(node2))>0)
}
void** heap_flatten(heap_t*h)
{
- void**nodes = (void**)malloc(h->size*sizeof(void*));
+ void**nodes = (void**)rfx_alloc(h->size*sizeof(void*));
void**p = nodes;
while(h->size) {
int t;
if(crc32)
return;
- crc32= (unsigned int*)malloc(sizeof(unsigned int)*256);
+ crc32= (unsigned int*)rfx_alloc(sizeof(unsigned int)*256);
for(t=0; t<256; t++) {
unsigned int c = t;
int s;
s.str = text;
return s;
}
+char* string_cstr(string_t*str)
+{
+ return strdup_n(str->str, str->len);
+}
unsigned int string_hash(string_t*str)
{
int t;
unsigned int string_hash2(const char*str)
{
unsigned int checksum = 0;
+ const char*p = str;
if(!crc32)
crc32_init();
- while(*str) {
- checksum = checksum>>8 ^ crc32[(*str^checksum)&0xff];
- str++;
+ while(*p) {
+ checksum = checksum>>8 ^ crc32[(*p^checksum)&0xff];
+ p++;
}
return checksum;
}
+unsigned int string_hash3(const char*str, int len)
+{
+ string_t s;
+ s.str = str;
+ s.len = len;
+ return string_hash(&s);
+}
void string_dup2(string_t*str, const char*text, int len)
{
str->len = len;
return 1;
return 0;
}
-char* string_cstr(string_t*str)
-{
- return strdup_n(str->str, str->len);
-}
// ------------------------------- stringarray_t ------------------------------
-#define DEFAULT_HASH_SIZE 257
-
typedef struct _stringlist {
int index;
struct _stringlist*next;
{
stringarray_internal_t*s;
int t;
- sa->internal = (stringarray_internal_t*)malloc(sizeof(stringarray_internal_t));
- memset(sa->internal, 0, sizeof(stringarray_internal_t));
+ sa->internal = (stringarray_internal_t*)rfx_calloc(sizeof(stringarray_internal_t));
s = (stringarray_internal_t*)sa->internal;
mem_init(&s->pos);
- s->hash = malloc(sizeof(stringlist_t*)*hashsize);
- memset(s->hash, 0, sizeof(stringlist_t*)*hashsize);
+ s->hash = rfx_calloc(sizeof(stringlist_t*)*hashsize);
s->hashsize = hashsize;
}
void stringarray_put(stringarray_t*sa, string_t str)
char*ss = string_cstr(&str);
mem_put(&s->pos, &ss, sizeof(char*));
- stringlist_t*l = malloc(sizeof(stringlist_t));
+ stringlist_t*l = rfx_alloc(sizeof(stringlist_t));
l->index = s->num;
l->next = s->hash[hash];
s->hash[hash] = l;
if(index==l->index) {
old->next = l->next;
memset(l, 0, sizeof(stringlist_t));
- free(l);
+ rfx_free(l);
if(old==l)
return 0;
else
while(l) {
stringlist_t*next = l->next;
memset(l, 0, sizeof(stringlist_t));
- free(l);
+ rfx_free(l);
l = next;
}
}
- free(s->hash);s->hash=0;
- free(s);
+ rfx_free(s->hash);s->hash=0;
+ rfx_free(s);
}
void stringarray_destroy(stringarray_t*sa)
{
stringarray_clear(sa);
- free(sa);
+ rfx_free(sa);
}
// ------------------------------- dictionary_t -------------------------------
+#define INITIAL_SIZE 1
+
+static int max(int x, int y) {
+ return x>y?x:y;
+}
+
dict_t*dict_new()
{
- dict_t*d = malloc(sizeof(dict_t));
+ dict_t*d = rfx_alloc(sizeof(dict_t));
dict_init(d);
return d;
}
void dict_init(dict_t*h)
{
memset(h, 0, sizeof(dict_t));
- h->hashsize = DEFAULT_HASH_SIZE;
- h->slots = malloc(sizeof(dictentry_t*)*h->hashsize);
+ h->hashsize = INITIAL_SIZE;
+ h->slots = h->hashsize?(dictentry_t**)rfx_calloc(sizeof(dictentry_t*)*h->hashsize):0;
h->num = 0;
- memset(h->slots, 0, sizeof(dictentry_t*)*h->hashsize);
+}
+static void dict_expand(dict_t*h, int newlen)
+{
+ assert(h->hashsize < newlen);
+ dictentry_t**newslots = (dictentry_t**)rfx_calloc(sizeof(dictentry_t*)*newlen);
+ int t;
+ for(t=0;t<h->hashsize;t++) {
+ dictentry_t*e = h->slots[t];
+ while(e) {
+ dictentry_t*next = e->next;
+ unsigned int newhash = e->hash%newlen;
+ e->next = newslots[newhash];
+ newslots[newhash] = e;
+ e = next;
+ }
+ }
+ if(h->slots)
+ rfx_free(h->slots);
+ h->slots = newslots;
+ h->hashsize = newlen;
}
void dict_put(dict_t*h, string_t s, void* data)
{
- unsigned int checksum = string_hash(&s) % h->hashsize;
- dictentry_t*e = (dictentry_t*)malloc(sizeof(dictentry_t));
- e->s = strdup(s.str);
- e->next = h->slots[checksum];
+ /* TODO: should we look for duplicates here? */
+ unsigned int hash = string_hash(&s);
+ dictentry_t*e = (dictentry_t*)rfx_alloc(sizeof(dictentry_t));
+
+ unsigned int hash2 = string_hash(&s) % h->hashsize;
+ char*sdata = rfx_alloc(s.len);
+ memcpy(sdata, s.str, s.len);
+ e->s = sdata;
+ e->len = s.len;
+ e->hash = hash; //for resizing
+ e->next = h->slots[hash2];
e->data = data;
- h->slots[checksum] = e;
+ h->slots[hash2] = e;
h->num++;
}
void dict_put2(dict_t*h, const char*s, void*data)
string_set(&s2, s);
dict_put(h, s2, data);
}
+void dict_put3(dict_t*h, const char* s, int len, void*data)
+{
+ string_t s3;
+ string_set2(&s3, s, len);
+ dict_put(h, s3, data);
+}
void dict_dump(dict_t*h, FILE*fi, const char*prefix)
{
int t;
for(t=0;t<h->hashsize;t++) {
dictentry_t*e = h->slots[t];
while(e) {
+ char*s = strdup_n(e->s, e->len);
fprintf(fi, "%s%s=%08x\n", prefix, e->s, e->data);
+ rfx_free(s);
e = e->next;
}
}
{
return h->num;
}
-void* dict_lookup(dict_t*h, const char*s)
+void* dict_lookup2(dict_t*h, const char*s, int len)
{
- unsigned int checksum = string_hash2(s) % h->hashsize;
- dictentry_t*e = h->slots[checksum];
+ if(!h->num)
+ return 0;
+
+ unsigned int ohash = string_hash2(s);
+ unsigned int hash = ohash % h->hashsize;
+
+ /* check first entry for match */
+ dictentry_t*e = h->slots[hash];
+ if(e && e->len == len && !memcmp(e->s, s, len)) {
+ return e->data;
+ } else if(e) {
+ e = e->next;
+ }
+
+ /* if dict is 2/3 filled, double the size. Do
+ this the first time we have to actually iterate
+ through a slot to find our data */
+ if(e && h->num*3 >= h->hashsize*2) {
+ int newsize = h->hashsize;
+ while(h->num*3 >= newsize*2) {
+ newsize = newsize<15?15:(newsize+1)*2-1;
+ }
+ dict_expand(h, newsize);
+ hash = ohash % h->hashsize;
+ e = h->slots[hash];
+ }
+
+ /* check subsequent entries for a match */
while(e) {
- if(!strcmp(e->s, s)) {
+ if(e->len == len && !memcmp(e->s, s, len)) {
return e->data;
}
e = e->next;
}
return 0;
}
+void* dict_lookup(dict_t*h, const char*s)
+{
+ int l = strlen(s);
+ return dict_lookup2(h, s, l);
+}
char dict_del(dict_t*h, const char*s)
{
- unsigned int checksum = string_hash2(s) % h->hashsize;
- dictentry_t*head = h->slots[checksum];
+ if(!h->num)
+ return 0;
+ unsigned int hash = string_hash2(s) % h->hashsize;
+ int l = strlen(s);
+ dictentry_t*head = h->slots[hash];
dictentry_t*e = head, *prev=0;
while(e) {
- if(!strcmp(e->s, s)) {
+ if(e->len ==l && !memcmp(e->s, s, l)) {
dictentry_t*next = e->next;
- free((void*)e->s);
+ rfx_free((void*)e->s);
memset(e, 0, sizeof(dictentry_t));
- free(e);
+ rfx_free(e);
if(e == head) {
- h->slots[checksum] = 0;
+ h->slots[hash] = 0;
} else {
+ assert(prev);
prev->next = next;
}
+ h->num--;
return 1;
}
prev = e;
}
return 0;
}
+void dict_foreach_keyvalue(dict_t*h, void (*runFunction)(void*data, const char*key, void*val), void*data)
+{
+ int t;
+ for(t=0;t<h->hashsize;t++) {
+ dictentry_t*e = h->slots[t];
+ while(e) {
+ dictentry_t*next = e->next;
+ if(runFunction) {
+ char*s = strdup_n(e->s, e->len); //append \0
+ runFunction(data, s, e->data);
+ rfx_free(s);
+ }
+ e = e->next;
+ }
+ }
+}
void dict_foreach_value(dict_t*h, void (*runFunction)(void*))
{
int t;
dictentry_t*e = h->slots[t];
while(e) {
dictentry_t*next = e->next;
- free((void*)e->s);
+ rfx_free((void*)e->s);
if(freeFunction) {
freeFunction(e->data);
}
memset(e, 0, sizeof(dictentry_t));
- free(e);
+ rfx_free(e);
e = next;
}
}
- free(h->slots);h->slots = 0;
+ rfx_free(h->slots);
+ memset(h, 0, sizeof(dict_t));
}
void dict_clear(dict_t*h)
{
void dict_destroy(dict_t*dict)
{
dict_clear(dict);
- free(dict);
+ rfx_free(dict);
}
// ------------------------------- map_t --------------------------------------
void map_init(map_t*map)
{
map_internal_t*m;
- map->internal = (map_internal_t*)malloc(sizeof(map_internal_t));
- memset(map->internal, 0, sizeof(map_internal_t));
+ map->internal = (map_internal_t*)rfx_calloc(sizeof(map_internal_t));
m = (map_internal_t*)map->internal;
dict_init(&m->d);
}
void map_put(map_t*map, string_t t1, string_t t2)
{
map_internal_t*m = (map_internal_t*)map->internal;
- dict_put2(&m->d, string_cstr(&t1), (void*)string_cstr(&t2));
+ string_t s;
+ char* s1 = string_cstr(&t1);
+ dict_put2(&m->d, s1, (void*)string_cstr(&t2));
+ rfx_free(s1);
}
const char* map_lookup(map_t*map, const char*name)
{
const char*value = dict_lookup(&m->d, name);
return value;
}
+static void freestring(void*data)
+{
+ rfx_free(data);
+}
+static void dumpmapentry(void*data, const char*key, void*value)
+{
+ FILE*fi = (FILE*)data;
+ fprintf(fi, "%s=%s\n", key, (char*)value);
+}
void map_dump(map_t*map, FILE*fi, const char*prefix)
{
int t;
map_internal_t*m = (map_internal_t*)map->internal;
- fprintf(fi, "ERROR: map dumping not implemented yet\n");
- /*for(t=0;t<m->num;t++) {
- string_t s1 = stringarray_at2(&m->keys, t);
- string_t s2 = stringarray_at2(&m->values, t);
- fprintf(fi, "%s%s=%s\n", prefix, s1.str, s2.str);
- }*/
+ dict_foreach_keyvalue(&m->d, dumpmapentry, fi);
}
void map_clear(map_t*map)
{
map_internal_t*m = (map_internal_t*)map->internal;
- dict_clear(&m->d);
- free(m);
+ dict_free_all(&m->d, freestring);
+ rfx_free(m);
}
void map_destroy(map_t*map)
{
map_clear(map);
- free(map);
+ rfx_free(map);
}