2011-05-17 19 views
10

Estoy buscando sugerencias con respecto a unicode aware std :: string library replacements. Tengo un montón de código que usa std :: string, sus iteradores, etc., y me gustaría ahora admitir cadenas de Unicode (se prefieren las implementaciones de código abierto o libre, las capacidades de regex serían geniales).Unicode std :: string class replacement

No estoy seguro en este momento si requiero una reescritura completa o si puedo salir con la colocación de una nueva biblioteca de cadenas que admita todas las interfaces std :: string. El mundo Unicode parece muy complejo y solo quiero habilitarlo en mis aplicaciones, no es necesario que aprenda cada aspecto de él.

btw ¿cómo funciona el operador de índice cuando tiene que volver una referencia a una estructura 1, 2,3 o 4 que en teoría podría cambiar a una estructura de 1,2,3 o 4 bytes. si se pasa un valor de mayor o menor tamaño, ¿el cambio de ida y vuelta de la representación interna de datos ocurre in situ?

+1

Siempre hay std :: wstring, que proporciona una cadena de caracteres anchos; sin embargo, no se garantiza que funcione con unicode (el tamaño depende de la plataforma), pero puede ser útil. Pero sería un simple reemplazo directo para std :: string, como se define como: 'typedef std :: basic_string wstring' – icabod

+6

@icabod El uso de' std :: wstring' en sí mismo no resuelve el problema del póster, todavía dará resultados incorrectos, por ejemplo 'length()'. De hecho, 'std :: string' es suficiente si todos los datos se almacenan como UTF8. También vea: http://stackoverflow.com/questions/402283/stdwstring-vs-stdstring. – Darhuuk

Respuesta

10

No necesita una reescritura completa si se asegura de lo que contiene su std :: string. Por ejemplo, podría suponer (y convertir las entradas para estar seguro) que std :: string contiene cadenas codificadas en UTF8 (para aquellas que necesitan localización). No olvide que std :: string es solo un contenedor de datos en bruto, no está asociado a una codificación (incluso en C++ 0x, es solo una posibilidad, no un requisito).

Luego, cuando pasa texto a otras bibliotecas que requieren diferentes codificaciones, puede usar bibliotecas como UTF8CPP para convertir a la codificación requerida (pero la mayoría de las veces las bibliotecas lo harán ellas mismas).

De esta manera lo hace simple. UTF8 con std :: string estándar en el código, lo que permite pasar la cadena Unicode a todo lo demás (con conversión si es necesario).

Ha habido muchas discusiones sobre esto en la lista de correo de la comunidad de impulso. Quizás leerlo (si tienes suficiente tiempo ...) puede ayudarte a comprender otras posibles soluciones.

+1

He encontrado que esta es una buena solución. Sin embargo, tenga en cuenta que cualquier biblioteca escrita por Microsoft asumirá que las cadenas basadas en caracteres están codificadas en "ANSI" en lugar de UTF-8, por lo que tendrá que escribir envoltorios alrededor de esas funciones. – dan04

+0

Sí, y deberá asegurarse de que esas conversiones se realicen solo cuando sea necesario, no en el resto del código. – Klaim

6

lo que la codificación Unicode Qué se necesita? Si UTF-8 está bien se puede echar un vistazo a Glib::ustring

Glib :: ustring tiene la misma interfaz de como std :: string, pero contiene caracteres Unicode codificados como UTF-8.

+4

Tenga en cuenta que Glib :: ustring es (debería ser) muy intolerante con secuencias de caracteres ilegales; además, si se pasan, p. en el constructor, Glib dejará que las cosas se cuelguen al invocar 'std :: string ((char *) 0)' en lugar de arrojar una excepción descriptiva. – sehe

+0

+1 para 'Glib :: ustring', básicamente un reemplazo directo. – Darhuuk

1

Preguntar por "un tipo como std :: string, pero para Unicode" es como pedir "un tipo como unsigned, pero para números primos". std :: string es perfectamente capaz de almacenar Unicode, en muchas codificaciones, siendo el UTF-8 el más útil en general.

Lo que hay que reemplazar sus es iteradores, no el tipo de almacenamiento . Los iteradores deben iterar sobre los puntos de código de la cadena en lugar de los bytes. Es decir, ++i debe avanzar un punto de código, y *i debe devolver un punto de código (mediante uint32_t) en lugar de char.

+1

"capaz de almacenar Unicode, en muchas codificaciones" No es cierto. Es capaz de almacenar Unicode * solo * en UTF-8. Si desea contar CESU-8 (mala idea) y UTF-7 (antiguo, obsoleto), tal vez el recuento llegue a 3. Pero todavía no es "muchos" –

+0

@Mihai: también GB 18030 y UTF-8 modificado . Puede argumentar que nada de eso importa (aunque cuando necesita UTF-8 modificado, generalmente lo necesita). Yo diría que no hay ninguna codificación además de UTF-16 y UTF-32 realmente importante, por lo que, según su recuento, no hay "muchas" codificaciones para ningún tipo de datos que admitan. std :: string también es totalmente capaz de almacenar, p. subconjuntos de Unicode codificados como 8859-1. El punto es que "soporte Unicode" no es lo mismo que "formato de almacenamiento", y std :: string proporciona un formato de almacenamiento muy útil. –

0

He escrito mi propio C++ UTF-8 library, que es un reemplazo directo de std::wstring/string. El tipo de datos que se muestra al usuario es char32_t, pero internamente los caracteres anchos están empaquetados en utf8 char.

Todo es bastante rápido y su rendimiento es mejor con pocos puntos de código Unicode dentro de muchos puntos de código ASCII. Todas las operaciones que se conocen de std :: string están disponibles con esta clase (excepto para la subcadena find) y operan en índices de punto de código, en contraste con los índices de bytes.

Como beneficio adicional de programación defensiva, toda la gama de 0-255 ANSI puede utilizarse sin multibytes :)

Espero que esto ayude!