diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/buffer.c | 257 | ||||
-rw-r--r-- | common/compat.c | 13 | ||||
-rw-r--r-- | common/compat.h | 3 |
3 files changed, 193 insertions, 80 deletions
diff --git a/common/buffer.c b/common/buffer.c index 0bba3bf..db23d79 100644 --- a/common/buffer.c +++ b/common/buffer.c @@ -8,44 +8,106 @@ * Memory Buffer */ +#define BUF_IS_EMPTY(b) ((b)->_pp == (b)->_rp) +#define BUF_IN_JOIN(b) (!BUF_IS_EMPTY(b) && *((b)->_rp - 1) != 0) +#define BUF_NEW_BLOCK(b) ((b)->_pp = (b)->_rp) + +/* TODO: Increase this size to 2048 once we're done debugging */ +#define BUF_INITIAL 80 +#define BUF_DELTA 16 + +#define INTERNAL_DATA(intl) ((void*)(((unsigned char*)(intl)) + sizeof(*(intl)))) + +#define FILL_BETWEEN(b, e, x) memset((b), x, ((char*)(e)) - ((char*)(b))); + /* * LEGEND: - * _al: allocated - * _dt: data + * _ft: first buffer block + * _dt: current buffer block * _rp: read/write point * _pp: parse/begin point */ +typedef struct ha_buffer_internal +{ + char* end; + struct ha_buffer_internal* next; +} +internal_t; + void buffer_bump(ha_buffer_t* buf, int count) { + int allocated; + internal_t* intl; + ASSERT(buf && count); if(ha_buferr(buf)) return; - if(buf->_rp + count >= buf->_dt + buf->_al) + ASSERT(BUF_DELTA < BUF_INITIAL); + + /* Handle this common case first for efficiency */ + if(buf->_rp + (count + BUF_DELTA) < buf->_dt->end) + return; + + /* Now when in joins we let it go closer */ + if(BUF_IN_JOIN(buf) && (buf->_rp + count < buf->_dt->end)) + return; + + /* Okay now we know we have to extend */ + allocated = buf->_dt->end - (char*)(buf->_dt); + ASSERT(allocated > 0 && (allocated % BUF_INITIAL) == 0); + + /* Enlarge the size as much as needed */ + do + { + allocated *= 2; + } + while(allocated < count); + + ASSERT(sizeof(internal_t) < allocated); + intl = (internal_t*)malloc(allocated); + if(!intl) + { + ha_messagex(LOG_CRIT, "out of memory"); + buf->_dt = NULL; + buf->_pp = buf->_rp = NULL; + return; + } + else { - char* old = buf->_dt; - int alloc = buf->_al; - int diff; + void* beg = INTERNAL_DATA(intl); + intl->end = ((char*)(intl) + allocated); + intl->next = NULL; - while((buf->_al + count) > alloc) - alloc *= 2; +#ifdef _DEBUG + FILL_BETWEEN(beg, intl->end, 0xCD); +#endif - buf->_dt = (char*)reallocf(buf->_dt, alloc * sizeof(char)); - if(!buf->_dt) + if(BUF_IN_JOIN(buf)) { - buf->_al = 0; - buf->_rp = buf->_pp = NULL; - ha_messagex(LOG_CRIT, "out of memory"); - return; - } + int diff = buf->_rp - buf->_pp; + + /* Always true in a join */ + ASSERT(buf->_pp < buf->_rp); - buf->_al = alloc; + /* Copy the memory and blank out old */ + memcpy(beg, buf->_pp, diff); +#ifdef _DEBUG + FILL_BETWEEN(buf->_pp, buf->_rp, 0xDD); +#endif + + buf->_pp = beg; + buf->_rp = buf->_pp + diff; + } + else + { + buf->_rp = buf->_pp = INTERNAL_DATA(intl); + } - diff = buf->_dt - old; - buf->_rp += diff; - buf->_pp += diff; + buf->_dt->next = intl; + buf->_dt = intl; } } @@ -53,39 +115,57 @@ void ha_bufinit(ha_buffer_t* buf) { ASSERT(buf); memset(buf, 0, sizeof(*buf)); - ha_bufreset(buf); + + ASSERT(BUF_INITIAL > sizeof(internal_t)); + buf->_ft = (internal_t*)malloc(BUF_INITIAL); + if(buf->_ft) + { + buf->_ft->end = ((char*)(buf->_ft) + BUF_INITIAL); + buf->_ft->next = NULL; + +#ifdef _DEBUG + FILL_BETWEEN(INTERNAL_DATA(buf->_ft), buf->_ft->end, 0xCD); +#endif + + ha_bufreset(buf); + } } void ha_bufreset(ha_buffer_t* buf) { - ASSERT(buf); +#ifdef _DEBUG + internal_t* intl; +#endif - if(!buf->_dt || buf->_al == 0) - { - buf->_dt = (char*)reallocf(buf->_dt, 256 * sizeof(char)); - if(!buf->_dt) - { - buf->_al = 0; - buf->_rp = buf->_pp = NULL; - ha_messagex(LOG_CRIT, "out of memory"); - return; - } + ASSERT(buf); + ASSERT(buf->_ft); - buf->_al = 256; - } +#ifdef _DEBUG + /* Go through all the buffers and set them to 0xCD */ + for(intl = buf->_ft; intl; intl = intl->next) + FILL_BETWEEN(INTERNAL_DATA(intl), intl->end, 0xCD); +#endif - buf->_rp = buf->_dt; - buf->_pp = buf->_dt; + buf->_dt = buf->_ft; + buf->_rp = buf->_pp = (char*)INTERNAL_DATA(buf->_ft); } void ha_buffree(ha_buffer_t* buf) { + internal_t* intl; + internal_t* next; + ASSERT(buf); - if(buf->_dt) - free(buf->_dt); + /* Go through free all the buffers and set them to 0xDD */ + for(intl = buf->_ft; intl; intl = next) + { + next = intl->next; + FILL_BETWEEN(INTERNAL_DATA(intl), intl->end, 0xDD); + free(intl); + } - buf->_al = 0; + buf->_ft = buf->_dt = NULL; buf->_rp = buf->_pp = NULL; } @@ -258,9 +338,8 @@ char* ha_bufmcat(ha_buffer_t* buf, ...) if(ha_buferr(buf)) return NULL; - /* Move up the block pointer if we're not joining strings */ - if(ha_buflen(buf) > 0 && *(buf->_rp - 1) != 0) - buf->_pp = buf->_rp; + if(!BUF_IN_JOIN(buf)) + BUF_NEW_BLOCK(buf); while((str = va_arg(ap, char*)) != NULL) { @@ -298,16 +377,15 @@ char* ha_bufncpy(ha_buffer_t* buf, const char* src, size_t len) if(ha_buferr(buf)) return NULL; - /* Move up the block pointer if we're not joining strings */ - if(ha_buflen(buf) > 0 && *(buf->_rp - 1) != 0) - buf->_pp = buf->_rp; - /* Always add one for the terminating char */ buffer_bump(buf, len + 1); if(ha_buferr(buf)) return NULL; + if(!BUF_IN_JOIN(buf)) + BUF_NEW_BLOCK(buf); + memcpy(buf->_rp, src, len * sizeof(char)); buf->_rp += (len + 1); *(buf->_rp - 1) = 0; @@ -324,17 +402,16 @@ void* ha_bufmalloc(ha_buffer_t* buf, size_t sz) return NULL; /* TODO: Align memory on an appropriate boundary here */ - - /* We're not working with strings so always bump the pointer up */ - buf->_pp = buf->_rp; - buffer_bump(buf, sz); if(ha_buferr(buf)) return NULL; + BUF_NEW_BLOCK(buf); + ret = (void*)buf->_pp; buf->_rp += sz; - return (void*)buf->_pp; + buf->_pp = buf->_rp; + return ret; } void* ha_bufmemdup(ha_buffer_t* buf, const void* src, size_t bytes) @@ -390,6 +467,9 @@ char* ha_bufenc64(ha_buffer_t* buf, const void* source, size_t len) if(ha_buferr(buf)) return NULL; + if(!BUF_IN_JOIN(buf)) + BUF_NEW_BLOCK(buf); + while(2 < len) { input[0] = *src++; @@ -450,6 +530,7 @@ void* ha_bufdec64(ha_buffer_t* buf, const char* src, size_t bytes) int state = 0; int ch; char* pos; + void* ret; size_t done = 0; ASSERT(buf && src); @@ -457,6 +538,8 @@ void* ha_bufdec64(ha_buffer_t* buf, const char* src, size_t bytes) if(ha_buferr(buf)) return NULL; + BUF_NEW_BLOCK(buf); + if(bytes == 0) bytes = ~0; @@ -472,7 +555,7 @@ void* ha_bufdec64(ha_buffer_t* buf, const char* src, size_t bytes) if(pos == 0) /* A non-base64 character. */ break; - buffer_bump(buf, 3); + buffer_bump(buf, 4); if(ha_buferr(buf)) return; @@ -480,8 +563,7 @@ void* ha_bufdec64(ha_buffer_t* buf, const char* src, size_t bytes) switch(state) { case 0: - *(buf->_rp++) = (pos - BASE64C) << 2; - done++; + *(buf->_rp) = (pos - BASE64C) << 2; state = 1; break; @@ -505,18 +587,23 @@ void* ha_bufdec64(ha_buffer_t* buf, const char* src, size_t bytes) state = 0; break; }; - - /* TODO: Validate ending and return error if invalid somehow */ } + if(state != 3) + buf->_rp++; + + /* TODO: Validate ending and return error if invalid somehow */ + /* If we were asked for a specific amount of bytes, then return null */ if(bytes != ~0 && bytes != done) return NULL; - return buf->_pp; + ret = (void*)buf->_pp; + buf->_pp = buf->_rp; + return ret; } -static const char HEXC[] = "0123456789ABCDEF"; +static const char HEXC[] = "0123456789abcdef"; char* ha_bufenchex(ha_buffer_t* buf, const void* source, size_t len) { @@ -530,21 +617,18 @@ char* ha_bufenchex(ha_buffer_t* buf, const void* source, size_t len) if(ha_buferr(buf)) return NULL; + if(!BUF_IN_JOIN(buf)) + BUF_NEW_BLOCK(buf); + while(len > 0) { j = *(src) >> 4 & 0xf; - if(j <= 9) - *(buf->_rp++) = (j + '0'); - else - *(buf->_rp++) = (j + 'a' - 10); + *(buf->_rp++) = HEXC[j]; j = *(src++) & 0xf; - len--; + *(buf->_rp++) = HEXC[j]; - if(j <= 9) - *(buf->_rp++) = (j + '0'); - else - *(buf->_rp++) = (j + 'a' - 10); + len--; } *(buf->_rp++) = 0; @@ -553,10 +637,11 @@ char* ha_bufenchex(ha_buffer_t* buf, const void* source, size_t len) void* ha_bufdechex(ha_buffer_t* buf, const char* src, size_t bytes) { - unsigned short a; - unsigned short b; + unsigned short j; size_t done = 0; + int state = 0; char* pos; + void* ret; ASSERT(buf && src); @@ -573,29 +658,41 @@ void* ha_bufdechex(ha_buffer_t* buf, const char* src, size_t bytes) if(ha_buferr(buf)) return NULL; - while(src[0] && src[1] && done < bytes) + BUF_NEW_BLOCK(buf); + + while(src[0] && done < bytes) { /* Find the position */ - pos = strchr(HEXC, src[0]); + pos = strchr(HEXC, tolower(src[0])); if(pos == 0) break; - a = HEXC - pos; - - pos = strchr(HEXC, src[1]); - if(pos == 0); - break; + j = pos - HEXC; - b = HEXC - pos; + if(!state) + { + *(buf->_rp) = (j & 0xf) << 4; + state = 1; + } + else + { + *(buf->_rp++) |= (j & 0xf); + done++; + state = 0; + } - *(buf->_rp++) = ((a & 0xf) << 4) | (b & 0xf); - src += 2; - done++; + src++; } + /* All bytes have to come in pairs */ + if(state != 0) + return NULL; + /* If we were asked for a specific amount of bytes, then return null */ if(bytes != ~0 && bytes != done) return NULL; - return buf->_pp; + ret = (void*)buf->_pp; + buf->_pp = buf->_rp; + return ret; } diff --git a/common/compat.c b/common/compat.c index 6a4b914..5618ee5 100644 --- a/common/compat.c +++ b/common/compat.c @@ -28,3 +28,16 @@ char* strlwr(char* s) return s; } #endif + +#ifndef HAVE_STRUPR +char* strupr(char* s) +{ + char* t = s; + while(*t) + { + *t = toupper(*t); + t++; + } + return s; +} +#endif diff --git a/common/compat.h b/common/compat.h index c250db1..bb7311c 100644 --- a/common/compat.h +++ b/common/compat.h @@ -36,5 +36,8 @@ void* reallocf(void* p, size_t sz); char* strlwr(char* s); #endif +#ifndef HAVE_STRUPR +char* strupr(char* s); +#endif #endif /* _COMPAT_H_ */ |