initial commit
This commit is contained in:
154
common/iobuffer/iobuffer.c
Executable file
154
common/iobuffer/iobuffer.c
Executable file
@@ -0,0 +1,154 @@
|
||||
#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);
|
||||
}
|
||||
42
common/iobuffer/iobuffer.h
Executable file
42
common/iobuffer/iobuffer.h
Executable file
@@ -0,0 +1,42 @@
|
||||
#ifndef IOBUFFER_H_INCLUDED
|
||||
#define IOBUFFER_H_INCLUDED
|
||||
|
||||
typedef struct {
|
||||
char* iodata; //if not null, always 16 byte alignment for better AES encrypt
|
||||
int size;
|
||||
int capacity; //capacity, always >= size
|
||||
} iobuffer;
|
||||
|
||||
void iobuffer_init(iobuffer* p);
|
||||
void iobuffer_deinit(iobuffer* p);
|
||||
|
||||
/* 申请cap大小的缓冲 */
|
||||
int iobuffer_reserve(iobuffer* p, int cap);
|
||||
|
||||
/* 获取剩余缓冲的大小 */
|
||||
int iobuffer_freesize(iobuffer* p);
|
||||
|
||||
/* to后的data移到from位置 */
|
||||
void iobuffer_erase(iobuffer* p, int from, int to);
|
||||
|
||||
|
||||
/* 设置size=0, 清除所有data */
|
||||
void iobuffer_eraseall(iobuffer* p);
|
||||
|
||||
/* 读size大小的数据到to的内存 */
|
||||
void iobuffer_read(iobuffer* p, void* to, int size);
|
||||
|
||||
/* 插入字符串 */
|
||||
int iobuffer_append_string(iobuffer* p, const void* str);
|
||||
|
||||
/* 插入数据 */
|
||||
int iobuffer_appendData(iobuffer* p, const void* iodata, int count);
|
||||
|
||||
/* 插入格式打印:iobuffer_printf(p, "i m %s, years old", "liming", 5)*/
|
||||
int iobuffer_printf(iobuffer* p, const char *format, ...) __attribute__((__format__ (printf, 2, 3)));/* first arg is this pointer */
|
||||
|
||||
|
||||
// Don't call it but change your code logic
|
||||
// int iobuffer_prependData(iobuffer* p, const void* iodata, int count);
|
||||
|
||||
#endif /* IOBUFFER_H_INCLUDED */
|
||||
Reference in New Issue
Block a user