2008-09-28 11 views
12

Estoy usando TinyXML para analizar/compilar archivos XML. Ahora, de acuerdo con the documentation, esta biblioteca admite conjuntos de caracteres multibyte a través de UTF-8. Hasta ahora todo bien, creo. Pero, la única API que proporciona la biblioteca (para obtener/configurar nombres de elementos, nombres y valores de atributos, ... todo en donde se usa una cadena) es a través de std::string o const char*. Esto me hace dudar de mi propia comprensión del soporte de conjunto de caracteres multibyte. ¿Cómo puede una cadena que solo admite caracteres de 8 bits contener un carácter de 16 bits (a menos que use una página de códigos, lo que negaría la afirmación 'admite Unicode')? Entiendo que en teoría podría tomar un punto de código de 16 bits y dividirlo en 2 caracteres en un std::string, pero eso no transformaría el std::string en una cadena 'Unicode', lo haría inválido para la mayoría de los propósitos y tal vez accidentalmente trabajo cuando se escribe en un archivo y se lee en otro programa.¿Cómo funciona el soporte UTF-8 de TinyXML?

Entonces, ¿alguien puede explicarme cómo una biblioteca puede ofrecer una 'interfaz de 8 bits' (std::string o const char*) y aún admite cadenas 'Unicode'?

(Probablemente confundí un poco la terminología de Unicode aquí, disculpe la confusión que pueda surgir).

Respuesta

8

Primero, utf-8 se almacena en cadenas const char *, como dijo @quinmars. Y no es solo un superconjunto de ASCII de 7 bits (puntos de código < = 127 codificados siempre en un solo byte como ellos mismos), además es cuidadoso de que los bytes con esos valores nunca se usen como parte de la codificación de los valores de multibyte para los puntos de código > = 128. Entonces, si ve un byte == 44, es un carácter '<', etc. Todos los metacaracteres en XML están en ASCII de 7 bits. Así que uno puede simplemente analizar el XML, rompiendo cadenas donde los metacars dicen, pegando los fragmentos (posiblemente incluyendo caracteres no ASCII) en un char * o std :: string, y los fragmentos devueltos siguen siendo cadenas UTF-8 válidas aunque el analizador no conocía específicamente UTF-8.

Además (no específico para XML, pero bastante inteligente), incluso cosas más complejas genralmente simplemente funcionan (tm). Por ejemplo, si clasifica UTF-8 lexicográficamente por bytes, obtiene la misma respuesta que clasificarlo lexicográficamente por puntos de código, a pesar de la variación en # de bytes utilizados, porque el prefijo bytes introduce el código más largo (y por lo tanto más valioso) los puntos son numéricamente mayores que aquellos para valores menores).

+0

Ok gracias, está cada vez más claro, pero aún así - usando std :: string para representar los datos UTF-8 de esta manera, ¿no es eso semánticamente incorrecto? Nunca podrá confiar en los contenidos de esa cadena, ¡ni siquiera habrá forma de saber cuánto tiempo durará! (en longitud del personaje). – Roel

+0

E incluso para la versión de const char *, aún tendría que usar otra biblioteca para trabajar con la cadena de manera confiable. – Roel

+2

Más indefinido que incorrecto. Los métodos de std :: string (concatenación, iteración, iteración, find_ *, etc.) aún funcionan. length() solo se define como == size() de todos modos. Hay una nueva condición previa de que los desplazamientos se encuentren en un límite de char. Si std :: string hizo alguna promesa sobre la codificación, sería incorrecto, pero no es así. – puetzk

2

UTF-8 es compatible con el código ASCII de 7 bits. Si el valor de un byte es mayor que 127, significa que se inicia un carácter multibyte. Dependiendo del valor del primer byte, puede ver cuántos bytes tomará el personaje, que pueden ser de 2 a 4 bytes, incluido el primer byte (también son posibles 5 o 6, pero no son válidos para utf-8). Aquí hay un buen recurso sobre UTF-8: UTF-8 and Unicode FAQ, también la página wiki para utf8 es muy informativa. Como UTF-8 está basado en caracteres y terminado en 0, puede usar las funciones de cadenas estándar para la mayoría de las cosas. Lo único importante es que el recuento de caracteres puede diferir del recuento de bytes. Funciones como strlen() devuelven el recuento de bytes pero no necesariamente el recuento de caracteres.

0

Al usar entre 1 y 4 caracteres para codificar un punto de código Unicode.