#include #include #include #include #include #include #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); }