-
-
[求助]grow_buf
-
发表于: 2015-8-14 20:51 1972
-
#ifndef _GROW_BUF_H_
#define _GROW_BUF_H_
#include "list.h"
// 地址-长度
struct addr_len {
char *p;
int len;
};
// 偏移-长度
struct offset_len {
int offset;
int len;
};
// 位置
struct position {
union {
char *p;
int offset;
};
enum { ADDR, OFFSET } type;
};
// 位置-长度
struct pos_len {
struct position pos;
int len;
};
// 自动扩容缓冲区单元
struct grow_buf_unit {
int offset;
struct addr_len buf;
struct list_head list;
};
// 自动扩容缓冲区
struct grow_buf {
int default_grow;
int size;
int free;
struct list_head head;
};
struct grow_buf *grow_buf_alloc(int size);
void grow_buf_free(struct grow_buf *buf);
int gb_read_buf(struct grow_buf *gb, struct pos_len *pos, struct addr_len *result);
int gb_write_buf(struct grow_buf *gb, struct position *pos, struct addr_len *buf, int grow);
int gb_read_file(struct grow_buf *gb, struct pos_len *pos, int fd, int offset);
int gb_write_file(struct grow_buf *gb, struct position *pos, int fd, int offset, int grow);
int gb_copy(struct grow_buf *to_gb, struct position *to_pos,
struct grow_buf *from_gb, struct pos_len *from_pos);
/******************************************************
* 提供以下辅助函数: *
* 1. 方便表达"全部读取","接着空闲位置写"等含义 *
* 2. 避免为struct pos_len *pos参数制定复杂规则 *
******************************************************/
// grow_buf开始位置
#define grow_buf_start(gb) ({ \
struct grow_buf_unit *unit \
= container_of((gb)->head.next, struct grow_buf_unit, list); \
unit->buf.p = unit->buf.p; \
})
// grow_buf空闲位置,没有空闲位置时,返回NULL
#define grow_buf_end(gb) ({ \
char *p = NULL; \
if ((gb)->free > 0) { \
struct list_head *pos, *n; \
struct grow_buf_unit *unit; \
list_for_each_safe(pos, n, &(gb)->head) { \
unit = container_of((gb)->head.prev, struct grow_buf_unit, list); \
if ((gb)->size - (gb)->free >= unit->offset \
&& (gb)->size - (gb)->free < unit->offset + unit->buf.len) { \
p = unit->buf.p + (((gb)->size - (gb)->free) - unit->offset); \
break; \
} \
} \
} \
p = p; \
})
// grow_buf已写入长度
#define grow_buf_write_len(gb) ((gb)->size - (gb)->free)
#endif
------------------------------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "grow-buf.h"
/*
* grow_buf扩容
*/
static int buf_growing(struct grow_buf *buf, int grow)
{
struct grow_buf_unit *unit = NULL;
unit = malloc(sizeof(struct grow_buf_unit));
if (unit == NULL) {
printf("%s(), %d: malloc failed\n", __FUNCTION__, __LINE__);
goto err;
}
unit->buf.p = malloc(grow);
if (unit->buf.p == NULL) {
printf("%s(), %d: malloc failed\n", __FUNCTION__, __LINE__);
goto err;
}
unit->buf.len = grow;
unit->offset = buf->size;
list_add_tail(&unit->list, &buf->head);
buf->size += unit->buf.len;
buf->free += unit->buf.len;
printf("%s(), %d: grew successed, %d -> %p\n", __FUNCTION__, __LINE__, grow, unit->buf.p);
return 0;
err:
if (unit != NULL) {
if (unit->buf.p != NULL)
free(unit->buf.p);
free(unit);
}
return -1;
}
/*
* 通过地址查找unit
*/
#define gb_unit_by_addr(gb, addr) ({ \
struct list_head *_pos, *_n; \
struct grow_buf_unit *unit; \
list_for_each_safe(_pos, _n, &(gb)->head) { \
unit = container_of(_pos, struct grow_buf_unit, list); \
if ((addr) >= unit->buf.p && (addr) < unit->buf.p+unit->buf.len) \
break; \
} \
if (_pos == &(gb)->head) \
unit = NULL; \
unit = unit; \
})
/*
* 通过偏移查找unit
*/
#define gb_unit_by_offset(gb, _offset) ({ \
struct list_head *_pos, *_n; \
struct grow_buf_unit *unit; \
list_for_each_safe(_pos, _n, &(gb)->head) { \
unit = container_of(_pos, struct grow_buf_unit, list); \
if ((_offset) >= unit->offset && (_offset) < unit->offset+unit->buf.len) \
break; \
} \
if (_pos == &(gb)->head) \
unit = NULL; \
unit = unit; \
})
/*
* grow_buf分配
*
* size: 初始化大小,同时也作为默认增长大小
*/
struct grow_buf *grow_buf_alloc(int size)
{
struct grow_buf *gb = NULL;
gb = malloc(sizeof(struct grow_buf));
if (gb == NULL) {
printf("%s(), %d: malloc failed\n", __FUNCTION__, __LINE__);
goto err;
}
gb->default_grow = size;
gb->size = 0;
gb->free = 0;
INIT_LIST_HEAD(&gb->head);
if (buf_growing(gb, size) < 0)
goto err;
return gb;
err:
grow_buf_free(gb);
return NULL;
}
/*
* grow_buf释放
*/
void grow_buf_free(struct grow_buf *buf)
{
if (buf != NULL)
{
struct list_head *_pos, *_n;
struct grow_buf_unit *unit;
list_for_each_safe(_pos, _n, &buf->head)
{
unit = container_of(_pos, struct grow_buf_unit, list);
list_del_init(&unit->list);
if (unit->buf.p != NULL)
free(unit->buf.p);
free(unit);
}
free(buf);
}
}
/*
* grow_buf读取,如果读取的数据跨越unit,需要读取多次,直到pos->len=0
*
* pos: 读取位置,程序执行后,会将其更新为下次要读的位置和长度
* result: 读取结果
*/
int gb_read_buf(struct grow_buf *gb, struct pos_len *pos, struct addr_len *result)
{
struct grow_buf_unit *unit = NULL;
if (pos->len == 0) {
result->p = NULL;
result->len = 0;
return 0;
}
if (pos->len < 0)
return -1;
switch (pos->pos.type)
{
case ADDR:
if (pos->pos.p == NULL)
return -1;
unit = gb_unit_by_addr(gb, pos->pos.p);
break;
case OFFSET:
if (pos->pos.offset < 0)
return -1;
unit = gb_unit_by_offset(gb, pos->pos.offset);
pos->pos.type = ADDR;
pos->pos.p = unit->buf.p + (pos->pos.offset - unit->offset);
break;
default:
break;
}
if (unit == NULL || grow_buf_write_len(gb)
- (unit->offset + (pos->pos.p - unit->buf.p)) < pos->len)
{
printf("%s(), %d: beyond grow_buf scope\n", __FUNCTION__, __LINE__);
return -1;
}
result->p = pos->pos.p;
if ((result->len = (unit->buf.p
+ unit->buf.len)-pos->pos.p) <= pos->len)
{
unit = container_of(unit->list.next, struct grow_buf_unit, list);
pos->pos.p = unit->buf.p;
} else {
result->len = pos->len;
pos->pos.p += result->len;
}
pos->len -= result->len;
return result->len;
}
/*
* grow_buf写入
*
* pos: 写入位置 (pos->p=NULL,可能由于无空闲空间导致)
* buf: 希望写入的数据
* grow: 当gb剩余空间不足时,希望增长的大小 (<=0表示按默认大小增长)
* 最终增长大小,根据grow,default_grow,buf->len确定
*/
int gb_write_buf(struct grow_buf *gb, struct position *pos, struct addr_len *buf, int grow)
{
struct grow_buf_unit *unit = NULL;
int offset = 0, _offset = 0;
int len = buf->len;
if (buf->len == 0)
return 0;
if (buf->len < 0)
return -1;
if (grow <= 0)
grow = gb->default_grow;
switch (pos->type)
{
case ADDR:
if (pos->p != NULL) {
if ((unit = gb_unit_by_addr(gb, pos->p)) == NULL)
return -1;
offset = pos->p - unit->buf.p;
} else {
if (gb->free > 0)
return -1;
printf("%s(), %d: !!!!!!!!!!!!!!!!!!!!!!\n", __FUNCTION__, __LINE__);
grow = grow < buf->len ? buf->len : grow;
if (buf_growing(gb, grow) < 0)
return -1;
unit = container_of(gb->head.prev, struct grow_buf_unit, list);
offset = 0;
}
break;
case OFFSET:
if (pos->offset < 0)
return -1;
if ((unit = gb_unit_by_offset(gb, pos->offset)) == NULL)
{
printf("%s(), %d: !!!!!!!!!!!!!!!!!!!!!!\n", __FUNCTION__, __LINE__);
grow = grow < (pos->offset - gb->size + buf->len) ?
(pos->offset - gb->size + buf->len) : grow;
if (buf_growing(gb, grow) < 0)
return -1;
unit = container_of(gb->head.prev, struct grow_buf_unit, list);
}
offset = pos->offset - unit->offset;
break;
default:
printf("%s(), %d: wrong position type !\n", __FUNCTION__, __LINE__);
return -1;
}
while (1)
{
int _len = (unit->offset+unit->buf.len)-offset;
if (_len > len)
_len = len;
printf("write: %p, len: %d\n", unit->buf.p+offset, _len);
printf("%d, %d\n", offset, _offset);
memcpy(unit->buf.p+offset, buf->p+_offset, _len);
_offset += _len;
if (unit->offset+offset+_len > grow_buf_write_len(gb))
gb->free -= (unit->offset+offset+_len - grow_buf_write_len(gb));
if ((len -= _len) == 0)
break;
if (buf_growing(gb, grow < len ? len : grow) < 0)
return -1;
unit = container_of(unit->list.next, struct grow_buf_unit, list);
offset = 0;
}
return 0;
}
/*
* 读取grow_buf数据到文件
*
* pos: 读取位置
* offset: 文件偏移
*/
int gb_read_file(struct grow_buf *gb, struct pos_len *pos, int fd, int offset)
{
return 0;
}
/*
* 将文件数据写入grow_buf
*
* pos: 写入位置 (NULL表示空闲空间开始位置)
* offset: 文件偏移
* grow: 当gb剩余空间不足时,希望增长的大小 (0表示按默认大小增长)
*/
int gb_write_file(struct grow_buf *gb, struct position *pos, int fd, int offset, int grow)
{
return 0;
}
/*
* grow_buf之间数据复制
*
* to_pos: 写入位置 (NULL表示空闲空间开始位置)
* pos: 读取位置
*/
int gb_copy(struct grow_buf *to_gb, struct position *to_pos,
struct grow_buf *from_gb, struct pos_len *from_pos)
{
return 0;
}
int main()
{
struct grow_buf *gb = NULL;
struct position pos;
struct addr_len buf;
struct pos_len _pos;
int i, ret;
gb = grow_buf_alloc(128);
if (gb == NULL)
goto err;
// write
buf.p = "0123456789";
buf.len = 10;
for (i = 0; i < 15; i ++)
{
pos.type = ADDR;
pos.p = grow_buf_end(gb);
//pos.type = OFFSET;
//pos.offset = buf.len * i;
ret = gb_write_buf(gb, &pos, &buf, 0);
if (ret < 0)
goto err;
}
// read
//_pos.pos.type = ADDR;
//_pos.pos.p = grow_buf_start(gb);
_pos.pos.type = OFFSET;
_pos.pos.p = 0;
_pos.len = 140;
while (1)
{
ret = gb_read_buf(gb, &_pos, &buf);
if (ret < 0)
goto err;
printf("%d\n", buf.len);
printf("%s\n", buf.p);
if (_pos.len == 0)
break;
}
grow_buf_free(gb);
return 0;
err:
grow_buf_free(gb);
return -1;
}
#define _GROW_BUF_H_
#include "list.h"
// 地址-长度
struct addr_len {
char *p;
int len;
};
// 偏移-长度
struct offset_len {
int offset;
int len;
};
// 位置
struct position {
union {
char *p;
int offset;
};
enum { ADDR, OFFSET } type;
};
// 位置-长度
struct pos_len {
struct position pos;
int len;
};
// 自动扩容缓冲区单元
struct grow_buf_unit {
int offset;
struct addr_len buf;
struct list_head list;
};
// 自动扩容缓冲区
struct grow_buf {
int default_grow;
int size;
int free;
struct list_head head;
};
struct grow_buf *grow_buf_alloc(int size);
void grow_buf_free(struct grow_buf *buf);
int gb_read_buf(struct grow_buf *gb, struct pos_len *pos, struct addr_len *result);
int gb_write_buf(struct grow_buf *gb, struct position *pos, struct addr_len *buf, int grow);
int gb_read_file(struct grow_buf *gb, struct pos_len *pos, int fd, int offset);
int gb_write_file(struct grow_buf *gb, struct position *pos, int fd, int offset, int grow);
int gb_copy(struct grow_buf *to_gb, struct position *to_pos,
struct grow_buf *from_gb, struct pos_len *from_pos);
/******************************************************
* 提供以下辅助函数: *
* 1. 方便表达"全部读取","接着空闲位置写"等含义 *
* 2. 避免为struct pos_len *pos参数制定复杂规则 *
******************************************************/
// grow_buf开始位置
#define grow_buf_start(gb) ({ \
struct grow_buf_unit *unit \
= container_of((gb)->head.next, struct grow_buf_unit, list); \
unit->buf.p = unit->buf.p; \
})
// grow_buf空闲位置,没有空闲位置时,返回NULL
#define grow_buf_end(gb) ({ \
char *p = NULL; \
if ((gb)->free > 0) { \
struct list_head *pos, *n; \
struct grow_buf_unit *unit; \
list_for_each_safe(pos, n, &(gb)->head) { \
unit = container_of((gb)->head.prev, struct grow_buf_unit, list); \
if ((gb)->size - (gb)->free >= unit->offset \
&& (gb)->size - (gb)->free < unit->offset + unit->buf.len) { \
p = unit->buf.p + (((gb)->size - (gb)->free) - unit->offset); \
break; \
} \
} \
} \
p = p; \
})
// grow_buf已写入长度
#define grow_buf_write_len(gb) ((gb)->size - (gb)->free)
#endif
------------------------------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "grow-buf.h"
/*
* grow_buf扩容
*/
static int buf_growing(struct grow_buf *buf, int grow)
{
struct grow_buf_unit *unit = NULL;
unit = malloc(sizeof(struct grow_buf_unit));
if (unit == NULL) {
printf("%s(), %d: malloc failed\n", __FUNCTION__, __LINE__);
goto err;
}
unit->buf.p = malloc(grow);
if (unit->buf.p == NULL) {
printf("%s(), %d: malloc failed\n", __FUNCTION__, __LINE__);
goto err;
}
unit->buf.len = grow;
unit->offset = buf->size;
list_add_tail(&unit->list, &buf->head);
buf->size += unit->buf.len;
buf->free += unit->buf.len;
printf("%s(), %d: grew successed, %d -> %p\n", __FUNCTION__, __LINE__, grow, unit->buf.p);
return 0;
err:
if (unit != NULL) {
if (unit->buf.p != NULL)
free(unit->buf.p);
free(unit);
}
return -1;
}
/*
* 通过地址查找unit
*/
#define gb_unit_by_addr(gb, addr) ({ \
struct list_head *_pos, *_n; \
struct grow_buf_unit *unit; \
list_for_each_safe(_pos, _n, &(gb)->head) { \
unit = container_of(_pos, struct grow_buf_unit, list); \
if ((addr) >= unit->buf.p && (addr) < unit->buf.p+unit->buf.len) \
break; \
} \
if (_pos == &(gb)->head) \
unit = NULL; \
unit = unit; \
})
/*
* 通过偏移查找unit
*/
#define gb_unit_by_offset(gb, _offset) ({ \
struct list_head *_pos, *_n; \
struct grow_buf_unit *unit; \
list_for_each_safe(_pos, _n, &(gb)->head) { \
unit = container_of(_pos, struct grow_buf_unit, list); \
if ((_offset) >= unit->offset && (_offset) < unit->offset+unit->buf.len) \
break; \
} \
if (_pos == &(gb)->head) \
unit = NULL; \
unit = unit; \
})
/*
* grow_buf分配
*
* size: 初始化大小,同时也作为默认增长大小
*/
struct grow_buf *grow_buf_alloc(int size)
{
struct grow_buf *gb = NULL;
gb = malloc(sizeof(struct grow_buf));
if (gb == NULL) {
printf("%s(), %d: malloc failed\n", __FUNCTION__, __LINE__);
goto err;
}
gb->default_grow = size;
gb->size = 0;
gb->free = 0;
INIT_LIST_HEAD(&gb->head);
if (buf_growing(gb, size) < 0)
goto err;
return gb;
err:
grow_buf_free(gb);
return NULL;
}
/*
* grow_buf释放
*/
void grow_buf_free(struct grow_buf *buf)
{
if (buf != NULL)
{
struct list_head *_pos, *_n;
struct grow_buf_unit *unit;
list_for_each_safe(_pos, _n, &buf->head)
{
unit = container_of(_pos, struct grow_buf_unit, list);
list_del_init(&unit->list);
if (unit->buf.p != NULL)
free(unit->buf.p);
free(unit);
}
free(buf);
}
}
/*
* grow_buf读取,如果读取的数据跨越unit,需要读取多次,直到pos->len=0
*
* pos: 读取位置,程序执行后,会将其更新为下次要读的位置和长度
* result: 读取结果
*/
int gb_read_buf(struct grow_buf *gb, struct pos_len *pos, struct addr_len *result)
{
struct grow_buf_unit *unit = NULL;
if (pos->len == 0) {
result->p = NULL;
result->len = 0;
return 0;
}
if (pos->len < 0)
return -1;
switch (pos->pos.type)
{
case ADDR:
if (pos->pos.p == NULL)
return -1;
unit = gb_unit_by_addr(gb, pos->pos.p);
break;
case OFFSET:
if (pos->pos.offset < 0)
return -1;
unit = gb_unit_by_offset(gb, pos->pos.offset);
pos->pos.type = ADDR;
pos->pos.p = unit->buf.p + (pos->pos.offset - unit->offset);
break;
default:
break;
}
if (unit == NULL || grow_buf_write_len(gb)
- (unit->offset + (pos->pos.p - unit->buf.p)) < pos->len)
{
printf("%s(), %d: beyond grow_buf scope\n", __FUNCTION__, __LINE__);
return -1;
}
result->p = pos->pos.p;
if ((result->len = (unit->buf.p
+ unit->buf.len)-pos->pos.p) <= pos->len)
{
unit = container_of(unit->list.next, struct grow_buf_unit, list);
pos->pos.p = unit->buf.p;
} else {
result->len = pos->len;
pos->pos.p += result->len;
}
pos->len -= result->len;
return result->len;
}
/*
* grow_buf写入
*
* pos: 写入位置 (pos->p=NULL,可能由于无空闲空间导致)
* buf: 希望写入的数据
* grow: 当gb剩余空间不足时,希望增长的大小 (<=0表示按默认大小增长)
* 最终增长大小,根据grow,default_grow,buf->len确定
*/
int gb_write_buf(struct grow_buf *gb, struct position *pos, struct addr_len *buf, int grow)
{
struct grow_buf_unit *unit = NULL;
int offset = 0, _offset = 0;
int len = buf->len;
if (buf->len == 0)
return 0;
if (buf->len < 0)
return -1;
if (grow <= 0)
grow = gb->default_grow;
switch (pos->type)
{
case ADDR:
if (pos->p != NULL) {
if ((unit = gb_unit_by_addr(gb, pos->p)) == NULL)
return -1;
offset = pos->p - unit->buf.p;
} else {
if (gb->free > 0)
return -1;
printf("%s(), %d: !!!!!!!!!!!!!!!!!!!!!!\n", __FUNCTION__, __LINE__);
grow = grow < buf->len ? buf->len : grow;
if (buf_growing(gb, grow) < 0)
return -1;
unit = container_of(gb->head.prev, struct grow_buf_unit, list);
offset = 0;
}
break;
case OFFSET:
if (pos->offset < 0)
return -1;
if ((unit = gb_unit_by_offset(gb, pos->offset)) == NULL)
{
printf("%s(), %d: !!!!!!!!!!!!!!!!!!!!!!\n", __FUNCTION__, __LINE__);
grow = grow < (pos->offset - gb->size + buf->len) ?
(pos->offset - gb->size + buf->len) : grow;
if (buf_growing(gb, grow) < 0)
return -1;
unit = container_of(gb->head.prev, struct grow_buf_unit, list);
}
offset = pos->offset - unit->offset;
break;
default:
printf("%s(), %d: wrong position type !\n", __FUNCTION__, __LINE__);
return -1;
}
while (1)
{
int _len = (unit->offset+unit->buf.len)-offset;
if (_len > len)
_len = len;
printf("write: %p, len: %d\n", unit->buf.p+offset, _len);
printf("%d, %d\n", offset, _offset);
memcpy(unit->buf.p+offset, buf->p+_offset, _len);
_offset += _len;
if (unit->offset+offset+_len > grow_buf_write_len(gb))
gb->free -= (unit->offset+offset+_len - grow_buf_write_len(gb));
if ((len -= _len) == 0)
break;
if (buf_growing(gb, grow < len ? len : grow) < 0)
return -1;
unit = container_of(unit->list.next, struct grow_buf_unit, list);
offset = 0;
}
return 0;
}
/*
* 读取grow_buf数据到文件
*
* pos: 读取位置
* offset: 文件偏移
*/
int gb_read_file(struct grow_buf *gb, struct pos_len *pos, int fd, int offset)
{
return 0;
}
/*
* 将文件数据写入grow_buf
*
* pos: 写入位置 (NULL表示空闲空间开始位置)
* offset: 文件偏移
* grow: 当gb剩余空间不足时,希望增长的大小 (0表示按默认大小增长)
*/
int gb_write_file(struct grow_buf *gb, struct position *pos, int fd, int offset, int grow)
{
return 0;
}
/*
* grow_buf之间数据复制
*
* to_pos: 写入位置 (NULL表示空闲空间开始位置)
* pos: 读取位置
*/
int gb_copy(struct grow_buf *to_gb, struct position *to_pos,
struct grow_buf *from_gb, struct pos_len *from_pos)
{
return 0;
}
int main()
{
struct grow_buf *gb = NULL;
struct position pos;
struct addr_len buf;
struct pos_len _pos;
int i, ret;
gb = grow_buf_alloc(128);
if (gb == NULL)
goto err;
// write
buf.p = "0123456789";
buf.len = 10;
for (i = 0; i < 15; i ++)
{
pos.type = ADDR;
pos.p = grow_buf_end(gb);
//pos.type = OFFSET;
//pos.offset = buf.len * i;
ret = gb_write_buf(gb, &pos, &buf, 0);
if (ret < 0)
goto err;
}
// read
//_pos.pos.type = ADDR;
//_pos.pos.p = grow_buf_start(gb);
_pos.pos.type = OFFSET;
_pos.pos.p = 0;
_pos.len = 140;
while (1)
{
ret = gb_read_buf(gb, &_pos, &buf);
if (ret < 0)
goto err;
printf("%d\n", buf.len);
printf("%s\n", buf.p);
if (_pos.len == 0)
break;
}
grow_buf_free(gb);
return 0;
err:
grow_buf_free(gb);
return -1;
}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
赞赏
他的文章
- [求助]CVE编号对应代码 5741
- [求助]汇编语句“xx = .”是什么意思? 2896
- [求助]shellcode 丶丶 2953
- [分享]网址记录 7912
看原图
赞赏
雪币:
留言: