gpt4 book ai didi

c++ - libxml2 xmlChar * 到 std::wstring

转载 作者:太空狗 更新时间:2023-10-29 23:52:46 30 4
gpt4 key购买 nike

libxml2 似乎将其所有字符串存储为 UTF-8,如 xmlChar *

/**
* xmlChar:
*
* This is a basic byte in an UTF-8 encoded string.
* It's unsigned allowing to pinpoint case where char * are assigned
* to xmlChar * (possibly making serialization back impossible).
*/
typedef unsigned char xmlChar;

因为 libxml2 是一个 C 库,所以没有提供从 xmlChar * 中获取 std::wstring 的例程。我想知道在 C++11 中将 xmlChar * 转换为 std::wstring谨慎方法是否是使用 mbstowcs C函数,通过这样的东西(正在进行中):

std::wstring xmlCharToWideString(const xmlChar *xmlString) {
if(!xmlString){abort();} //provided string was null
int charLength = xmlStrlen(xmlString); //excludes null terminator
wchar_t *wideBuffer = new wchar_t[charLength];
size_t wcharLength = mbstowcs(wideBuffer, (const char *)xmlString, charLength);
if(wcharLength == (size_t)(-1)){abort();} //mbstowcs failed
std::wstring wideString(wideBuffer, wcharLength);
delete[] wideBuffer;
return wideString;
}

编辑: 仅供引用,我非常清楚 xmlStrlen 返回的内容;它是用于存储字符串的 xmlChar 的数量;我知道这不是 characters 的数量,而是 unsigned char 的数量。如果我将它命名为 byteLength 就不会那么困惑了,但我认为它会更清楚,因为我同时拥有 charLengthwcharLength。至于代码的正确性,wideBuffer 总是大于或等于 以容纳缓冲区所需的大小(我相信)。因为需要比 wide_t 更多空间的字符将被截断(我认为)。

最佳答案

xmlStrlen() 返回 xmlChar* 字符串中的 UTF-8 编码代码单元数。这与转换数据时所需的 wchar_t 编码代码单元的数量不同,因此不要使用 xmlStrlen() 来分配 的大小wchar_t 字符串。您需要调用std::mbtowc()一次得到正确的长度,然后分配内存,再次调用mbtowc()填充内存。您还必须使用 std::setlocale()告诉 mbtowc() 使用 UTF-8(弄乱语言环境可能不是一个好主意,尤其是在涉及多个线程的情况下)。例如:

std::wstring xmlCharToWideString(const xmlChar *xmlString)
{
if (!xmlString) { abort(); } //provided string was null

std::wstring wideString;

int charLength = xmlStrlen(xmlString);
if (charLength > 0)
{
char *origLocale = setlocale(LC_CTYPE, NULL);
setlocale(LC_CTYPE, "en_US.UTF-8");

size_t wcharLength = mbtowc(NULL, (const char*) xmlString, charLength); //excludes null terminator
if (wcharLength != (size_t)(-1))
{
wideString.resize(wcharLength);
mbtowc(&wideString[0], (const char*) xmlString, charLength);
}

setlocale(LC_CTYPE, origLocale);
if (wcharLength == (size_t)(-1)) { abort(); } //mbstowcs failed
}

return wideString;
}

一个更好的选择,因为你提到了 C++11,是将 std::codecvt_utf8std::wstring_convert 一起使用,这样你就不必处理语言环境:

std::wstring xmlCharToWideString(const xmlChar *xmlString)
{
if (!xmlString) { abort(); } //provided string was null
try
{
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> conv;
return conv.from_bytes((const char*)xmlString);
}
catch(const std::range_error& e)
{
abort(); //wstring_convert failed
}
}

另一种选择是使用实际的 Unicode 库,例如 ICU 或 ICONV,来处理 Unicode 转换。

关于c++ - libxml2 xmlChar * 到 std::wstring,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14107268/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com