awk ‘BEGIN{for(i=0;i<8;i++){for(j=0;j<16;j++){printf("%X\n", i*16+j)}}}‘ | awk ‘{p="";if(NR<=16)p="0";printf("console.log(\"%s\",escape(\"\\x%s%s\")==\"\\x%s%s\");\n",$1, p, $1, p, $1)}‘
可以得到128行代码:
console.log("0",escape("\x00")=="\x00");
console.log("1",escape("\x01")=="\x01");
console.log("2",escape("\x02")=="\x02");
console.log("3",escape("\x03")=="\x03");
console.log("4",escape("\x04")=="\x04");
console.log("5",escape("\x05")=="\x05");
console.log("6",escape("\x06")=="\x06");
console.log("7",escape("\x07")=="\x07");
console.log("8",escape("\x08")=="\x08");
console.log("9",escape("\x09")=="\x09");
console.log("A",escape("\x0A")=="\x0A");
console.log("B",escape("\x0B")=="\x0B");
console.log("C",escape("\x0C")=="\x0C");
console.log("D",escape("\x0D")=="\x0D");
console.log("E",escape("\x0E")=="\x0E");
console.log("F",escape("\x0F")=="\x0F");
…
在Chrome下面打开控制台,执行以上代码,可以得到如下:
0 false
1 false
2 false
3 false
4 false
5 false
…
其中false代表需要转义的字符,true代表无需转义的字符,这样我就可以得到128个字符中转义成%XX的字符数了。当然为了保险起见,这些被转义的字符是否真的变成%XX,还可以通过这条命令的结果在Javascript中验证一下。
awk ‘BEGIN{for(i=0;i<8;i++){for(j=0;j<16;j++){printf("%X\n", i*16+j)}}}‘ | awk ‘{p="";if(NR<=16)p="0";printf("if(escape(\"\\x%s%s\")!=\"\\x%s%s\")console.log(\"%s\", escape(\"\\x%s%s\")==\"%%%s%s\");\n", p, $1, p, $1, $1, p, $1, p, $1)}’
经检验,与我们开始的判断完全吻合,大家可以自己试一下。现在,我们用CPP代码来实现escape:
/*! * \brief 将UCS-2编码文本转义 * \param[in] sUCValue: sUCValue UCS2格式字符串 * \return string 转换后的字符串 */ std::string escape(const std::string& sUCValue) { const static bool s_esc[256] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; const T_UC* bpos = (T_UC*)&sUCValue[0]; const T_UC* epos = bpos + (sUCValue.size()/sizeof(T_UC)); std::string sValue = __encodeBase(s_esc, bpos, epos, "%", "%u", ""); return sValue; }
其中__encodeBase的实现如下:
char* ITOX2(int x, char vx[2]) { static char MAPX[16] = { ‘0‘, ‘1‘, ‘2‘, ‘3‘, ‘4‘, ‘5‘, ‘6‘, ‘7‘, ‘8‘, ‘9‘, ‘A‘, ‘B‘, ‘C‘, ‘D‘, ‘E‘, ‘F‘ }; vx[0] = MAPX[(unsigned char)x>>4]; vx[1] = MAPX[x&0x0F]; return vx; } char* ITOX4(int x, char vx[4]) { ITOX2((unsigned short)(x&0xFF00)>>8, vx); ITOX2(x&0xFF, vx+2); return vx; } std::string __encodeBase(const bool esc[256], const T_UC* bpos, const T_UC* epos, const char* prefix2, const char* prefix4, const char* subfix) { int bSize2 = strlen(prefix2); int bSize4 = strlen(prefix4); int eSize = strlen(subfix); char v2[16] = {0}; char v4[16] = {0}; char* p2 = v2+bSize2; char* p4 = v4+bSize4; memcpy(v2, prefix2, bSize2); memcpy(v4, prefix4, bSize4); memcpy(p2+2, subfix, eSize); memcpy(p4+4, subfix, eSize); int s2 = bSize2+2+eSize; int s4 = bSize4+4+eSize; std::string sValue((bSize4+eSize+4)*(epos-bpos), 0); char* tpos = &sValue[0]; while (bpos < epos) { if (*bpos & 0xff00) { ITOX4(*bpos, p4); memcpy(tpos, v4, s4); tpos += s4; ++bpos; } else if (esc[*bpos & 0xff]) { ITOX2(*bpos, p2); memcpy(tpos, v2, s2); tpos += s2; ++bpos; } else { *tpos++ = *bpos++; } } sValue.resize(tpos - &sValue[0]); return sValue; }
同理我们来实现encodeURIComponent。先得到表示256个字符是否需要转义的状态map,通过以下结果得到Javascript代码:
awk ‘BEGIN{for(i=0;i<8;i++){for(j=0;j<16;j++){printf("%X\n", i*16+j)}}}‘ | awk ‘{p="";if(NR<=16)p="0";printf("console.log(\"%s\",encodeURIComponent(\"\\x%s%s\")==\"\\x%s%s\");\n",$1, p, $1, p, $1)}‘
CPP代码实现:
/*! * \brief 将UTF-8编码文本转义 * \param[in] sData: utf-8格式字符串 * \return string 转换后的字符串 */ std::string encodeURIComponent(const std::string& sData) { const static bool s_esc[256] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; std::string sValue; sValue.reserve(sData.size() * 4); T_UTF8 *bpos = (T_UTF8*)&sData[0]; T_UTF8 *epos = bpos + sData.size(); while (bpos<epos) { if (!s_esc[*bpos & 0xff]) { sValue += *bpos; } else { char vx[4]={‘%‘, 0, 0, 0}; ITOX2(*bpos, vx+1); sValue += vx; } bpos++; } return sValue; }
两者对应的decode函数分别如下:
/*! * \brief 将文本解码成utf-8 * \param[in] sData, URIComponent之后的字符串 * \return string 转换后的字符串,utf-8格式 */ std::string decodeURIComponent(const std::string& sData) { std::string sResult = sData; int x, y; for (x = 0, y = 0; sData[y]; x++, y++) { if((sResult[x] = sData[y]) == ‘%‘) { sResult[x] = x2c(&sData[y+1]); y += 2; } } return sResult.substr(0, x); } /*! * \brief 将文本解码成unicode * \param[in] sData, escape之后的字符串 * \return string 转换后的字符串,unicode格式 */ std::string unescape(const std::string& sData) { struct HEX { static bool isHex(T_UC ch) { return (ch>=‘0‘ && ch<=‘9‘ || ch>=‘A‘ && ch<=‘F‘ || ch>=‘a‘ && ch<=‘f‘); } }; std::string sUCValue = UCS2(sData); std::string sValue(sUCValue.size(), 0); T_UC *ucbpos = (T_UC *)&sUCValue[0]; T_UC *ucepos = ucbpos + sUCValue.size()/sizeof(T_UC); T_UC *ucbResult = (T_UC *)&sValue[0]; #define HEXUCTOI(uc) ((uc >= ‘a‘)? (uc - ‘a‘ + 10) : (uc >= ‘A‘) ? (uc - ‘A‘ + 10) : (uc - ‘0‘)) while (ucbpos < ucepos) { if (*ucbpos != 0x25) // % { *ucbResult++ = *ucbpos++; } else if((*(ucbpos+1)==‘u‘ || *(ucbpos+1)==‘U‘) && (ucepos>ucbpos+5) && HEX::isHex(*(ucbpos+2)) && HEX::isHex(*(ucbpos+3)) && HEX::isHex(*(ucbpos+4)) && HEX::isHex(*(ucbpos+5))) { *ucbResult++ = (HEXUCTOI(*(ucbpos+2))<<12) | (HEXUCTOI(*(ucbpos+3))<<8) | (HEXUCTOI(*(ucbpos+4))<<4) | (HEXUCTOI(*(ucbpos+5))); ucbpos=ucbpos+6; } else if ((ucepos>ucbpos+2) && HEX::isHex(*(ucbpos+1)) && HEX::isHex(*(ucbpos+2)) ) { *ucbResult++ = (HEXUCTOI(*(ucbpos+1))<<4) | (HEXUCTOI(*(ucbpos+2))); ucbpos=ucbpos+3; } else { *ucbResult++ = *ucbpos++; } } sValue.resize((ucbResult-(T_UC *)&sValue[0])*sizeof(T_UC)); return sValue; }
另外,还有json、xml、html的转义,后续再介绍。
原文:http://blog.csdn.net/yulongli/article/details/23671785