1. 配置文件
1.1 文件格式
Minigui的配置文件是标准的section - key - value格式。
# MiniGUI.cfg
[system]
gal_engine=pc_xvfb
defaultmode=360x480-16bpp
1.2 ETC_S 与 ETCSECTION
ETC_S对应整个配置文件,而ETCSECTION对应单个Section的数据。

对于ETC_S,
- 成员sections[]是动态分配的ETCSECTION数组,保存section信息。
- 成员section_nr_alloc是ETCSECTION数组的大小,而section_nr是数组中实际的ETCSECTION的数目。
对于ETCSECTION,
- 成员name是Section名字
- 成员keys和values长度相同。前者是键数组,后者相应的值数组。key_nr是键数目, key_nr_alloc()是数组大小。
1.3 加载配置文件 mg_InitMgEtc()
mg_InitMgEtc()负责加载配置文件。

-
调用LookForEtcFile()得到配置文件名。其中,
- 得到配置文件名,调用GetValueFromEtcFile(),尝试读取文件中的一个必需项,如果成功,则调用strcpy()将文件名保存在全局变量ETCFILEPATH[]中。
char ETCFILEPATH [MAX_PATH + 1];
- 得到配置文件目录时,首先读取环境变量MG_CFG_PATH,如果这个文件不行,则尝试minigui进程的工作目录。配置文件名为MiniGUI.cfg。
-
调用LoadEtcFile()加载配置文件。
-
打开文件。
-
调用malloc()创建ETC_S实例,以及它的成员sections数组。这个实例保存在全局变量hMgEtc中,它实际上是一个ETC_S指针。
GHANDLE hMgEtc = 0;
-
调用etc_ReadSection()读取Section,包括其下的Key及Value。如果Section、Key、Value的数组长度超限,则调用realloc()拓展长度。
1.4 GetValueFromEtc()
GetValueFromEtc()从全局变量hMgEtc读取键值。

2. 数据块堆
2.1 BLOCKHEAP
BLOCKHEAP是数据块的堆,用于提高小结构的分配效率,如剪裁区域CLIPRGN等。
- 数据块保存在一个数组中,成员heap指向这个数组。
- 成员bd_size是数据块的大小。
- 成员heap_size是数组的大小。
- 成员free是第一个空闲数据块的索引,这个用于加快查找空闲块。

BLOCKHEAP的内存布局如下图。
- 绿色部分是BLOCKHEAP结构。
- 黄/橙色部分是数据块,包括图中的free block和used block。一是挨着的数据包部分,这是成员heap指向的数组,数组大小是heap_size。
- 用户获取数据块时,优先从heap指向的数组这里获取。如果其中的数据包都已使用,则调用alloc()动态分配。在图中标示为special block。

-
数据块包括两个部分,首先是起始地址的两字节标志,然后是真正的数据。标志的取值如下。
#define BDS_FREE 0x0000 // 在heap数组中,未使用 #define BDS_SPECIAL 0x0001 // 动态分配,不在heap数组中 #define BDS_USED 0x0002 // 在heap数组中,已使用
2.2 InitBlockDataHeap()
函数InitBlockDataHeap()初始化BLOCKHEAP。其中将成员heap置空。

2.3 BlockDataAlloc()
函数BlockDataAlloc()从BLOCKHEAP中得到数据块。
- 如果heap数组还没有创建,则调用calloc()创建它。数组大小由heap_size和bd_size指定。
- 在heap数组中搜索空闲的数据块(标志为BDS_FREE)。如果找到,返回它,标志设置为BDS_USED。
- 如果没找到空闲数据块,则调用calloc()分配一个,返回它,标志设置为BDS_SPECIAL。

3. Hash表
3.1 HASH_TABLE
HASH_TABLE定义Hash表,RES_ENTRY是其中的表项。

关于RES_ENTRY,
-
source是数据,type是数据类型
-
flag标志位
-
key是键值。键值HASH_KEY实际上是一个DWORD。
typedef DWORD RES_KEY;
-
成员next使表项可以链接成链表。
关于HASH_TABLE,
-
成员entries是RES_ENTRY链表的数组,size是数组大小。 数组大小是固定的,使用Key2Idx()函数将key值映射到数组范围内。
#define Key2Idx(t,key) ((key)%((t)->size))
-
成员函数init_hash_table()初始化Hash表。
-
成员函数get_entry()根据key值得到表项RES_ENTRY。如果对应表项不存在,且参数指定了“新建”选项,则创建表项。
-
成员函数remove_entry()移除键值。
网友评论