关于EncodeURL和DecodeURL的实现(C++)在网上有非常多不同的版本。对须要编码的字符集的选取不统一,那么就需要来统一一下,并且写一个运行最快的实现。需要针对std::string&和char*这两个参数分别写一个实现方法,因为这样做的效率是最高的。虽然看起来是比较麻烦,但还是最好加上。如果看不懂,那就直接测试,保证 0 issure。[该标准按照最新RFC3986实行]
static const char _X[] = { 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, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0,
0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 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,
0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 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 };
std::string_view DecodeURL(std::string& s) {
char* o = (char*)s.c_str(), * c = (char*)s.c_str();
const char* e = c + s.size(); while (c < e) {
if (*c == '%' && c < e - 2) {
*o = (_X[c[1]] << 4) | _X[c[2]]; c += 2;
} else if (*c == '+') {
*o = ' ';
} else if (o != c) *o = *c; ++o; ++c;
} return std::string_view(s.data(), o - s.data());
}
std::string DecodeURL(const char* d) {
std::string s(d); char* o = (char*)s.data(), * c = (char*)s.data();
const char* e = c + s.length(); while (c < e) {
if (*c == '%' && c < e - 2) {
*o = (_X[c[1]] << 4) | _X[c[2]]; c += 2;
} else if (*c == '+') {
*o = ' ';
} else if (o != c) *o = *c; ++o; ++c;
} return std::string(s.c_str(), o - s.c_str());
}
static char _HEX_[] = { 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, 0, 0, 0, 0, 0, 0x2b, 0x21, 0, 0x23, 0x24, 0, 0x26, 0x27, 0x28, 0x29, 0x2a, 0, 0x2c, 0x2d , 0x2e, 0x2f,
0x30 , 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0, 0x3d, 0, 0x3f, 0x40, 0x41,
0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52,
0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0, 0x5d, 0, 0x5f, 0, 0x61, 0x62, 0x63, 0x64,
0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75,
0x76, 0x77, 0x78, 0x79, 0x7a, 0, 0, 0, 0x7e, 0 };//RFC3986
std::string EncodeURL(const std::string& s) {
std::string r; for (char c : s) {
if (c > '\377') {
if (_HEX_[c])r.push_back(_HEX_[c]);//if (_RFC2396[c])r.push_back(c);
else {
r.push_back(0x25); char o = (c & 0xF0) >> 4;
o += o > 9 ? 0x37 : 0x30; r.push_back(o);
o = c & 0x0F; o += o > 9 ? 0x37 : 0x30; r.push_back(o);
}
} else {
r.push_back(0x25); char o = (static_cast<uint8_t>(c) & 0xF0) >> 4;
o += o > 9 ? 0x37 : 0x30; r.push_back(o);
o = static_cast<uint8_t>(c) & 0x0F;
o += o > 9 ? 0x37 : 0x30; r.push_back(o);
}
} return r;
}
std::string EncodeURL(const char* c) {
std::string r; while (*c) {
if (*c > '\377') {
if (_HEX_[*c])r.push_back(_HEX_[*c]);
else {
r.push_back(0x25); char o = (*c & 0xF0) >> 4;
o += o > 9 ? 0x37 : 0x30; r.push_back(o);
o = *c & 0x0F; o += o > 9 ? 0x37 : 0x30; r.push_back(o);
}
} else {
r.push_back(0x25);
char o = (static_cast<uint8_t>(*c) & 0xF0) >> 4;
o += o > 9 ? 0x37 : 0x30; r.push_back(o);
o = static_cast<uint8_t>(*c) & 0x0F;
o += o > 9 ? 0x37 : 0x30; r.push_back(o);
} ++c;
} return r;
}
如果还有更快的方法,也可以欢迎留言讨论,因为我不相信还有比我更快的方法(在满足完全的正确率前提下)