分类: 嵌入式
2015-08-23 16:43:38
encoding_manager.c
15年8月22日15:30:38
#include <config.h>
#include <encoding_manager.h>
#include <string.h>
#include <stdlib.h>
static PT_EncodingOpr g_ptEncodingOprHead;
int RegisterEncodingOpr(PT_EncodingOpr ptEncodingOpr)
{
PT_EncodingOpr ptTmp;
if (!g_ptEncodingOprHead)
{
g_ptEncodingOprHead = ptEncodingOpr;
ptEncodingOpr->ptNext = NULL;
}
else
{
ptTmp = g_ptEncodingOprHead;
while (ptTmp->ptNext)
{
ptTmp = ptTmp->ptNext;
}
ptTmp->ptNext = ptEncodingOpr;
ptEncodingOpr->ptNext = NULL;
}
return 0;
}
void ShowEncodingOpr(void)
{
int i = 0;
PT_EncodingOpr ptTmp = g_ptEncodingOprHead;
while (ptTmp)
{
printf("%02d %s\n", i++, ptTmp->name);
ptTmp = ptTmp->ptNext;
}
}
PT_EncodingOpr SelectEncodingOprForFile(unsigned char *pucFileBufHead)
{
PT_EncodingOpr ptTmp = g_ptEncodingOprHead;
while (ptTmp)
{
if (ptTmp->isSupport(pucFileBufHead))
return ptTmp;
else
ptTmp = ptTmp->ptNext;
}
return NULL;
}
int AddFontOprForEncoding(PT_EncodingOpr ptEncodingOpr, PT_FontOpr ptFontOpr)
{
PT_FontOpr ptFontOprCpy;
if (!ptEncodingOpr || !ptFontOpr)
{
return -1;
}
else
{
ptFontOprCpy = malloc(sizeof(T_FontOpr));
if (!ptFontOprCpy)
{
return -1;
}
else
{
memcpy(ptFontOprCpy, ptFontOpr, sizeof(T_FontOpr));
ptFontOprCpy->ptNext = ptEncodingOpr->ptFontOprSupportedHead;
ptEncodingOpr->ptFontOprSupportedHead = ptFontOprCpy;
return 0;
}
}
}
int DelFontOprFrmEncoding(PT_EncodingOpr ptEncodingOpr, PT_FontOpr ptFontOpr)
{
PT_FontOpr ptTmp;
PT_FontOpr ptPre;
if (!ptEncodingOpr || !ptFontOpr)
{
return -1;
}
else
{
ptTmp = ptEncodingOpr->ptFontOprSupportedHead;
if (strcmp(ptTmp->name, ptFontOpr->name) == 0)
{
/* 删除头节点 */
ptEncodingOpr->ptFontOprSupportedHead = ptTmp->ptNext;
free(ptTmp);
return 0;
}
ptPre = ptEncodingOpr->ptFontOprSupportedHead;
ptTmp = ptPre->ptNext;
while (ptTmp)
{
if (strcmp(ptTmp->name, ptFontOpr->name) == 0)
{
/* 从链表中取出,释放 */
ptPre->ptNext = ptTmp->ptNext;
free(ptTmp);
return 0;
}
else
{
ptPre = ptTmp;
ptTmp = ptTmp->ptNext;
}
}
return -1;
}
}
int EncodingInit(void)
{
int iError;
iError = AsciiEncodingInit();
if (iError)
{
DBG_PRINTF("AsciiEncodingInit error!\n");
return -1;
}
iError = Utf16leEncodingInit();
if (iError)
{
DBG_PRINTF("Utf16leEncodingInit error!\n");
return -1;
}
iError = Utf16beEncodingInit();
if (iError)
{
DBG_PRINTF("Utf16beEncodingInit error!\n");
return -1;
}
iError = Utf8EncodingInit();
if (iError)
{
DBG_PRINTF("Utf8EncodingInit error!\n");
return -1;
}
return 0;
}
encoding_manager.h
#ifndef _ENCODING_MANAGER_H
#define _ENCODING_MANAGER_H
#include <fonts_manager.h>
#include <disp_manager.h>
typedef struct EncodingOpr {
char *name;
int iHeadLen;
PT_FontOpr ptFontOprSupportedHead;
int (*isSupport)(unsigned char *pucBufHead);
int (*GetCodeFrmBuf)(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode);
struct EncodingOpr *ptNext;
}T_EncodingOpr, *PT_EncodingOpr;
int RegisterEncodingOpr(PT_EncodingOpr ptEncodingOpr);
void ShowEncodingOpr(void);
PT_DispOpr GetDispOpr(char *pcName);
PT_EncodingOpr SelectEncodingOprForFile(unsigned char *pucFileBufHead);
int AddFontOprForEncoding(PT_EncodingOpr ptEncodingOpr, PT_FontOpr ptFontOpr);
int DelFontOprFrmEncoding(PT_EncodingOpr ptEncodingOpr, PT_FontOpr ptFontOpr);
int EncodingInit(void);
int AsciiEncodingInit(void);
int Utf16beEncodingInit(void);
int Utf16leEncodingInit(void);
int Utf8EncodingInit(void);
#endif /* _ENCODING_MANAGER_H */
先讲解encoding_manager.h:
主要是这个 EncodingOpr结构体:
typedef struct EncodingOpr {
char *name; /* 名字,根据名字找到对应的结构体 */
int iHeadLen; /* 前导1的长度,后面具体分析。 */
PT_FontOpr ptFontOprSupportedHead;
int (*isSupport)(unsigned char *pucBufHead);
int (*GetCodeFrmBuf)(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode);
struct EncodingOpr *ptNext;
}T_EncodingOpr, *PT_EncodingOpr;
(1)这个结构体挺复杂的,首先,显示一个字符的步骤是:1.得到这个字符的编码2.根据这个编码选择用哪个字体来解析3.显示。 所以,对应每一种编码格式,都有一个它自己的EncodingOpr结构体,每个编码格式里面都有它相对应可以解析这个编码的字体,而这个字体可能不止是一个,我们把这些字体放在EncodingOpr结构体里面的 ptFontOprSupportedHead链表中。所以这是 EncodingOpr结构体中 ptFontOprSupportedHead的由来。
(2)isSupport函数,对于一个字符,是否可以用utf-8(或其他编码)来解析呢?我们在每种编码方式里面添加了这个函数,这样,通过调用这个函数,就可以知道是否可以用这个编码方式来解码。(3)GetCodeFrmBuf函数,从一个文件(已经映射到内存中了)中取出编码值,对于utf-8的编码,它的编码值是以0xEF,0xBB,0xBF来开头的,对于utf-16le的编码,它的编码值是以0xFF, 0xFE来开头的,我们想要获取真正的字符编码值,需要将这个前导位去掉,来取出真正的编码,这个函数就是这个作用。
下面分析encoding_manager.c文件:
(1)首先,还是先定义一个g_ptEncodingOprHead链表头,
static PT_EncodingOpr g_ptEncodingOprHead;
int RegisterEncodingOpr(PT_EncodingOpr ptEncodingOpr)
{
PT_EncodingOpr ptTmp;
if (!g_ptEncodingOprHead)
{
g_ptEncodingOprHead = ptEncodingOpr;
ptEncodingOpr->ptNext = NULL;
}
else
{
ptTmp = g_ptEncodingOprHead;
while (ptTmp->ptNext)
{
ptTmp = ptTmp->ptNext;
}
ptTmp->ptNext = ptEncodingOpr;
ptEncodingOpr->ptNext = NULL;
}
return 0;
}
/* 将 ptEncodingOpr这个结构体添加到 g_ptEncodingOprHead链表中,到最后,这个链表中含有
* utf-8, utf-16be,utf-16le,ascii这几种编码方式的结构体。
*/
(2)ShowEncodingOpr()函数,取出链表中每一项的名字,打印出来。
(3)为文件选择编码方式函数:
PT_EncodingOpr SelectEncodingOprForFile(unsigned char *pucFileBufHead)
{
PT_EncodingOpr ptTmp = g_ptEncodingOprHead;
while (ptTmp)
{
if (ptTmp->isSupport(pucFileBufHead))
return ptTmp;
/*其中isSupport函数返回1代表支持*/
else
ptTmp = ptTmp->ptNext;
}
return NULL;
}
/* 这个函数从 g_ptEncodingOprHead链表中遍历每一项,选择支持文件的编码方式,从main.c中可以
* 看出来,程序首先将utf-8, utf-16be, utf-16le, asci等几种编码方式进行注册,即添加进
* g_ptEncodingOprHead这个链表中,当打开一个文件的时候,调用这个
* SelectEncodingOprForFile函数来选择其中一个支持的编码方式。
*/
(4) AddFontOprForEncoding函数:(之前已经说过,每个编码方式都可以用一种或多种字体来解析,这些字体就放在编码对应的ptEncodingOpr结构体里面的ptFontOprSupportedHead链表中)
int AddFontOprForEncoding(PT_EncodingOpr ptEncodingOpr, PT_FontOpr ptFontOpr)
{
PT_FontOpr ptFontOprCpy;
if (!ptEncodingOpr || !ptFontOpr)
{
return -1;
}
/* 如果这两项中有一项为空,则返回-1. */
else
{
ptFontOprCpy = malloc(sizeof(T_FontOpr));
if (!ptFontOprCpy)
{
return -1;
}
/* 分配内存,如果没成功,返回-1。 */
else
{
memcpy(ptFontOprCpy, ptFontOpr, sizeof(T_FontOpr));
ptFontOprCpy->ptNext = ptEncodingOpr->ptFontOprSupportedHead;
ptEncodingOpr->ptFontOprSupportedHead = ptFontOprCpy;
/* 这三句代码不是很理解,1)首先将 ptFontOpr拷贝到 ptFontOprCpy分配的内存中,这时候
* ptFontOprCpy里面就是ptFontOpr结构体2)将ptFontOprCpy的 ptNext指向原来的链表头3)再
* 将整个ptFontOprCpy结构体赋值给链表头,形成一个新的链表头,也就是说ptFontOprCpy是新的链
* 表头,它的ptNext指向原来的链表头,相当与在链表头前面加了一项。 */
return 0;
}
}
}
(5) DelFontOprFrmEncoding函数:
int DelFontOprFrmEncoding(PT_EncodingOpr ptEncodingOpr, PT_FontOpr ptFontOpr)
{
PT_FontOpr ptTmp;
PT_FontOpr ptPre;
if (!ptEncodingOpr || !ptFontOpr) /* 如果这两项任意一项为空就返回-1 */
{
return -1;
}
else
{
ptTmp = ptEncodingOpr->ptFontOprSupportedHead;
if (strcmp(ptTmp->name, ptFontOpr->name) == 0)
{
/* 删除头节点 */
ptEncodingOpr->ptFontOprSupportedHead = ptTmp->ptNext;
free(ptTmp);
return 0;
}
ptPre = ptEncodingOpr->ptFontOprSupportedHead;
ptTmp = ptPre->ptNext;
while (ptTmp)
{
if (strcmp(ptTmp->name, ptFontOpr->name) == 0)
{
/* 从链表中取出,释放 */
ptPre->ptNext = ptTmp->ptNext;
free(ptTmp);
return 0;
}
else
{
ptPre = ptTmp;
ptTmp = ptTmp->ptNext;
}
}
return -1;
}
}
这个函数是上一个函数的反函数,主要是理解里面的链表操作。
(6) EncodingInit函数:在里面注册了ascii, utf16le, utf16be, utf8这几种编码方式。