经过日记02说明内存池的实现后,现在开始介绍使用内存池的第一个结构体bufstr。
bufstr结构体以及相关实现函数替服务器管理字符串(服务器的处理信息数据)的内存块使用与操作。
我们先看看bufstr结构体的具体实现:
typedef struct {
//指向数据
char **ptr;
//指向内存块开头
memblock * mblock;
//内存块数目
int mbnum;
//已经使用大小(字节)
int used;
//总共内存空间大小(字节)
int size;
} bufstr;
bufstr结构体的操作函数中,把指定字符串复制到用户指定的bufstr结构体的数据末尾,这个操作函数实现起来是比较有技巧的,因为不但当前用户指定的bufstr结构体的数据末尾有两种情况,分别是块内,块末。而且当前用户指定的bufstr结构体的块数量是否能容纳所需要追加的字符串。
(1)该操作函数的具体实现:
int bufstr_append_string(mempool *mpool,bufstr *b,char *s)
{
int slen,total,mbsize,mbnum,cnum,n;
slen = strlen(s)+1;
if(b==NULL||s==NULL)
{
return 0;
}
mbsize = MBSIZE;
for(;;)
{
total = b->size - b->used+1;
if(total>=slen)
{
if(b->used % mbsize > 0)
{
if(mbsize-b->used%mbsize+1 >= slen)
{
memcpy((&b->ptr[b->used / mbsize][(b->used % mbsize)-1]),s,slen-1);
b->ptr[b->used / mbsize][(b->used % mbsize)-1+(slen-1)] = '\0';
}
else
{
memcpy((&b->ptr[b->used / mbsize][(b->used % mbsize)-1]),s,mbsize - b->used%mbsize + 1);
s+=mbsize-b->used%mbsize+1;
mbnum = (slen - (mbsize - b->used%mbsize+1)) / mbsize;
cnum = (slen - (mbsize - b->used%mbsize+1)) % mbsize;
n=0;
while(n<mbnum)
{
memcpy(b->ptr[(b->used / mbsize)+1+n],s,mbsize);
s+=mbsize;
n++;
}
if(cnum>0)
{
memcpy(b->ptr[b->used / mbsize+1+n],s,cnum);
b->ptr[b->used / mbsize+1+n][cnum] ='\0';
}
else
{
b->ptr[(b->used / mbsize)+1+n][0]='\0';
}
}
}
else
{
if(b->used / mbsize == 0)
{
bufstr_copy_string(mpool,b,s);
return 1;
}
else
{
memcpy((&b->ptr[(b->used / mbsize)-1][mbsize-1]),s,1);
s++;
mbnum = (slen - 1) / mbsize;
cnum = (slen - 1) % mbsize;
n=0;
while(n<mbnum)
{
memcpy(b->ptr[(b->used / mbsize)+n],s,mbsize);
s+=mbsize;
n++;
}
if(cnum>0)
{
memcpy(b->ptr[(b->used / mbsize)+n],s,cnum);
b->ptr[(b->used / mbsize)+n][cnum] ='\0';
}
else
{
b->ptr[(b->used / mbsize)+n][0]='\0';
}
}
}
b->used+=slen-1;
return 1;
}
else
{
bufstr_prepare_size(mpool,b,slen);
}
}
}
(2)确保用户的bufstr结构体的ptr的指向区域至少有指定大小的空余内存空间,即bufstr_append_string函数中所调用的bufstr_prepare_size函数的实现:
int bufstr_prepare_size(mempool *mpool,bufstr *b, int size)
{
int total,mbsize,mbnum,n,i;
memblock *mbtemp;
if(b==NULL||b->size==0)
{
return 0;
}
mbsize = MBSIZE;
total = b->size - b->used;
n=size -total;
if(n > 0)
{
mbnum = n / mbsize;
if(n % mbsize>0)
{
mbnum++;
}
mbtemp = b->mblock;
while(mbtemp->next!=NULL)
{
mbtemp = mbtemp->next;
}
mbtemp->next = mempool_take_mblocks(mpool,mbnum);
//指向新增块的链头
mbtemp = mbtemp->next;
//使ptr指向每个新增内存块的数据部分
for(i=0;i<mbnum;i++)
{
b->ptr[b->mbnum+i] = (char*)mbtemp->memptr;
mbtemp = mbtemp->next;
}
b->mbnum += mbnum;
b->size += mbsize * mbnum;
}
return 1;
}
下面是bufstr结构体的操作函数名字,由于操作函数很多,我就不逐一列举了,若大家需要了解哪一个,可以在评论中告诉我,我看到时更新内容。
//创建bufstr结构b,并拥有一个内存块,即1K的内存空间
bufstr *bufstr_init(mempool *mpool);
//释放用户指定的bufstr结构体b
void bufstr_free(mempool *mpool,bufstr *b);
//确保用户指定的bufstr结构体b的ptr的指向区域至少有size大小的空余内存空间
int bufstr_prepare_size(mempool *mpool,bufstr *b, int size);
//把指定字符串s复制到用户指定的bufstr结构体b的数据空间,覆盖之前b的数据
int bufstr_copy_string(mempool *mpool,bufstr *b,char *s);
//把指定字符串s前s_len个字符复制到用户指定的bufstr结构体b的数据空间,覆盖之前b的数据
int bufstr_copy_string_len(mempool *mpool,bufstr *b,char *s,int s_len);
//将bufstr结构体src的内容复制到bufstr结构体des中,覆盖之前des的数据
int bufstr_copy_string_bufstr(mempool *mpool,bufstr *des,bufstr *src);
int bufstr_append_string_len(mempool *mpool,bufstr *b,char *s,int len);
//把指定字符串s复制到用户指定的bufstr结构体b的数据末尾(覆盖之前'\0')
int bufstr_append_string(mempool *mpool,bufstr *b,char *s);
//把指定bufstr的src里面的数据复制到用户指定的bufstr结构体des的数据末尾(覆盖之前'\0')
int bufstr_append_bufstr(mempool *mpool,bufstr *des, bufstr *src);
//把bufstr的数据转换成字符串,并返回
char *read_string_bufstr(bufstr * src);
//把bufstr里面的数据转换成整形输出
int read_int_bufstr(bufstr *src);
//将path字符串里面的文件名提取出来,复制给bufstr结构体,覆盖掉先前数据
bufstr *bufstr_copy_bufstr_filename(mempool *mpool,bufstr *src);
bufstr *bufstr_copy_filename(mempool *mpool,char *path);
//将path字符串里面的文件扩展名提取出来,复制给bufstr结构体并返回,覆盖掉先前数据
bufstr *bufstr_copy_bufstr_etrname(mempool *mpool,bufstr *src);
bufstr *bufstr_copy_etrname(mempool *mpool,char *path);
//比较bufstr和string
int bufstr_compare_string(bufstr *a, char *b);
//比较bufstr和bufstr
int bufstr_compare_bufstr(bufstr *a, char *b);
char* string_to_lower(char *str);
char* string_to_upper(char *str);
//将bufstr里面的大写字符转换成小写字符
int bufstr_to_lower(bufstr * b);
//将bufstr里面的小写字符转换成大写字符
int bufstr_to_upper(bufstr * b);
//将一个整数转换成字符串
char *itoa(size_t num);
//判断用户指定的bufstr结构体b所指的内容中是否含有字符串src
int bufstr_include_string(bufstr *b, char *src);
//判断用户指定的bufstr结构体str1所指字符串中是否含有str2所指字符串
int bufstr_include_bufstr(bufstr *str1, bufstr *str2);