2014-05-13 53 views
1

我只是對自己的代碼持懷疑態度(自然而然地進行測試),並希望有人驗證這是否真的是endian不可知論的方法。這種將Unicode字符轉換爲真正的endian不可知的方法嗎?

在跨平臺項目的內部,我使用UTF-32(std :: u32string)作爲字符串類型。但是爲了在不同平臺上處理I/O更簡單,我在將任何文本發送到文件或通過電線之前將UTF-32轉換爲UTF-8。

我會說這種方法是endian不可知論的。 UTF-8是一種字節定向編碼,意味着計算機的字節序不會影響字節流。在發送到流之前,大型32位字符將按照它們在字符串中出現的順序轉換爲UTF-8。

這裏的代碼片段從一個JSON字符串類提供的我在做什麼

/** 
* 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; 
} 
+0

我看不到任何endian-ness問題。但是,特殊字符檢查似乎是多餘的。以避免對這些角色的解釋,因爲控制角色的一般處理就足夠了。此外(但主要是學術問題)僅在C++執行字符集基於ASCII時才起作用。 –

+0

我將來會用適當的u32string常量替換這些字符串常量。 顯式轉義實際上更多用於調試目的。 Json規範允許這些字符被明確地轉義。在文本編輯器或wireshark中添加一些額外的代碼並查看常用控制代碼比繼續查找十六進制值更容易。 – BlamKiwi

回答

1

一般這種方法可以實現字節順序無關的例子,因爲UTF-32的系統中只使用具有相同的字節順序,而在任何情況下,它與可能具有不同字節順序的系統接口都是UTF-8,而UTF-8是建立在字節流上的(因此沒有字節順序)。

但是,轉換本身是endian敏感的,必須正確實施,以便字節序不會成爲問題(例如,沒有memcopy,但算術轉換)。假設你的標準庫實現正確地進行了這種轉換應該是合理的。

要添加一些澄清爲什麼這個代碼應以字節序(22.5/4)的影響:

對於小面codecvt_utf8
- 小面應當UTF-8多字節序列和UCS2之間進行轉換或程序中的UCS4(取決於大小Elem)。
- 字節順序不會影響多字節序列的讀寫方式。
- 多字節序列可以寫成文本或二進制文件。

codecvt_mode枚舉類型的endianess構件僅用於讀/寫UTF-16和UTF-32的多字節序列。

+0

[它們本身不是**他的例程](http://en.cppreference.com/w/cpp/locale/wstring_convert/to_bytes)。 – CoffeeandCode

+0

Unicode轉換器是STL轉換工具的typedef。 'typedef std :: wstring_convert ,char32_t> UnicodeConverter;' 我似乎無法找到有關STL是否需要轉換爲endian不可知的任何特定信息。 – BlamKiwi

+0

我忽略了那個typedef -.- –