iniLoadFromFile
|-----iniInitContext
| |-----hash_init_ex
| |-----_has_alloc_buckets
|-----iniDoLoadFormFile
| |-----get_url_content
| |-----getFileContent
| |-----iniDoLoadItemsFromBuffer
| |-----iniDoloadFromFile(这里再次调用,是为了处理#include)
| |-----hash_find
| |-----_chain_find_entry
| |-----hash_insert
| |-----hash_insert_ex
|-----iniSortItems
| |-----hash_walk
iniDoLoadItemsFromBuffer:从缓冲区中的无结构数据,转化成IniContext结构数据
-
//用content缓冲区中的数据初始化pContext
-
static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext) //content:从文件中读取的信息,pContext:需要初始化的IniContext结构
-
{
-
IniSection *pSection;
-
IniItem *pItem;
-
char *pLine;
-
char *pLastEnd;
-
char *pEqualChar;
-
char *pIncludeFilename;
-
int nLineLen;
-
int nNameLen;
-
int nValueLen;
-
int result;
-
-
result = 0;
-
pLastEnd = content - 1;//content的上一个字符
-
pSection = pContext->current_section;//psection指向当前section
-
if (pSection->count > 0)
-
{
-
pItem = pSection->items + pSection->count; //pitem指向当前item
-
}
-
else
-
{
-
pItem = pSection->items;//如果count=0,则让pitem指向第一个item
-
}
-
-
while (pLastEnd != NULL)
-
{
-
pLine = pLastEnd + 1;//
-
pLastEnd = strchr(pLine, '\n');//找到第一个\n,这两句表示每次检索一行
-
if (pLastEnd != NULL)//找到\n后,把\n替换成\0
-
{
-
*pLastEnd = '\0';
-
}
-
-
if (*pLine == '#' && \//寻找#include http.conf这种格式的字符串
-
strncasecmp(pLine+1, "include", 7) == 0 && \//与include相比较
-
(*(pLine+8) == ' ' || *(pLine+8) == '\t'))//include与文件名以' '或者'\t'分开
-
{
-
pIncludeFilename = strdup(pLine + 9);//字符串复制,复制include后的文件名,strdup函数在内部分配了内存,在外部需要释放内存
-
if (pIncludeFilename == NULL)
-
{
-
logError("file: "__FILE__", line: %d, " \
-
"strdup %d bytes fail", __LINE__, \
-
(int)strlen(pLine + 9) + 1);
-
result = errno != 0 ? errno : ENOMEM;
-
break;
-
}
-
-
trim(pIncludeFilename);//去除文件名前后空格
-
if (strncasecmp(pIncludeFilename, "http://", 7) != 0 \//如果文件名不是网络地址
-
&& !fileExists(pIncludeFilename)) //并且文件不存在
-
{
-
logError("file: "__FILE__", line: %d, " \
-
"include file \"%s\" not exists, " \
-
"line: \"%s\"", __LINE__, \
-
pIncludeFilename, pLine);
-
free(pIncludeFilename);
-
result = ENOENT;
-
break;
-
}
-
-
result = iniDoLoadFromFile(pIncludeFilename, \
-
pContext);//读取include包含的文件的信息
-
if (result != 0)
-
{
-
free(pIncludeFilename);
-
break;
-
}
-
-
pSection = pContext->current_section;
-
if (pSection->count > 0)
-
{
-
pItem = pSection->items + pSection->count; //must re-asign
-
}
-
else
-
{
-
pItem = pSection->items;
-
}
-
-
free(pIncludeFilename);
-
continue;
-
}
-
-
trim(pLine);
-
if (*pLine == '#' || *pLine == '\0')//以#号开始或者是\0的字符串,直接continue,这里的\0是在函数开头由\n替换而来
-
{
-
continue;
-
}
-
-
nLineLen = strlen(pLine);
-
if (*pLine == '[' && *(pLine + (nLineLen - 1)) == ']') //section,寻找[seciontname]的字符串
-
{//这里表示遇到了section
-
char *section_name;
-
int section_len;
-
-
*(pLine + (nLineLen - 1)) = '\0';//把‘]’置为 ‘\0’
-
section_name = pLine + 1; //skip [
-
-
trim(section_name);
-
if (*section_name == '\0') //global section
-
{
-
pContext->current_section = &pContext->global;
-
pSection = pContext->current_section;
-
if (pSection->count > 0)
-
{
-
pItem = pSection->items + pSection->count;
-
}
-
else
-
{
-
pItem = pSection->items;
-
}
-
continue;
-
}
-
-
section_len = strlen(section_name);
-
pSection = (IniSection *)hash_find(&pContext->sections,\
-
section_name, section_len);//根据section name找section
-
if (pSection == NULL)//若section没有找到
-
{
-
pSection = (IniSection *)malloc(sizeof(IniSection));//先分配空间
-
if (pSection == NULL)
-
{
-
result = errno != 0 ? errno : ENOMEM;
-
logError("file: "__FILE__", line: %d, "\
-
"malloc %d bytes fail, " \
-
"errno: %d, error info: %s", \
-
__LINE__, \
-
(int)sizeof(IniSection), \
-
result, STRERROR(result));
-
-
break;
-
}
-
-
memset(pSection, 0, sizeof(IniSection));//置0
-
result = hash_insert(&pContext->sections, \//将section插入到hash表
-
section_name, section_len, pSection);
-
if (result < 0)
-
{
-
result *= -1;
-
logError("file: "__FILE__", line: %d, "\
-
"insert into hash table fail, "\
-
"errno: %d, error info: %s", \
-
__LINE__, result, \
-
STRERROR(result));
-
break;
-
}
-
else
-
{
-
result = 0;
-
}
-
}
-
-
pContext->current_section = pSection;
-
if (pSection->count > 0)
-
{
-
pItem = pSection->items + pSection->count;
-
}
-
else
-
{
-
pItem = pSection->items;
-
}
-
continue;
-
}
-
-
pEqualChar = strchr(pLine, '=');//寻找name=value的字符串
-
if (pEqualChar == NULL)
-
{
-
continue;
-
}
-
-
nNameLen = pEqualChar - pLine;//name的长度
-
nValueLen = strlen(pLine) - (nNameLen + 1);//value的长度
-
if (nNameLen > FAST_INI_ITEM_NAME_LEN)
-
{
-
nNameLen = FAST_INI_ITEM_NAME_LEN;
-
}
-
-
if (nValueLen > FAST_INI_ITEM_VALUE_LEN)
-
{
-
nValueLen = FAST_INI_ITEM_VALUE_LEN;
-
}
-
-
if (pSection->count >= pSection->alloc_count)
-
{
-
pSection->alloc_count += _ALLOC_ITEMS_ONCE;//每次增加8个
-
pSection->items=(IniItem *)realloc(pSection->items, //扩大空间
-
sizeof(IniItem) * pSection->alloc_count);
-
if (pSection->items == NULL)
-
{
-
logError("file: "__FILE__", line: %d, " \
-
"realloc %d bytes fail", __LINE__, \
-
(int)sizeof(IniItem) * \
-
pSection->alloc_count);
-
result = errno != 0 ? errno : ENOMEM;
-
break;
-
}
-
-
pItem = pSection->items + pSection->count;
-
memset(pItem, 0, sizeof(IniItem) * \ //把剩余的部分置0
-
(pSection->alloc_count - pSection->count));
-
}
-
-
memcpy(pItem->name, pLine, nNameLen);
-
memcpy(pItem->value, pEqualChar + 1, nValueLen);
-
-
trim(pItem->name);
-
trim(pItem->value);
-
-
pSection->count++;
-
pItem++;
-
}
-
-
return result;
-
}
iniDoLoadItemsFromBuffer函数首先把所有的\n替换成\0,然后一行一行的读取数据,如果读取的这个数据是“#include”,则再次去读取inlcude后的文件信息到pContext中。如果读到的数据是包含[],则说明遇到一个section,把该section加入到hash表中,若读到的数据是name=value,则把该数据放入到全局section中。
|-----hash_find
|-----_chain_find_entry
-
//在hash表中查找key是否存在
-
void *hash_find(HashArray *pHash, const void *key, const int key_len) //pHash:指向hash表的指针,key:sectionName,key_len:sectionName的长度
-
{
-
unsigned int hash_code;
-
HashData **ppBucket;
-
HashData *hash_data;
-
-
hash_code = pHash->hash_func(key, key_len); //计算hashcode
-
ppBucket = pHash->buckets + (hash_code % (*pHash->capacity)); //通过这种策略,确定hash的表的入口条目
-
-
hash_data = _chain_find_entry(ppBucket, key, key_len, hash_code);//从入口条目开始,遍历链表
-
if (hash_data != NULL)
-
{
-
return hash_data->value;
-
}
-
else
-
{
-
return NULL;
-
}
-
}
-
//从hash表的入口条目开始,遍历链表
-
static HashData *_chain_find_entry(HashData **ppBucket, const void *key, \ //ppBucket:指向hashcode对应的入口的指针
-
const int key_len, const unsigned int hash_code)
-
{
-
HashData *hash_data;
-
-
hash_data = *ppBucket;//获取第一个节点
-
while (hash_data != NULL)
-
{
-
if (key_len == hash_data->key_len && \//若hashdata的key_len与参数key_len相同
-
memcmp(key, hash_data->key, key_len) == 0) //并且hashdata的key与参数key相同
-
{
-
return hash_data;
-
}
-
-
hash_data = hash_data->next;
-
}
-
-
return NULL;
-
}
|-----hash_insert
|-----hash_insert_ex
|-----DELETE_FROM_BUCKET
|-----CALC_NODE_MALLOC_BYTES
|-----ADD_TO_BUCKET
|-----_rehash
-
//把hashdata插入hash表
-
int hash_insert_ex(HashArray *pHash, const void *key, const int key_len, \ //pHash:hash表,key:sectionName,key_len:sectionName的长度,value:section整个结构的值,value_len:section结构的长度
-
void *value, const int value_len)
-
{
-
unsigned int hash_code;
-
HashData **ppBucket;
-
HashData *hash_data;
-
HashData *previous;
-
char *pBuff;
-
int bytes;
-
int malloc_value_size;
-
-
hash_code = pHash->hash_func(key, key_len);//通过name与len计算hashcode
-
ppBucket = pHash->buckets + (hash_code % (*pHash->capacity));//通过hashcode获取指针数组位置
-
-
previous = NULL;
-
hash_data = *ppBucket;
-
while (hash_data != NULL)//hashdata存在
-
{
-
if (key_len == hash_data->key_len && \
-
memcmp(key, hash_data->key, key_len) == 0)
-
{
-
break;
-
}
-
-
previous = hash_data;
-
hash_data = hash_data->next;
-
}
-
-
if (hash_data != NULL) //exists
-
{
-
if (!pHash->is_malloc_value)//该值若为0,表示hash表不会为value预留空间,value直接从外部传入
-
{
-
hash_data->value_len = value_len;
-
hash_data->value = (char *)value;
-
return 0;
-
}
-
else//表示hash表为value预留空间
-
{
-
if (hash_data->malloc_value_size >= value_len && \
-
hash_data->malloc_value_size / 2 < value_len)
-
{
-
hash_data->value_len = value_len;
-
memcpy(hash_data->value, value, value_len);
-
return 0;
-
}
-
-
DELETE_FROM_BUCKET(pHash, ppBucket, previous, hash_data)
-
}
-
}
-
-
if (!pHash->is_malloc_value)//表示value不在hashdata结构后
-
{
-
malloc_value_size = 0;
-
}
-
else //表示value在hashdata结构后,这里把value的长度放入hashdata结构中
-
{
-
malloc_value_size = value_len;
-
}
-
-
bytes = CALC_NODE_MALLOC_BYTES(key_len, malloc_value_size);//计算一个hashdata需要分配的空间
-
if (pHash->max_bytes > 0 && pHash->bytes_used+bytes > pHash->max_bytes)
-
{
-
return -ENOSPC;
-
}
-
-
pBuff = (char *)malloc(bytes);
-
if (pBuff == NULL)
-
{
-
return -ENOMEM;
-
}
-
-
pHash->bytes_used += bytes;//改变used变量
-
-
hash_data = (HashData *)pBuff;
-
hash_data->malloc_value_size = malloc_value_size;
-
-
hash_data->key_len = key_len;
-
memcpy(hash_data->key, key, key_len);
-
#ifdef HASH_STORE_HASH_CODE
-
hash_data->hash_code = hash_code;
-
#endif
-
hash_data->value_len = value_len;
-
-
if (!pHash->is_malloc_value) //这里表示value已经在外面分配了空间,而不是放在hashdata后面
-
{
-
hash_data->value = (char *)value;
-
}
-
else //这里表示value需要放在hashdata后,[hashdata][key][value]
-
{
-
hash_data->value = hash_data->key + hash_data->key_len;//指向value的首地址
-
memcpy(hash_data->value, value, value_len);//拷贝value
-
}
-
-
ADD_TO_BUCKET(pHash, ppBucket, hash_data)//添加hashdata到hash表
-
-
if ((double)pHash->item_count / (double)*pHash->capacity >= \
-
pHash->load_factor)//
-
{
-
_rehash(pHash);//重新hash
-
}
-
-
return 1;
-
}
hash_insert_ex函数在hash表中查找key是对应的hashdata否存在与hash表中,若存在,则直接修改hashdata的value与value_len,若不存在,调用CALC_NODE_MALLOC_BYTES计算需要分配的空间,创建hashdata,并分配空间,并调用ADD_TO_BUCKET插入到hash表中,检查是否rehash,若需要,则执行rehash
|-----hash_insert
|-----hash_insert_ex
|-----DELETE_FROM_BUCKET
|-----CALC_NODE_MALLOC_BYTES
|-----ADD_TO_BUCKET
|-----_rehash
-
#define CALC_NODE_MALLOC_BYTES(key_len, value_size) \
-
sizeof(HashData) + key_len + value_size
CALC_NODE_MALLOC_BYTES宏,计算一个hashdata需要分配的空间的大小,这里在hashdata后面预留了key与value的空间
|-----hash_insert
|-----hash_insert_ex
|-----DELETE_FROM_BUCKET
|-----CALC_NODE_MALLOC_BYTES
|-----ADD_TO_BUCKET
|-----_rehash
|-----_rehash_1
-
static int _rehash(HashArray *pHash) //对hash表中的hashdata数据重新进行排列
-
{
-
int result;
-
unsigned int *pOldCapacity;
-
-
pOldCapacity = pHash->capacity;
-
if (pHash->is_malloc_capacity) //这里先重新计算capacity
-
{
-
unsigned int *pprime;
-
unsigned int *prime_end;
-
-
pHash->capacity = NULL;
-
-
prime_end = prime_array + PRIME_ARRAY_SIZE;
-
for (pprime = prime_array; pprime!=prime_end; pprime++)//寻找大于pOldCapacity的最大质数
-
{
-
if (*pprime > *pOldCapacity)
-
{
-
pHash->capacity = pprime;
-
break;
-
}
-
}
-
}
-
else
-
{
-
pHash->capacity++;
-
}
-
-
if ((result=_rehash1(pHash, *pOldCapacity, pHash->capacity)) != 0)
-
{
-
pHash->capacity = pOldCapacity; //rollback
-
}
-
else
-
{
-
if (pHash->is_malloc_capacity) //
-
{
-
free(pOldCapacity);
-
pHash->is_malloc_capacity = false;
-
}
-
}
-
-
/*printf("rehash, old_capacity=%d, new_capacity=%d\n", \
-
old_capacity, *pHash->capacity);
-
*/
-
return result;
-
}
rehash首先重新计算capacity,再调用_rehash对hash表中的数据重新排列
-
static int _rehash1(HashArray *pHash, const int old_capacity, \
-
unsigned int *new_capacity)
-
{
-
HashData **old_buckets;
-
HashData **ppBucket;
-
HashData **bucket_end;
-
HashData *hash_data;
-
HashData *pNext;
-
int result;
-
-
old_buckets = pHash->buckets;//保留的老的hashdata的地址
-
pHash->capacity = new_capacity;
-
if ((result=_hash_alloc_buckets(pHash, old_capacity)) != 0)//重新给老的hashdata分配空间
-
{//失败了,则rollback
-
pHash->buckets = old_buckets;
-
return result;
-
}
-
-
//printf("old: %d, new: %d\n", old_capacity, *pHash->capacity);
-
-
pHash->item_count = 0;
-
bucket_end = old_buckets + old_capacity;
-
for (ppBucket=old_buckets; ppBucket<bucket_end; ppBucket++)
-
{
-
if (*ppBucket == NULL)
-
{
-
continue;
-
}
-
-
hash_data = *ppBucket;
-
while (hash_data != NULL)
-
{
-
pNext = hash_data->next;
-
-
ADD_TO_BUCKET(pHash, (pHash->buckets + \//将老的hashdata按照新的规则放入hash表中
-
(HASH_CODE(pHash, hash_data) % \//因为capacity变化了,造成了计算出的%运算的值发生了变化
-
(*pHash->capacity))), hash_data)
-
-
hash_data = pNext;
-
}
-
}
-
-
free(old_buckets);//释放老的空间
-
return 0;
-
}
-
_rehash1函数先按照新的capacity为hash分配空间,再把hashdata按照新规则计算的位置,放入到hash表中,最后释放老的hashdata的空间
阅读(632) | 评论(0) | 转发(0) |