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;i 0) { 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