Глосарій Unicode
Unicode - велика і складна тема. Я не хочу заглиблюватися там занадто глибоко, проте необхідний швидкий глосарій:
- Точки коду : Точки коду - це основні будівельні блоки Unicode, кодова точка - це просто ціле число, що відображається у значенні . Ціла частина вміщується в 32 біти (ну, насправді 24 біти), і значення може бути буква, діакритика, пробіл, знак, смайлик, напівпрапор…, і це може бути навіть " наступна частина читається справа наліво ".
- Кластери графем : Кластери графем - це групи семантично пов’язаних точок коду, наприклад, прапор у unicode представлений об’єднанням двох точок коду; кожен з цих двох, ізольовано, не має значення, але об'єднаний у скупчення графем, вони представляють прапор. Кластери графем також використовуються для поєднання листа з діакритикою в деяких сценаріях.
Це основне для Unicode. Різницю між кодовою точкою та кластером графем можна здебільшого зменшити, оскільки для більшості сучасних мов кожен "символ" відображається в єдину кодову точку (існують виділені форми з наголосом для загальновживаних комбінацій буква + діакритичні). І все ж, якщо ви беретесь за смайли, прапори тощо ..., то, можливо, вам доведеться звернути увагу на відмінності.
UTF Primer
Потім, серія Unicode Code Points повинна бути закодована; загальними кодуваннями є UTF-8, UTF-16 та UTF-32, останні два існують як у формах Little-Endian, так і Big-Endian, загалом 5 загальних кодувань.
В UTF-X X - це розмір у бітах одиниці коду , кожна точка коду представлена як одна або декілька одиниць коду, залежно від її величини:
- UTF-8: 1 до 4 кодових одиниць,
- UTF-16: 1 або 2 кодові одиниці,
- UTF-32: 1 одиниця коду.
std::string
і std::wstring
.
- Не використовуйте,
std::wstring
якщо ви дбаєте про портативність ( wchar_t
у Windows лише 16 біт); використовувати std::u32string
замість цього (ака std::basic_string<char32_t>
).
- Представлення в пам'яті (
std::string
або std::wstring
) не залежить від представлення на диску (UTF-8, UTF-16 або UTF-32), тому підготуйтеся до необхідності перетворення на межі (читання та запис).
- Хоча 32-біт
wchar_t
гарантує, що одиниця коду представляє повну точку коду, вона все ще не являє собою повний кластер графем.
Якщо ви лише читаєте або складаєте рядки, у вас не повинно бути проблем із std::string
або std::wstring
.
Проблеми починаються, коли ви починаєте нарізати та нарізати, тоді вам слід звернути увагу на (1) межі точки коду (в UTF-8 або UTF-16) та (2) межі кластерів графем. З першими можна впоратись досить легко самостійно, для останнього потрібно використовувати бібліотеку, обізнану з Unicode.
Збір std::string
або std::u32string
?
Якщо продуктивність викликає занепокоєння, швидше за все, вона std::string
буде працювати краще завдяки меншому розміру пам'яті; хоча інтенсивне використання китайської мови може змінити угоду. Як завжди, профіль.
Якщо кластери графем не є проблемою, то std::u32string
перевага полягає у спрощенні речей: 1 одиниця коду -> 1 кодова точка означає, що ви не можете випадково розділити кодові точки, а всі функції std::basic_string
працюють нестандартно.
Якщо ви взаємодієте із програмним забезпеченням std::string
або char*
/ char const*
, дотримуйтесь, std::string
щоб уникнути перетворення назад і вперед. В іншому випадку це буде біль.
UTF-8 в std::string
.
UTF-8 насправді працює досить добре в std::string
.
Більшість операцій працюють нестандартно, оскільки кодування UTF-8 є самосинхронізуючимся і зворотно сумісним з ASCII.
Через спосіб кодування точок коду, пошук кодової точки не може випадково збігтися з серединою іншої кодової точки:
str.find('\n')
працює,
str.find("...")
працює для відповідності байта за байтом 1 ,
str.find_first_of("\r\n")
працює під час пошуку символів ASCII .
Подібним чином, regex
переважно це працює нестандартно. Оскільки послідовність символів ( "haha"
) - це лише послідовність байтів ( "哈"
), основні шаблони пошуку повинні працювати нестандартно.
Однак будьте обережні щодо класів символів (таких як [:alphanum:]
), оскільки залежно від аромату регулярного виразу та реалізації він може або не відповідати символам Unicode.
Так само, обережно застосовуйте повторювачі до символів, що не належать до ASCII, "哈?"
може вважати останній байт необов’язковим; використовувати круглі дужки , щоб чітко розмежувати повторювану сукупність електронних даних в таких випадках: "(哈)?"
.
1 Ключові поняття для пошуку - це нормалізація та порівняння; це впливає на всі операції порівняння. std::string
завжди буде порівнювати (і, отже, сортувати) байт за байтом, не враховуючи правила порівняння, характерні для мови чи використання. Якщо вам потрібно обробити повну нормалізацію / сортування, вам потрібна повна бібліотека Unicode, така як ICU.