这种转换Unicode字符的方法是否真正与字节序无关?

时间:2014-05-13 01:06:12

标签: c++ c++11 endianness

我对自己的代码(以及自然的测试)有点怀疑,并希望有人来验证这是否真的与endian无关。

在跨平台项目的内部,我使用UTF-32(std :: u32string)作为字符串类型。但是为了在不同平台上处理I / O更容易,我在将任何文本发送到文件或通过线路之前将UTF-32转换为UTF-8。

我想说这种方法与endian无关。 UTF-8是一种面向字节的编码,这意味着计算机的字节顺序不会影响字节流。大型32位字符按照它们在发送到流中之前在字符串中出现的顺序转换为UTF-8。

这里有来自Json String类的代码片段,以提供我正在做的事情的一个例子

/**
*   Provides conversion facilities between UTF-8 and Unicode32 strings.
*/
typedef std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> UnicodeConverter;

/**
* Converts the JSON value to a valid JSON string.
* @param the UTF-8 stream to write to.
* @returns The UTF-8 stream.
*/
inline std::ostream& VToJson(std::ostream& os) const override { return EscapeJsonString(os << STRING_JSON_QUOTE) << STRING_JSON_QUOTE; }

/**
*   Streams a json string in its escaped form.
*   @param os the UTF-8 stream to write to.
*   @returns the original stream.
*/
std::ostream& JsonString::EscapeJsonString(std::ostream &os) const 
{
    UnicodeConverter conv;
    for each (char32_t c in i_Value)
    {
        // Check if character is a special character
        if (c == '\\')
            // Output escaped rev solidus
            os << "\\\\";
        else if (c == '/')
            // Output escaped solidus
            os << "\\/";
        else if (c == '\b')
            // Output escaped backspace
            os << "\\b";
        else if (c == '\f')
            // Output escaped formfeed
            os << "\\f";
        else if (c == '\n')
            // Output escaped new line
            os << "\\n";
        else if (c == '\r')
            // Output secaped carriage return
            os << "\\r";
        else if (c == '\t')
            // Output escaped tab
            os << "\\t";
        else if (is_unicode_control(c))
        {
            // Output escape
            os << "\\u";

            // Output hex representation
            std::stringstream str;
            str << std::setfill('0') << std::setw(4) << std::hex << c;
            os << str.str();
        }
        else
            // Normal character
            os << conv.to_bytes(c);
    }
    return os;
}

1 个答案:

答案 0 :(得分:1)

一般来说,这种方法可以实现字节序不可知,因为UTF-32仅用于具有相同字节序的系统,而在每种情况下,它与可能具有不同字节序的系统接口使用UTF-8 - 和UTF-8建立在字节流上(因此没有字节顺序)。

但是,转换本身是字节序敏感的,必须正确实现,以便字节顺序不会成为问题(例如,不是memcopy,而是算术移位)。假设您的标准库实现正确地执行此转换应该是合理的。

添加一些说明,说明为什么此代码不受endianess的影响(22.5 / 4):

  

对于方面codecvt_utf8
   - 小平面应在UTF-8多字节序列和UCS2或UCS4之间转换(取决于   程序中Elem的大小。
   - 字节顺序不应影响如何读取或写入多字节序列    - 多字节序列可以写成文本或二进制文件。

endianess枚举类型的codecvt_mode成员仅用于读/写UTF-16和UTF-32多字节序列。