C++ Boost.Locale和isprint

C++ Boost.Locale和isprint,c++,c++11,boost,utf-8,C++,C++11,Boost,Utf 8,我正在寻找一种方法来显示UTF-8字符串,并转义其不可打印/无效字符。在ASCII的时代,我习惯于使用isprint来决定字符是按原样打印还是转义打印。对于UTF-8,迭代更加困难,但是Boost.Locale做得很好。然而,我并没有在其中找到任何东西来决定某个字符是否可以打印,甚至实际上是否有效 在下面的源代码中,字符串“Hello”あにま ➦ Unicode对每个代码点都有属性,其中包括a和技术报告列表(alpha、graph等)。Unicodeprint分类包括选项卡,其中std::is

我正在寻找一种方法来显示UTF-8字符串,并转义其不可打印/无效字符。在ASCII的时代,我习惯于使用
isprint
来决定字符是按原样打印还是转义打印。对于UTF-8,迭代更加困难,但是Boost.Locale做得很好。然而,我并没有在其中找到任何东西来决定某个字符是否可以打印,甚至实际上是否有效


在下面的源代码中,字符串“Hello”あにま ➦ Unicode对每个代码点都有属性,其中包括a和技术报告列表(alpha、graph等)。Unicode
print
分类包括选项卡,其中
std::isprint
(使用C语言环境)不包括。
打印
包括字母、标记、数字、标点符号、符号、空格和格式代码点。格式代码点,但包括相邻字符。我相信这正是您想要的(选项卡除外);规范经过精心设计,以支持这些字符属性

大多数分类函数,如
std::isprint
,一次只能给出一个标量值,因此UTF32是明显的编码选择。不幸的是,无法保证您的系统支持UTF32语言环境,也不能保证
wchar\u t
是保存所有unicode代码点所需的20位因此,如果可以的话,我会考虑使用分类。它具有所有Unicode类的内部表,并实现在ReGeX技术报告中列出的分类。它看起来像使用了旧的Unicode 5.2数据库,但是提供了用于生成表的C++,并且可以应用于更新的文件。

多字节UTF8序列仍需要转换为单独的代码点(UTF32),并且您特别提到跳过无效UTF8序列的能力。由于我是C++程序员,所以我决定不必要地对您的屏幕进行垃圾邮件,并实现一个CONTXPROUT8->UTF32函数:

#包括
#包括
#包括
#包括
#包括
#包括
名称空间{
结构多字节信息{
std::uint8_t id_掩码;
std::uint8\u t id\u匹配器;
std::uint8数据屏蔽;
};
constexpr const std::uint8\t多字节\u id\u掩码=0xC0;
constexpr const std::uint8多字节id匹配器=0x80;
constexpr const std::uint8多字节数据掩码=0x3F;
constexpr const std::uint8多字节位=6;
constexpr const多字节信息多字节信息[]={
//跳过1字节信息
{0xE0,0xC0,0x1F},
{0xF0,0xE0,0x0F},
{0xF8,0xF0,0x07};
constexpr const无符号最大长度=
(sizeof(多字节信息)/sizeof(多字节信息));
constexpr const std::uint32_t超长[]={0x80、0x800、0x10000};
constexpr const std::uint32\u t max\u code\u point=0x10FFFF;
}
枚举类提取:std::uint8{success,failure};
结构提取尝试{
标准:uint32代码点;
std::uint8字节处理;
提取状态;
};
模板
constexpr提取尝试下一个代码点(迭代器位置,
常量迭代器(结束){
静态断言(
std::是相同的{},
“错误的迭代器类型”);
提取\尝试结果{0,0,提取::失败};
如果(结束位置){
result.code_point=std::uint8_t(*位置);
++位置;
++result.bytes_处理;
如果(0x7F<结果代码\u点){
无符号预期_长度=1;
用于(常量自动信息:多字节信息){
if((result.code\u point&info.id\u mask)==info.id\u matcher){
result.code\u point&=info.data\u mask;
打破
}
++预期长度;
}
if(最大长度<预期长度| | |(末端位置)<预期长度){
返回结果;
}
for(无符号字节=0;字节<预期长度;++字节){
常量std::uint8\u t下一个字节=*(位置+字节);
if((下一个字节和多字节id掩码)!=多字节id匹配器){
返回结果;
}

对于我的用例(将\x123样式转义放入字符串中),我也在想同样的事情,我的简单解决方法是将字符串>127的所有字节和ASCII控制字符视为需要转义。iPrint可以使用32位的宽字符,但不能保证a“字符”是单个代码点。您是否正在寻找仅使用Boost的解决方案?是否可以使用其他类似ICU的库?通常情况下,我会这样做确定unicode码点是否可打印并不是一个简单的规则。“可打印”的含义取决于上下文。例如,是否允许多个码点使用一个标志符号。可能,一种标准的方法是使用。起初,grance似乎提供了一种过滤零宽度标志符号的方法,但我不确定。