www.pudn.com > GSMEnDecode.rar > GSMEncode.hpp


#ifndef _CAESAR_GSMENCODE_H__DEF 
#define _CAESAR_GSMENCODE_H__DEF 
 
#include  
 
/* 
在PDU Mode中,可以采用三种编码方式来对发送的内容进行编码, 
它们是7-bit、8-bit和UCS2编码。7-bit编码用于发送普通的ASCII字符, 
它将一串7-bit的字符(最高位为0)编码成8-bit的数据,每8个字符可 
“压缩”成7个;8-bit编码通常用于发送数据消息,比如图片和铃声等; 
而UCS2编码用于发送Unicode字符。PDU串的用户信息(TP-UD)段最大容量 
是140字节,所以在这三种编码方式下,可以发送的短消息的最大字符数 
分别是160、140和70。这里,将一个英文字母、一个汉字和一个数据字节 
都视为一个字符。需要注意的是,PDU串的用户信息长度(TP-UDL),在各 
种编码方式下意义有所不同。7-bit编码时,指原始短消息的字符个数, 
而不是编码后的字节数。8-bit编码时,就是字节数。UCS2编码时,也是 
字节数,等于原始短消息的字符数的两倍。如果用户信息(TP-UD)中存在 
一个头(基本参数的TP-UDHI为1),在所有编码方式下,用户信息长度(TP 
-UDL)都等于头长度与编码后字节数之和。如果采用GSM 03.42所建议的压 
缩算法(TP-DCS的高3位为001),则该长度也是压缩编码后字节数或头长度 
与压缩编码后字节数之和。 
 
7byte编码原理: 
将源串每8个字符分为一组(最后一组可以不满8个)进行编码,在组内字符间压缩, 
但每组之间是没有什么联系的。 
压缩的方式是从下一个ASCII从低位取值错位,把8个7位的ASCII码压缩成7个8位的BYTE. 
 
UNICODE编码原理: 
国际化编码方式。没两个字节表示一个字,对于原ACSII字符高位填充0 
 
UCS2编码原理: 
将双字节的UNICODE以高位在前,低位在后的方式输出为BYTE流。 
 
UTF-8原理: 
UCS 字符 U+0000 到 U+007F (ASCII) 被编码为字节 0x00 到 0x7F (ASCII 兼容). 这意味着只包含 7 位 ASCII 字符的文件在 ASCII 和 UTF-8 两种编码方式下是一样的.  
所有 >U+007F 的 UCS 字符被编码为一个多个字节的串, 每个字节都有标记位集. 因此, ASCII 字节 (0x00-0x7F) 不可能作为任何其他字符的一部分.  
表示非 ASCII 字符的多字节串的第一个字节总是在 0xC0 到 0xFD 的范围里, 并指出这个字符包含多少个字节. 多字节串的其余字节都在 0x80 到 0xBF 范围里. 这使得重新同步非常容易, 并使编码无国界, 且很少受丢失字节的影响.  
可以编入所有可能的 231个 UCS 代码  
UTF-8 编码字符理论上可以最多到 6 个字节长, 然而 16 位 BMP 字符最多只用到 3 字节长.  
Bigendian UCS-4 字节串的排列顺序是预定的.  
字节 0xFE 和 0xFF 在 UTF-8 编码中从未用到.  
下列字节串用来表示一个字符. 用到哪个串取决于该字符在 Unicode 中的序号. 
 
U-00000000 - U-0000007F:  0xxxxxxx   
U-00000080 - U-000007FF:  110xxxxx 10xxxxxx   
U-00000800 - U-0000FFFF:  1110xxxx 10xxxxxx 10xxxxxx   
U-00010000 - U-001FFFFF:  11110xxx 10xxxxxx 10xxxxxx 10xxxxxx   
U-00200000 - U-03FFFFFF:  111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx   
U-04000000 - U-7FFFFFFF:  1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx   
 
xxx 的位置由字符编码数的二进制表示的位填入. 越靠右的 x 具有越少的特殊意义. 只用最短的那个足够表达一个字符编码数的多字节串. 注意在多字节串中, 第一个字节的开头"1"的数目就是整个串中字节的数目. 
 
例如: Unicode 字符 U+00A9 = 1010 1001 (版权符号) 在 UTF-8 里的编码为: 
 
11000010 10101001 = 0xC2 0xA9 
 
而字符 U+2260 = 0010 0010 0110 0000 (不等于) 编码为: 
 
11100010 10001001 10100000 = 0xE2 0x89 0xA0 
 
这种编码的官方名字拼写为 UTF-8, 其中 UTF 代表 UCS Transformation Format. 请勿在任何文档中用其他名字 (比如 utf8 或 UTF_8) 来表示 UTF-8, 当然除非你指的是一个变量名而不是这种编码本身. 
 
 
*/ 
 
