⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gsmencode.hpp

📁 短信中使用的各种字符编码方式互相转换的函数
💻 HPP
字号:
#ifndef _CAESAR_GSMENCODE_H__DEF
#define _CAESAR_GSMENCODE_H__DEF

#include <windows.h>

/*
在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<nSrcLength;i+=2)
			{
				//输出高4位
				if(*pSrc>='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<nSrcLength;i++)
			{
				::wsprintf(pDst+i*2,"%02X",pSrc[i]);
			}
		}
		catch (...) 
		{
			return -1;
		}
		
		return nSrcLength<<1;
	}


	
	
	/*******************************************************************
	函 数 名 称:	GSMEncodeUCS2(const CHAR* pSrc, BYTE* pDst, int nSrcLength)
	功 能 描 述:	把Ascii串转化为UCS2字符串
	参 数 说 明:	pSrc: 字节数据指针。pDst:UCS2指针。nSrcLength:源字符串长度。
	返回值 说明:	-1:		数据错误
	>=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;i<nDstLen;i++)
						{
							//取高位放在第一个BYTE
							*pDst++		=	HIBYTE(wchr[i]);
							//取低位放在下一个BYTE
							*(pDst++)	=	LOBYTE(wchr[i]);
						}
						
					}
					else
					{
						return -1;
					}
					
					nOffset	-=	8;
					nTotal	+=	nDstLen<<1;
					pSrc	+=	8;	
				}
				else
				{
					nDstLen	=	::MultiByteToWideChar(CP_ACP, 0, pSrc, nOffset, wchr, 8);
					if(nDstLen>0)
					{
						for(int i=0;i<nDstLen;i++)
						{
							//取高位放在第一个BYTE
							*(pDst++)		=	HIBYTE(wchr[i]);
							//取低位放在下一个BYTE
							*(pDst++)	=	LOBYTE(wchr[i]);
						}
					}
					else
					{
						return -1;
					}
					
					nTotal	+=	nDstLen<<1;
					break;
				}
			}
			
		}
		catch(...)
		{
			return -1;
		}
		
		return nTotal;
	}
	
	

	
	
	/*******************************************************************
	函 数 名 称:	GSMUncodeUCS2(const BYTE* pSrc, CHAR* pDst, int nSrcLength)
	功 能 描 述:	把UCS2流转化为ASCII流
	参 数 说 明:	pSrc: UCS2指针。pDst:字节数据指针。nSrcLength:源字符串长度。
	返回值 说明:	-1:		数据错误
					>=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<nOffset>>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<nSrcLength;nLen+=2)
		{
			//取一个Unicode字符
			wchr	=	*(pSrc++)<<8;
			wchr	|=	*(pSrc++);
			
			if(wchr<=0x007F)
			{
				//第一种编码模式
				*(pDst++)	=	LOBYTE(wchr);
				nTotal		++;
			}
			else
			if(wchr<=0x07FF)
			{
				//第二种编码模式
				*(pDst++)	=	0xc0 | HIBYTE(wchr<<2);
				*(pDst++)	=	0x80 | (LOBYTE(wchr) & 0x3f);
				nTotal		+=	2;
			}
			else
			{
				//第三种编码模式
				*(pDst++)	=	0xe0 | HIBYTE(wchr>>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<nSrcLength;nTotal+=2)
		{
			//判断首字符
			bychr	=	*(pSrc++);
			
			if(bychr <= 0x7f)
			{
				//第一种模式
				*(pDst++)	=	0x00;
				*(pDst++)	=	bychr;
				nLen		++;
			}
			else
			if(bychr>=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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -