使用 boost 和标准 C++ 的 Unicode 安全查找

Posted

技术标签:

【中文标题】使用 boost 和标准 C++ 的 Unicode 安全查找【英文标题】:Unicode safe find using boost and standard C++ 【发布时间】:2015-09-30 12:44:00 【问题描述】:

考虑以下 sn-p:

namespace bl = boost::locale;
static bl::generator gen;
static auto loc = gen("en_US.UTF-8");
std::string foo8 = u8"Föo";
std::string deco = bl::normalize(foo8,bl::norm_nfd,loc);
std::string comp = bl::normalize(foo8,bl::norm_nfc,loc);
std::cout << "decomposed: " << deco.find("o") << ", composed: " << comp.find("o") <<"\n";

这给出:“分解:1,组合:3”。

现在,正确答案取决于整理因素,但在大多数情况下,后者才是我想要的——o 的第一个位置,而不是分解的 ö 的第一部分。显然,对于这个示例,我可以将字符串规范化为 NFC 以确保获得所需的结果,但这不适用于无法组合字素簇的情况。

此外,X.find("ö") 将具有实现定义的行为,因为无法保证 ö 在搜索中的编码方式。

我可以通过在 UAX 29 中实现算法或通过规范化搜索字符串来实现 Unicode 安全查找功能,但我想知道是否有办法通过使用 C++ std 库和 boost 来做到这一点——也许通过将语言环境与字符串算法相结合——但我还没有找到解决方案。

谁有明确的答案?我知道我可以使用 ICU,并且 boost::locale 是围绕 ICU 库的 c++ 友好包装器(至少如果你想要完整的 unicode 支持的话)。

【问题讨论】:

一个数字从样本输出中被截断 标准库绝对是“不”。你会考虑ICU吗? 我看到 boost、boost::locale 和 unicode。我认为 icu 已经是那里的依赖项 ICU 是一个依赖项,我可以忍受(有点),但我宁愿不必与 ICU 一起工作——尽管如果需要我可以实现一个包装函数。从 C++ 的角度来看,ICU 的界面非常糟糕。 【参考方案1】:

此外,X.find("ö") 将具有实现定义的行为,因为没有保证 ö 在搜索中的编码方式。

遗憾的是,您对此确实无能为力。作为 API 的客户端,您必须确保始终使用 u8 前缀调用它,并且参数也被规范化。可以编写一个find 函数在搜索之前对输入进行规范化,但没有办法减轻编码中的歧义。

我可以通过在 UAX 29 中实现算法来实现 Unicode 安全查找功能

Boost.Locales segment_index 已经实现了,不需要实现它。

我想知道是否有办法通过使用 C++ std 库和 boost 来做到这一点——也许通过将语言环境与字符串算法相结合——但我还没有找到解决方案。

标准库对此毫无用处,据我所知,Boost.Locale 没有字符串搜索功能。 ICU 的字符串搜索功能使用规范等价的概念,这可能是您最好的选择。

【讨论】:

哎呀,我写这个问题搞砸了。它应该是“但是这在无法组合的字素簇的情况下不起作用。我已经纠正了这个和代码复制中的错误。你的答案似乎是 UAX 29不过要成为赢家——这应该允许我编写一个 unicode 安全、非转换的查找,而无需对 UAX 29 的表进行编码的所有手工劳动,这是最终目标。我会在接受答案之前验证这一点。跨度> 可悲的是,segment_index 并不真正适合我的目的,因为使用它来实现 unicode 感知查找会使我的性能无法接受。不过,显然我会得到最好的答案。我已编辑您的答案以反映我对问题所做的更正。 感谢您的编辑。是的,我真的希望我有更好的东西给你,但是没有太多选择:(

以上是关于使用 boost 和标准 C++ 的 Unicode 安全查找的主要内容,如果未能解决你的问题,请参考以下文章

VS2008下直接安装使用Boost库1 46 1版本

VS2015编译boost1.62

c++ boost文件夹放在哪

模拟实现c++标准库和boost库中的智能指针

如何在Visual Studio 2010中使用C++“准”标准库 Boost 1.44.0

boost::asio基本使用