/* 
GSMEncode:用以实现在GSM应用中常见的字符串处理,与编码转化的问题。会根据情况继续扩充 
作者:邹德强。 
江西捷德智能卡有限公司。 
name_caesar@msn.com 
*/ 
 
class CGSMEnCode 
{ 
public: 
	/******************************************************************* 
	函 数 名 称:	GSMString2Bytes(const char* pSrc, BYTE* pDst, int nSrcLength) 
	功 能 描 述:	把可打印字符串转化为字节数据。 
	参 数 说 明:	pSrc: 字符串指针。pDst:字节数据指针。nSrcLength:源字符串长度。 
	返回值 说明:	-1:		数据错误 
	>=0:	字节数据长度 
	作       者:	邹德强 
	更 新 日 期:	2004.2.26 
	*******************************************************************/ 
	static int GSMString2Bytes(const CHAR* pSrc, BYTE* pDst, int nSrcLength) 
	{ 
		try 
		{ 
			for(int i=0;i='0' && *pSrc<='9') 
				{ 
					*pDst = (*pSrc - '0')<<4; 
				} 
				else 
					if(*pSrc>='a' && *pSrc<='f') 
					{ 
						*pDst = (*pSrc - 'a' + 0x0A)<<4; 
					} 
					else 
						if(*pSrc>='A' && *pSrc<='F') 
						{ 
							*pDst = (*pSrc - 'A' + 0x0A)<<4; 
						} 
						else 
						{ 
							return -1; 
						} 
						 
						pSrc++; 
						 
						//输出低四位 
						if(*pSrc>='0' && *pSrc<='9') 
						{ 
							*pDst |= (*pSrc - '0'); 
						} 
						else 
							if(*pSrc>='a' && *pSrc<='f') 
							{ 
								*pDst |= (*pSrc - 'a' + 0x0A); 
							} 
							else 
								if(*pSrc>='A' && *pSrc<='F') 
								{ 
									*pDst |= (*pSrc - 'A' + 0x0A); 
								} 
								else 
								{ 
									return -1; 
								} 
								 
								pSrc++; 
								pDst++; 
			} 
		} 
		catch (...)  
		{ 
			return -1; 
		} 
		 
