unicode与gbk双向编码转换(分离底层,便于移植)

unicode与gbk双向编码转换表在短信解析,FATFS长文件名等都有用到,我一般是将编码表放置于外部falsh,与字库放到一起,本次将编码表的底层进行了分离,并且对编码表进行检测,具体实现如下:

底层存储器接口分离后,可以将编码表存放于内存,内部flash,外部flash,外部TF卡等等地方,代码与平台无关。

unicode_gbk.c

/*************************************************************************************************************
 * 文件名		:	unicode_gbk.c
 * 功能			:	汉字编码转换
 * 作者			:	[email protected]
 * 创建时间		:	2013-04-03
 * 最后修改时间	:	2018-03-25
 * 详细			:	2018-03-25:增加回调函数支持,用于从存储器读取编码表
*************************************************************************************************************/
#include "system.h"
#include "unicode_gbk.h"



//回调接口-底层数据寄存器接口
static bool (*ReadGbkToUnicodeCode_CallBack)(u8 pData[2], u32 OffsetByteAddr);
static bool (*ReadUnicodeToGbkCode_CallBack)(u8 pData[2], u32 OffsetByteAddr);


/*************************************************************************************************************************
* 函数			:	bool GBK_UNICODE_Init(bool (*ReadGbkToUnicodeCode)(u8 pData[2], u32 OffsetByteAddr), bool (*ReadUnicodeToGbkCode)(u8 pData[2], u32 OffsetByteAddr))
* 功能			:	初始化GBK,UNICODE编码表
* 参数			:	ReadGbkToUnicodeCode:读取GBK转UNICODE编码表回调函数,OffsetByteAddr:字节偏移地址
					ReadUnicodeToGbkCode:读取UNICODE转GBK编码表回调函数,OffsetByteAddr:字节偏移地址					
* 返回			:	TRUE:初始化成功;FALSE:初始化失败
* 依赖			:	底层读写函数
* 作者			:	[email protected]
* 时间			:	2013-04-18
* 最后修改时间 	: 	2018-13-25
* 说明			: 	2018-13-25:增加底层接口回调,必须在底层接口初始化完成后才能进进行调用
*************************************************************************************************************************/ 
bool GBK_UNICODE_Init(bool (*ReadGbkToUnicodeCode)(u8 pData[2], u32 OffsetByteAddr), bool (*ReadUnicodeToGbkCode)(u8 pData[2], u32 OffsetByteAddr))
{
	const u16 GBK_Code = /*'国';//*/0xB9FA;	//测试的中文汉字
	
	ReadGbkToUnicodeCode_CallBack = ReadGbkToUnicodeCode;	//读取GBK转UNICODE编码表回调函数
	ReadUnicodeToGbkCode_CallBack = ReadUnicodeToGbkCode;	//读取UNICODE转GBK编码表回调函数
	if(ReadGbkToUnicodeCode == NULL || ReadUnicodeToGbkCode == NULL)
	{
		DEBUG("编码转换表回调函数有误!\r\n");
		return FALSE;
	}
	else 
	{
		if(OneGBKtoUNICODE(GBK_Code) != 0x56FD)
		{
			DEBUG("GBK to UNICODE编码表检查错误!\r\n");
			return FALSE;
		}
		else if(OneUNICODEtoGBK(0x56FD) != GBK_Code)
		{
			DEBUG("UNICODE to GBK编码表检查错误!\r\n");
			return FALSE;
		}
		else
			return TRUE;
	}
}




/*************************************************************************************************************************
* 函数			:	u16 OneGBKtoUNICODE(u16 GBKCode)
* 功能			:	将GBK编码转换为unicode编码
* 参数			:	GBK	
* 返回			:	unicode
* 依赖			:	底层读写函数
* 作者			:	[email protected]
* 时间			:	20120602
* 最后修改时间 	: 	20120602
* 说明			: 	需要flash中的码表支持
					GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe
*************************************************************************************************************************/ 
u16 OneGBKtoUNICODE(u16 GBKCode)
{
	u16 unicode;
	u8 buff[2];
	u16 *p;
	u8 ch,cl;

	ch = GBKCode >> 8;
	cl = GBKCode & 0x00ff;
	ch -= 0x81;
    cl -= 0x40;
	unicode = (ch*0xbf+cl)*2;
	ReadGbkToUnicodeCode_CallBack(buff, unicode); 	//读取GBK转UNICODE编码表

	p = (u16 *)buff;
	return *p;
}



/*************************************************************************************************************************
* 函数	:	u16 OneUNICODEtoGBK(u16 unicode)
* 功能	:	将unicode编码转换为GBK编码
* 参数	:	unicode
* 返回	:	GBK	
* 依赖	:	底层读写函数
* 作者	:	[email protected]
* 时间	:	20120602
* 最后修改时间 : 20120602
* 说明	: 	需要flash中的码表支持
			GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe
*************************************************************************************************************************/ 
u16 OneUNICODEtoGBK(u16 unicode)
{
	u32 offset;
	u8 temp[2];
	u16 res;
	
	if(unicode<=0X9FA5)offset=unicode-0X4E00;
	else if(unicode>0X9FA5)//是标点符号
	{
		if(unicode<0XFF01||unicode>0XFF61) return 0;	//没有对应编码
		offset=unicode-0XFF01+0X9FA6-0X4E00;    
	}  
	ReadUnicodeToGbkCode_CallBack(temp, offset*2);		//读取UNICODE转GBK编码表
	res=temp[0];
	res<<=8;
	res+=temp[1];
	
	return res ; //返回找到的编码			 
}


