urldecode
可以参考 openssl 官方的实现: https://github.com/openssl/openssl/blob/0770c882150ea0159cc2b0a2cea2e8ed8442f36f/apps/ocsp.c
文中搜素 : urldecode 关键字
我把它摘录出来整理下,就是如下代码:
#include <ctype.h>
#include <stdio.h>
#include <string>
#include <string.h>
#include <stdlib.h>
#define _UC(c) ((unsigned char)(c))
int OPENSSL_hexchar2int(unsigned char c)
{
#ifdef CHARSET_EBCDIC
c = os_toebcdic[c];
#endif
switch (c) {
case '0':
return 0;
case '1':
return 1;
case '2':
return 2;
case '3':
return 3;
case '4':
return 4;
case '5':
return 5;
case '6':
return 6;
case '7':
return 7;
case '8':
return 8;
case '9':
return 9;
case 'a': case 'A':
return 0x0A;
case 'b': case 'B':
return 0x0B;
case 'c': case 'C':
return 0x0C;
case 'd': case 'D':
return 0x0D;
case 'e': case 'E':
return 0x0E;
case 'f': case 'F':
return 0x0F;
}
return -1;
}
static int urldecode(char *p)
{
unsigned char *out = (unsigned char *)p;
unsigned char *save = out;
for (; *p; p++) {
if (*p != '%')
*out++ = *p;
else if (isxdigit(_UC(p[1])) && isxdigit(_UC(p[2]))) {
/* Don't check, can't fail because of ixdigit() call. */
*out++ = (OPENSSL_hexchar2int(p[1]) << 4)
| OPENSSL_hexchar2int(p[2]);
p += 2;
}
else
return -1;
}
*out = '\0';
return (int)(out - save);
}
unicode2utf8
unicode 的几种表达方式:
-
字面值
- 比如以下表示
爱我中华
:\u5341\u4e8c\u795e\u5175\u5668
- 这只是一种书写表达方式
- 大多数语言,都在字符串中用这种表达方式,来表示这个字符是 unicode 编码来解析
- 比如以下表示
-
内存中
- 按 unicode 编码规则,真实在内存中的分布情况
- c/c++ 中字符串用比如 L"爱我中华" 来告知编译器,初始化变量时,需要按 unicode 编码规则,填充内存
- c/c++ 中使用 std::wstring 、 wchar_t 、 wchar 等类型处理 unicode 编码
具体 unicode2utf8 的代码类似如下:
int htoi(char s[])
{
return strtol(s, NULL, 16);
}
std::wstring decodeUnicode(const std::string &unicodeString)
{
std::wstring out;
char aChar;
int len = (int)unicodeString.size();
char *data = (char *)unicodeString.data();
for (int x = 0; x < len;) {
aChar = data[x++];
if (aChar == '\\') {
aChar = data[x++];
if (aChar == 'u') {
char tempChar[5] = { data[x++], data[x++], data[x++], data[x++], 0 };
out += (wchar_t)htoi(tempChar);
} else {
printf("format error!\n");
return L"";
}
} else
out += (wchar_t)aChar;
}
return out;
}
int main()
{
// 需要设置这行, 不然 wcstombs 会执行失败。 unicode 转 utf-8 必须要依赖系统字符集
setlocale(LC_ALL, "");
// 其他语言常见的字面值表达方式
std::string data0 = "\\u5341\\u4e8c\\u795e\\u5175\\u5668";
// 通过 decodeUnicode 转化为 c/c++ 可识别的 unicode 内存分布方式
std::wstring data2 = decodeUnicode(data0);
// 使用 wcstombs 函数把 unicode 编码转化为 utf-8 编码
len = wcstombs(nullptr, (wchar_t*)data2.data(), 0);
std::string data3;
data3.resize(len);
wcstombs((char*)data3.c_str(), (wchar_t*)data2.data(), data3.size());
printf("data3:%s\n", data3.c_str());
return 0;
}
unicode to utf8 也可以使用其他库,比如 https://github.com/breezechen/sconv