Как работает поддержка UTF-8 для TinyXML?

Я использую TinyXML для анализа/создания файлов XML. Теперь, согласно документации, эта библиотека поддерживает многобайтовые наборы символов через UTF-8. Пока все хорошо, я думаю. Но единственный API, который предоставляет библиотека (для получения/установки имен элементов, имен и значений атрибутов,... всего, где используется строка), — это std::string или const char*. Это заставляет меня сомневаться в собственном понимании поддержки многобайтовых наборов символов. Как строка, которая поддерживает только 8-битные символы, может содержать 16-битный символ (если только она не использует кодовую страницу, которая опровергает утверждение «поддерживает Unicode»)? Я понимаю, что теоретически вы могли бы взять 16-битную кодовую точку и разделить ее на 2 символа в std::string, но это не преобразовало бы std::string в строку «Unicode», это сделало бы ее недействительной для большинства целей и, возможно, случайно работать при записи в файл и чтении другой программой.

Итак, может ли кто-нибудь объяснить мне, как библиотека может предлагать «8-битный интерфейс» (std::string или const char*) и при этом поддерживать строки «Unicode»?

(Я, вероятно, перепутал здесь некоторую терминологию Unicode; извините за возникшую из-за этого путаницу).


person Roel    schedule 28.09.2008    source источник


Ответы (3)


Во-первых, utf-8 хранится в строках const char *, как сказал @quinmars. И это не только надмножество 7-битного ASCII (кодовые точки ‹= 127 всегда кодируются одним байтом, как они сами), но и то, что байты с этими значениями никогда не используются как часть кодирования многобайтовых значений для кодовых точек. >= 128. Итак, если вы видите байт == 44, это символ '‹' и т. д. Все метасимволы в XML представлены в 7-битном коде ASCII. Таким образом, можно просто проанализировать XML, разбивая строки там, где говорят метасимволы, вставляя фрагменты (возможно, включая не-ASCII-символы) в char * или std::string, а возвращаемые фрагменты остаются действительными строками UTF-8, даже если парсер специально не знал UTF-8.

Кроме того (не специфично для XML, но довольно умно), даже более сложные вещи обычно просто работают (тм). Например, если вы сортируете UTF-8 лексикографически по байтам, вы получаете тот же ответ, что и лексикографически сортируя его по кодовым точкам, несмотря на различия в количестве используемых байтов, потому что байты префикса представляют более длинный (и, следовательно, более значимый) код. баллы численно больше, чем для меньших значений).

person puetzk    schedule 28.09.2008
comment
Хорошо, спасибо, становится яснее, но все же - использование std::string для представления данных UTF-8 таким образом, разве это не семантически неправильно? Вы никогда не сможете полагаться на содержимое этой строки — даже не будет способа узнать ее длину! (по длине символа). - person Roel; 29.09.2008
comment
И даже для версии const char* вам все равно придется использовать другую библиотеку для надежной работы со строкой. - person Roel; 29.09.2008
comment
Скорее неопределенное, чем неправильное. Методы std::string (конкатенация, нарезка итератора, find_* и т. д.) по-прежнему работают. length() в любом случае определяется только как == size(). Появилось новое предварительное условие, согласно которому смещения должны находиться на границе символа. Если бы std::string давал какие-либо обещания относительно кодирования, это было бы неправильно, но это не так. - person puetzk; 29.09.2008

UTF-8 совместим с 7-битным кодом ASCII. Если значение байта больше 127, это означает, что начинается многобайтовый символ. В зависимости от значения первого байта можно увидеть, сколько байтов займет символ, это может быть 2-4 байта, включая первый байт (технические также возможны 5 или 6, но они не являются допустимыми utf-8). Вот хороший ресурс по UTF-8: Часто задаваемые вопросы по UTF-8 и Unicode, также вики-страница для utf8 очень информативна. Поскольку UTF-8 основана на символах и заканчивается 0, вы можете использовать стандартные строковые функции для большинства вещей. Важно только то, что количество символов может отличаться от количества байтов. Такие функции, как strlen(), возвращают количество байтов, но не обязательно количество символов.

person quinmars    schedule 28.09.2008

Используя от 1 до 4 символов для кодирования одной кодовой точки Unicode.

person Nemanja Trifunovic    schedule 28.09.2008