/*************************************************************************************************************************
* 函数			:	void GBKToUnicode(u16 *pGBK, u16 *pUnicode, u32 cnt)
* 功能			:	将多个GBK编码转换为UNICODE
* 参数			:	pGBK:GBK编码缓冲区
* 					pUnicode:UNCODE编码缓冲区
* 					cnt:转换编码个数
* 返回			:	无	
* 依赖			:	OneGBKtoUNICODE
* 作者			:	[email protected]
* 时间			:	20130403
* 最后修改时间 	: 	20130403
* 说明			: 	GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe
*************************************************************************************************************************/ 
void GBKToUnicode(u16 *pGBK, u16 *pUnicode, u32 cnt)
{
	while(cnt --)
	{
		*pUnicode = OneGBKtoUNICODE(*pGBK ++);
		pUnicode ++;
	}
}




/*************************************************************************************************************************
* 函数			:	void UnicodeToGBK(u16 *pUnicode, u16 *pGBK, u32 cnt)
* 功能			:	将多个UNICODE编码转换为GBK
* 参数			:	pUnicode:UNCODE编码缓冲区
* 					pGBK:GBK编码缓冲区
* 					cnt:转换编码个数
* 返回			:	无	
* 依赖			:	OneUNICODEtoGBK
* 作者			:	[email protected]
* 时间			:	20130403
* 最后修改时间 	: 	20130403
* 说明	: 			GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe
*************************************************************************************************************************/ 
void UnicodeToGBK(u16 *pUnicode, u16 *pGBK, u32 cnt)
{
	while(cnt --)
	{
		*pGBK = OneUNICODEtoGBK(*pUnicode ++);
		pGBK ++;
	}
}

unicode_gbk.h

/*************************************************************************************************************
 * 文件名		:	unicode_gbk.h
 * 功能			:	汉字编码转换
 * 作者			:	[email protected]
 * 创建时间		:	2013-04-03
 * 最后修改时间	:	2013-04-03
 * 详细			:	2018-03-25:增加回调函数支持,用于从存储器读取编码表
*************************************************************************************************************/
#ifndef UNICODE_GBK_H_
#define UNICODE_GBK_H_
#include "system.h"

bool GBK_UNICODE_Init(bool (*ReadGbkToUnicodeCode)(u8 pData[2], u32 OffsetByteAddr), bool (*ReadUnicodeToGbkCode)(u8 pData[2], u32 OffsetByteAddr));//初始化GBK,UNICODE编码表

u16 OneGBKtoUNICODE(u16 GBKCode);						//单个GBK转UNICODE
u16 OneUNICODEtoGBK(u16 unicode);						//单个UNICODE转GBK

void GBKToUnicode(u16 *pGBK, u16 *pUnicode, u32 cnt);	//将多个GBK编码转换为UNICODE
void UnicodeToGBK(u16 *pUnicode, u16 *pGBK, u32 cnt);	//将多个UNICODE编码转换为GBK


#endif /*UNICODE_GBK_H_*/

//初始化

//初始化双向字库编码转换接口-必须在存储器初始化后进行初始化,并且会验证编码表是否正确(存在)
	if(GBK_UNICODE_Init(ReadGbkToUnicodeCode, ReadUnicodeToGbkCode) == FALSE)
	{
		uart_printf("编码表初始化失败\r\n");
	}

//接口

///////////////////////////////////////////////////////////////////////////////////////////////////
//GBK与UNICODE双向编码表基址定义(在外部flash 中)
#define CODE_UtoG_BASE	(0xBB000)	   					//unicode转GBK码表-在外部falsh中的字节地址
#define CODE_GtoU_BASE	(0xC5500)						//GBK转unicode码表-在外部falsh中的字节地址

/***********************************************双向字库编码转换表接口************************************************/
//GbkToUnicode编码转换表底层接口,需要先初始化W25XXX芯片
__inline bool ReadGbkToUnicodeCode(u8 pData[2], u32 OffsetByteAddr)
{
	W25XXX_Read(&g_SysGlobal.W25X16_Handle, pData, CODE_GtoU_BASE+OffsetByteAddr, 2);	//地址加上基址
	return TRUE;
}

//UnicodeToGbk编码转换表底层接口,需要先初始化W25XXX芯片
__inline bool ReadUnicodeToGbkCode(u8 pData[2], u32 OffsetByteAddr)
{
	W25XXX_Read(&g_SysGlobal.W25X16_Handle, pData, CODE_UtoG_BASE+OffsetByteAddr, 2);	//地址加上基址
	return TRUE;
}

比如在FATFS中使用,如下:

#include "unicode_gbk.h" //编码转换
WCHAR ff_convert (	/* Converted code, 0 means conversion error */
	WCHAR	src,	/* Character code to be converted */
	UINT	dir		/* 0: Unicode to OEMCP, 1: OEMCP to Unicode */
)
{
	WCHAR c;

	if (src < 0x80) {	/* ASCII */
		c = src;
	} 
	else 
	{
		if (dir) 
		{		/* OEMCP to unicode */

			c = OneGBKtoUNICODE(src);
		} 
		else 
		{		/* Unicode to OEMCP */
			c = OneUNICODEtoGBK(src);
		}
	}

	return c;
}


这2个接口,用于从存储器中编码表指定偏移读取数据,W25XXX驱动见:https://blog.csdn.net/cp1300/article/details/79055864

编码表下载地址:https://download.csdn.net/download/cp1300/10361436


你可能感兴趣的:(CortexM3(STM32))