		return nSrcLength>>1; 
	} 
 
 
 
	/******************************************************************* 
	函 数 名 称:	GSMBytes2String(const BYTE* pSrc, CHAR* pDst, int nSrcLength) 
	功 能 描 述:	把可打印字符串转化为字节数据。 
	参 数 说 明:	pSrc: 字节数据指针。pDst:字符串指针。nSrcLength:源字符串长度。 
	返回值 说明:	-1:		数据错误 
	>=0:	字节数据长度 
	作       者:	邹德强 
	更 新 日 期:	2004.2.26 
	*******************************************************************/ 
	static int GSMBytes2String(const BYTE* pSrc, CHAR* pDst, int nSrcLength) 
	{ 
		try 
		{ 
			for(int i=0;i=0:	字节数据长度 
	作       者:	邹德强 
	更 新 日 期:	2004.2.26 
	*******************************************************************/ 
	static int GSMEncodeUCS2(const CHAR* pSrc, BYTE* pDst, int nSrcLength) 
	{ 
		int	nDstLen	=	0; 
		int nOffset	=	nSrcLength; 
		int nTotal	=	0; 
		WCHAR wchr[8]; 
		 
		try 
		{		 
			//以8 WCHAR 为段。避免开启过大的Buffer 
			while(nOffset>0) 
			{ 
				if(nOffset>8) 
				{ 
					nDstLen = ::MultiByteToWideChar(CP_ACP, 0, pSrc, 8, wchr, 8); 
					if(nDstLen>0) 
					{ 
						for(int i=0;i0) 
					{ 
						for(int i=0;i=0:	字节数据长度 
	作       者:	邹德强 
	更 新 日 期:	2004.2.26 
	*******************************************************************/ 
	static int GSMDecodeUCS2(const BYTE* pSrc, CHAR* pDst, int nSrcLength) 
	{ 
		int	nDstLen	=	0; 
		int nOffset	=	nSrcLength; 
		int nTotal	=	0; 
		WCHAR wchr[8]; 
		 
		try 
		{ 
			while(nOffset>0) 
			{ 
				if(nOffset>16) 
				{ 
					for(int i=0;i<8;i++) 
					{ 
						//由BYTE组成UNICODE 
						wchr[i]	=	*(pSrc++)<<8; 
						wchr[i]	|=	*(pSrc++); 
					} 
					//把UNICODE分散成字符串 
					nDstLen	=	::WideCharToMultiByte(CP_ACP,0,wchr,8,pDst,16,NULL,NULL); 
					 
					pDst	+=	nDstLen; 
					nOffset	-=	16; 
					nTotal	+=	nDstLen; 
				} 
				else 
				{ 
					for(int i=0;i>1;i++) 
					{ 
						//由BYTE组成UNICODE 
						wchr[i]	=	*(pSrc++)<<8; 
						wchr[i]	|=	*(pSrc++); 
					} 
					//把UNICODE分散成字符串 
					nDstLen =	::WideCharToMultiByte(CP_ACP,0,wchr,nOffset>>1,pDst,nOffset,NULL,NULL); 
					nTotal	+=	nDstLen; 
					pDst	+=	nDstLen; 
					*pDst	=	0; 
					 
					break; 
				} 
			} 
		} 
		catch (...)  
		{ 
			return -1; 
		} 
		 
		return nTotal; 
	} 
	 
	 
	 
	 
 
	/******************************************************************* 
	函 数 名 称:	GSMEncode7bit(const char* pSrc, unsigned char* pDst, int nSrcLength) 
	功 能 描 述:	把ACSII流转化为7byteASCII流 
	参 数 说 明:	pSrc: 源指针。pDst:目标指针。nSrcLength:源字符串长度。 
	返回值 说明:	-1:		数据错误 
	>=0:	目标数据长度 
	作       者:	邹德强 
	更 新 日 期:	2004.2.26 
	*******************************************************************/ 
	static int GSMEncode7bit(const char* pSrc, unsigned char* pDst, int nSrcLength) 
	{ 
		 
		int	nbyt	=	0x00; 
		int	ntotal	=	0x00; 
		 
		for(int nlen=1;nlen<=nSrcLength;nlen++,pSrc++) 
		{		 
			//每8个byte一组的下标 
			nbyt 	= 	nlen%0x08; 
			 
			//第8个byte不处理 
			if(nbyt	==	0x00) 
			{ 
				continue; 
			} 
			else 
			{ 
				//把7bit数据转化为8bit数据 
				*(pDst++)	=	(*pSrc>>(nbyt-1)) | ((nlen==nSrcLength) ? 0x00 : (*(pSrc+1)<<(8-nbyt))); 
 
				//总处理数加1 
				ntotal	++; 
			} 
 
			 
		} 
 
		return ntotal; 
	} 
     
	 
	 
	 
	 
	/******************************************************************* 
	函 数 名 称:	GSMDecode7bit(const unsigned char* pSrc, char* pDst, int nSrcLength) 
	功 能 描 述:	把7byteASCII流转化为ACSII流 
	参 数 说 明:	pSrc: 源指针。pDst:目标指针。nSrcLength:源字符串长度。 
	返回值 说明:	-1:		数据错误 
					>=0:	目标数据长度 
	作       者:	邹德强 
	更 新 日 期:	2004.2.26 
	*******************************************************************/ 
	static int GSMDecode7bit(const unsigned char* pSrc, char* pDst, int nSrcLength) 
	{ 
		int	nbyt	=	0x00; 
		int ntotal	=	0x00; 
		 
		for(int nlen=1;nlen<=nSrcLength;nlen++,pSrc++) 
		{ 
			ntotal	++; 
 
			//每7个byte一组的下标 
			nbyt	=	nlen%0x07; 
 
			if(nbyt == 0x01) 
			{ 
				//每组第一个 
				*(pDst++)	=	*pSrc & 0x7F; 
			} 
			else 
			if(nbyt	== 0x00) 
			{ 
				//每组最后一个 
				*(pDst++)	=	*pSrc<<6 & 0x7F | *(pSrc-1)>>2; 
 
				//每组第7个bit完毕后增加一个输出 
				*(pDst++)	=	*pSrc>>1; 
				 
				//总处理数加1 
				ntotal++; 
			} 
			else 
			{ 
				*(pDst++)	=	(*pSrc<<(nbyt-1) & 0x7F) |  (*(pSrc-1)>>(9-nbyt)); 
			} 
		} 
 
		//串尾标识 
		*(pDst)	=	0x00; 
 
		return ntotal; 
	} 
 
	/******************************************************************* 
	函 数 名 称:	GSMUCS2ToUTF8(const CHAR* pSrc, BYTE* pDst, int nSrcLength) 
	功 能 描 述:	把UCS2的串转化为UTF-8 
	参 数 说 明:	pSrc: UCS2指针。pDst:UTF-8指针。nSrcLength:源字符串长度。 
	返回值 说明:	-1:		数据错误 
	>=0:	UTF8数据长度 
	作       者:	邹德强 
	更 新 日 期:	2004.2.26 
	*******************************************************************/ 
	static int GSMEncodeUTF8(const BYTE* pSrc, BYTE* pDst, int nSrcLength) 
	{ 
		int nTotal	=	0; 
		WCHAR wchr; 
		 
		for(int nLen=0;nLen>4); 
				*(pDst++)	=	0x80 | (HIBYTE(wchr<<2) & 0x3f); 
				*(pDst++)	=	0x80 | (LOBYTE(wchr) & 0x3f); 
				nTotal		+=	3; 
			} 
		} 
		 
		return nTotal; 
	} 
	 
	/******************************************************************* 
	函 数 名 称:	GSMUtf8ToUcs2(const CHAR* pSrc, BYTE* pDst, int nSrcLength) 
	功 能 描 述:	把UTF-8的串转化为UCS2 
	参 数 说 明:	pSrc: UTF-8数据指针。pDst:UCS2指针。nSrcLength:源字符串长度。 
	返回值 说明:	-1:		数据错误 
	>=0:	UCS2数据长度 
	作       者:	邹德强 
	更 新 日 期:	2004.2.26 
	*******************************************************************/ 
	static int GSMDecodeUTF8(const BYTE* pSrc, BYTE* pDst, int nSrcLength) 
	{ 
		int nTotal	=	0; 
		BYTE bychr; 
		for(int nLen=0;nLen=0xc0 && bychr<=0xdf) 
			{ 
				//第二种模式 
				*(pDst++)	=	(bychr>>2) & 0x07; 
				*(pDst++)	=	(bychr<<6) | (*(pSrc++) & 0x3F); 
				nLen		+=	2; 
			} 
			else 
			{ 
				//第三种模式 
				*(pDst++)	=	(bychr<<4) | ((*pSrc>>2) & 0x0F); 
				bychr		=	*(pSrc++); 
				*(pDst++)	=	(bychr<<6) | (*(pSrc++) & 0x3F); 
				nLen		+=	3; 
			} 
		} 
		 
		return nTotal; 
	} 
}; 
#endif