155 lines
3.7 KiB
C
Executable File
155 lines
3.7 KiB
C
Executable File
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
#include "iobuffer.h"
|
|
|
|
#define ALIGN(x, a) (((x) + (a)-1) & ~((a)-1))
|
|
|
|
static int pow2gt (int x) {
|
|
--x;
|
|
x|=x>>1;
|
|
x|=x>>2;
|
|
x|=x>>4;
|
|
x|=x>>8;
|
|
x|=x>>16;
|
|
return x+1;
|
|
}
|
|
|
|
|
|
void iobuffer_init(iobuffer* p) {
|
|
p->iodata = NULL;
|
|
p->size = 0;
|
|
p->capacity = 0;
|
|
}
|
|
|
|
void iobuffer_deinit(iobuffer* p) {
|
|
free(p->iodata);
|
|
p->iodata = NULL;
|
|
p->size = 0;
|
|
p->capacity = 0;
|
|
}
|
|
|
|
int iobuffer_reserve(iobuffer* p, int cap) {
|
|
if (cap > p->capacity) {
|
|
// round up
|
|
//extra 1 byte for null-terminated char,
|
|
int alloc = pow2gt(cap+1);
|
|
|
|
printf(" allcate iobuffer %d=>%d\n", cap, alloc);
|
|
// at least 16 byte align for AES encrypt
|
|
alloc = ALIGN(alloc,16);
|
|
|
|
assert(alloc >= cap + 1);
|
|
assert(alloc >= p->size + 1);
|
|
|
|
char* new_data = (char*)realloc(p->iodata, alloc);
|
|
if (!new_data) {
|
|
printf("can't allcate iobuffer %d=>%d\n", p->capacity, alloc);
|
|
return ENOMEM;
|
|
}
|
|
p->iodata = new_data;
|
|
p->capacity = alloc - 1;
|
|
p->iodata[p->size] = '\0';
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int iobuffer_freesize(iobuffer* p){
|
|
assert(p->capacity >= p->size);
|
|
return p->capacity - p->size;
|
|
}
|
|
|
|
|
|
int iobuffer_appendData(iobuffer* p, const void* data, int count) {
|
|
if (count <= 0)
|
|
return EINVAL;
|
|
|
|
int ret = iobuffer_reserve(p, p->size + count);
|
|
if (ret == 0) {
|
|
memcpy(p->iodata + p->size, data, count);
|
|
p->size += count;
|
|
p->iodata[p->size] = '\0';
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int iobuffer_append_string(iobuffer* p, const void* str)
|
|
{
|
|
return iobuffer_appendData(p, str, strlen(str));
|
|
}
|
|
|
|
int iobuffer_prependData(iobuffer* p, const void* data, int count) {
|
|
int ret = iobuffer_reserve(p, p->size + count);
|
|
if (ret == 0) {
|
|
memmove(p->iodata + count, p->iodata, p->size);
|
|
memcpy(p->iodata, data, count);
|
|
p->size += count;
|
|
p->iodata[p->size] = '\0';
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void iobuffer_erase(iobuffer* p, int from, int to) {
|
|
int n = to - from;
|
|
if (n > 0) {
|
|
if ( n != p->size ){
|
|
memmove(p->iodata + from, p->iodata + to, p->size - to);
|
|
}
|
|
p->size -= n;
|
|
p->iodata[p->size] = '\0';
|
|
}
|
|
}
|
|
|
|
void iobuffer_eraseall(iobuffer* p)
|
|
{
|
|
iobuffer_erase(p, 0, p->size);
|
|
}
|
|
|
|
|
|
static int ioprintf(iobuffer* this, const char *format, va_list ap)
|
|
{
|
|
int n;
|
|
int buflen = this->capacity - this->size;
|
|
if ( buflen < 128) {
|
|
if ( 0 != iobuffer_reserve(this, this->size + 1024))
|
|
return ENOMEM;
|
|
buflen = this->capacity - this->size;
|
|
}
|
|
|
|
while(1) {
|
|
char * buf = this->iodata + this->size;
|
|
n = vsnprintf(buf, buflen, format, ap);
|
|
if ( n <= 0) {
|
|
printf("vsnprintf err %d/%d,format=%s", n, errno, format);
|
|
return -2;
|
|
}
|
|
if ( n > buflen) {
|
|
if ( 0 != iobuffer_reserve(this, this->size + n + 1024))
|
|
return ENOMEM;
|
|
buflen = this->capacity - this->size;
|
|
}
|
|
else {
|
|
this->size += n;
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
int iobuffer_printf(iobuffer* p, const char *format, ...){
|
|
int result;
|
|
va_list ap;
|
|
va_start(ap, format);
|
|
result = ioprintf(p, format, ap);
|
|
va_end(ap);
|
|
return result;
|
|
}
|
|
|
|
void iobuffer_read(iobuffer* this, void* to, int size)
|
|
{
|
|
memcpy(to, this->iodata, size);
|
|
iobuffer_erase(this, 0, size);
|
|
}
|