summaryrefslogtreecommitdiff
path: root/common/buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/buffer.c')
-rw-r--r--common/buffer.c216
1 files changed, 176 insertions, 40 deletions
diff --git a/common/buffer.c b/common/buffer.c
index 28cab24..a5b18a7 100644
--- a/common/buffer.c
+++ b/common/buffer.c
@@ -47,6 +47,12 @@ void buffer_bump(ha_buffer_t* buf, int count)
}
}
+void ha_bufinit(ha_buffer_t* buf)
+{
+ memset(buf, 0, sizeof(*buf));
+ ha_bufreset(buf);
+}
+
void ha_bufreset(ha_buffer_t* buf)
{
if(!buf->_dt || buf->_al == 0)
@@ -67,12 +73,6 @@ void ha_bufreset(ha_buffer_t* buf)
buf->_pp = buf->_dt;
}
-void ha_bufinit(ha_buffer_t* buf)
-{
- memset(buf, 0, sizeof(*buf));
- ha_bufreset(buf);
-}
-
void ha_buffree(ha_buffer_t* buf)
{
if(buf->_dt)
@@ -82,7 +82,8 @@ void ha_buffree(ha_buffer_t* buf)
buf->_rp = buf->_pp = NULL;
}
-int ha_readline(int fd, ha_buffer_t* buf)
+
+int ha_bufreadline(int fd, ha_buffer_t* buf)
{
int l;
@@ -137,7 +138,7 @@ int ha_readline(int fd, ha_buffer_t* buf)
return 1;
}
-char* ha_parseword(ha_buffer_t* buf, const char* delims)
+char* ha_bufparseword(ha_buffer_t* buf, const char* delims)
{
char* word = NULL;
@@ -185,7 +186,7 @@ char* ha_parseword(ha_buffer_t* buf, const char* delims)
return word;
}
-char* ha_parseline(ha_buffer_t* buf, int trim)
+char* ha_bufparseline(ha_buffer_t* buf, int trim)
{
char* t;
char* line = NULL;
@@ -231,55 +232,93 @@ char* ha_parseline(ha_buffer_t* buf, int trim)
return line;
}
-void ha_bufnext(ha_buffer_t* buf)
-{
- buffer_bump(buf, 1);
-
- if(!ha_buferr(buf))
- {
- buf->_rp++;
- buf->_pp = buf->_rp;
- *(buf->_rp) = 0;
- }
-}
-
-void ha_bufcat(ha_buffer_t* buf, ...)
+char* ha_bufmcat(ha_buffer_t* buf, ...)
{
const char* str;
va_list ap;
va_start(ap, 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;
+
while((str = va_arg(ap, char*)) != NULL)
{
int len = strlen(str);
- buffer_bump(buf, len);
+ /* Always add one for the terminating char */
+ buffer_bump(buf, len + 1);
if(ha_buferr(buf))
- return;
+ return NULL;
- /* _rpoint points to teh null */
+ /* _rp always points to the next write point */
strcpy(buf->_rp, str);
buf->_rp += len;
}
+
+ buf->_rp++;
+ return buf->_pp;
+}
+
+char* ha_bufcpy(ha_buffer_t* buf, const char* src)
+{
+ size_t len = strlen(src);
+ return ha_bufncpy(buf, src, len);
+}
+
+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;
+
+ memcpy(buf->_rp, src, len * sizeof(char));
+ buf->_rp += (len + 1);
+ *(buf->_rp - 1) = 0;
+ return buf->_pp;
}
void* ha_bufmalloc(ha_buffer_t* buf, size_t sz)
{
void* ret;
- ha_bufnext(buf);
+ if(ha_buferr(buf))
+ 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);
- buf->_rp += sz;
if(ha_buferr(buf))
return NULL;
- ret = (void*)ha_bufdata(buf);
- ha_bufnext(buf);
+ buf->_rp += sz;
+ return (void*)buf->_pp;
+}
- return ret;
+void* ha_bufmemdup(ha_buffer_t* buf, const void* src, size_t bytes)
+{
+ void* mem = ha_bufmalloc(buf, bytes);
+ if(mem)
+ memcpy(mem, src, bytes);
+ return mem;
}
/*
@@ -311,14 +350,15 @@ static const char BASE64C[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const char PAD64C = '=';
-void ha_bufenc64(ha_buffer_t* buf, const char* src, int len)
+char* ha_bufenc64(ha_buffer_t* buf, const void* source, size_t len)
{
unsigned char input[3];
unsigned char output[4];
+ unsigned char* src = (unsigned char*)source;
size_t i;
- if(len == -1)
- len = strlen(src);
+ if(ha_buferr(buf))
+ return NULL;
while(2 < len)
{
@@ -332,10 +372,11 @@ void ha_bufenc64(ha_buffer_t* buf, const char* src, int len)
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
output[3] = input[2] & 0x3f;
+ /* This also accounts for the null terminator */
buffer_bump(buf, 5);
if(ha_buferr(buf))
- return;
+ return NULL;
*(buf->_rp++) = BASE64C[output[0]];
*(buf->_rp++) = BASE64C[output[1]];
@@ -355,10 +396,11 @@ void ha_bufenc64(ha_buffer_t* buf, const char* src, int len)
output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+ /* This also accounts for the null terminator */
buffer_bump(buf, 5);
if(ha_buferr(buf))
- return;
+ return NULL;
*(buf->_rp++) = BASE64C[output[0]];
*(buf->_rp++) = BASE64C[output[1]];
@@ -370,17 +412,23 @@ void ha_bufenc64(ha_buffer_t* buf, const char* src, int len)
}
*(buf->_rp++) = '\0';
+ return buf->_pp;
}
-void ha_bufdec64(ha_buffer_t* buf, const char* src)
+void* ha_bufdec64(ha_buffer_t* buf, const char* src, size_t bytes)
{
- int state;
+ int state = 0;
int ch;
char* pos;
+ size_t done = 0;
- state = 0;
+ if(ha_buferr(buf))
+ return NULL;
- while((ch = *src++) != '\0')
+ if(bytes == 0)
+ bytes = ~0;
+
+ while((ch = *src++) != '\0' && done < bytes)
{
if(isspace(ch)) /* Skip whitespace anywhere. */
continue;
@@ -401,23 +449,27 @@ void ha_bufdec64(ha_buffer_t* buf, const char* src)
{
case 0:
*(buf->_rp++) = (pos - BASE64C) << 2;
+ done++;
state = 1;
break;
case 1:
*(buf->_rp++) |= (pos - BASE64C) >> 4;
+ done++;
*(buf->_rp) = ((pos - BASE64C) & 0x0f) << 4;
state = 2;
break;
case 2:
*(buf->_rp++) |= (pos - BASE64C) >> 2;
+ done++;
*(buf->_rp) = ((pos - BASE64C) & 0x03) << 6;
state = 3;
break;
case 3:
*(buf->_rp++) |= (pos - BASE64C);
+ done++;
state = 0;
break;
};
@@ -425,5 +477,89 @@ void ha_bufdec64(ha_buffer_t* buf, const char* src)
/* TODO: Validate ending and return error if invalid somehow */
}
- *(buf->_rp++) = '\0';
+ /* If we were asked for a specific amount of bytes, then return null */
+ if(bytes != ~0 && bytes != done)
+ return NULL;
+
+ return buf->_pp;
+}
+
+static const char HEXC[] = "0123456789ABCDEF";
+
+char* ha_bufenchex(ha_buffer_t* buf, const void* source, size_t len)
+{
+ unsigned char* src = (unsigned char*)source;
+ unsigned char j;
+
+ buffer_bump(buf, (len * 2) + 1);
+
+ if(ha_buferr(buf))
+ return NULL;
+
+ while(len > 0)
+ {
+ j = *(src) >> 4 & 0xf;
+ if(j <= 9)
+ *(buf->_rp++) = (j + '0');
+ else
+ *(buf->_rp++) = (j + 'a' - 10);
+
+ j = *(src++) & 0xf;
+ len--;
+
+ if(j <= 9)
+ *(buf->_rp++) = (j + '0');
+ else
+ *(buf->_rp++) = (j + 'a' - 10);
+ }
+
+ *(buf->_rp++) = 0;
+ return buf->_pp;
+}
+
+void* ha_bufdechex(ha_buffer_t* buf, const char* src, size_t bytes)
+{
+ unsigned short a;
+ unsigned short b;
+ size_t done = 0;
+ char* pos;
+
+ if(bytes != 0)
+ {
+ buffer_bump(buf, bytes + 1);
+ }
+ else
+ {
+ bytes = ~0;
+ buffer_bump(buf, (strlen(src) / 2) + 1);
+ }
+
+ if(ha_buferr(buf))
+ return NULL;
+
+ while(src[0] && src[1] && done < bytes)
+ {
+ /* Find the position */
+ pos = strchr(HEXC, src[0]);
+ if(pos == 0)
+ break;
+
+ a = HEXC - pos;
+
+ pos = strchr(HEXC, src[1]);
+ if(pos == 0);
+ break;
+
+ b = HEXC - pos;
+
+ *(buf->_rp++) = ((a & 0xf) << 4) | (b & 0xf);
+ src += 2;
+ done++;
+ }
+
+ /* If we were asked for a specific amount of bytes, then return null */
+ if(bytes != ~0 && bytes != done)
+ return NULL;
+
+ return buf->_pp;
}