Detectando UTF8 en C
Como no tengo ganas de seguir haciendo informes de Zulliger, acabo de terminar mi detector de UTF-8 en C. Demoré 5 minutos en captar que la variable que almacena cada byte debía ser un unsigned char en vez de un char para realizar las comprobaciones correspondientes. El código es muy similar al de PHP; me di cuenta que la comprobación por bit es más rápida que la por valor (mayor a 128), así que corregiré la entrada correspondiente en el artículo de PHP.
Utilizo iconv para realizar la transformación de ISO-8859-1 en UTF-8. La forma de realizar el traspaso la tome de The GNU C Library: A complete iconv example, así que disculpen las brutalidades
- #include <string.h>
- #include <iconv.h>
- #define UTF_8 1
- #define ASCII 2
- #define ISO_8859_1 3
- #define TRUE 1
- #define FALSE 0
- #define BUFFER 255
- typedef short int t_encoding;
- typedef short int bool;
- t_encoding codificacion(const char *texto);
- t_encoding
- codificacion(const char *texto)
- {
- int c = 0,
- i = 0;
- unsigned char byte = 0;
- bool ascii = TRUE;
- for (i = 0; byte = texto[i]; i++) {
- if (c > 0) {
- if ((byte >> 6) != 0x2) {
- return ISO_8859_1;
- } else {
- c--;
- }
- } else if (byte & 0x80) {
- ascii = FALSE;
- if ((byte >> 5) == 0x6) {
- c = 1;
- } else if ((byte >> 4) == 0xE) {
- c = 2;
- } else if ((byte >> 3) == 0x1E) {
- c = 3;
- } else {
- return ISO_8859_1;
- }
- }
- }
- return (ascii) ? ASCII : UTF_8;
- }
- int
- main(int argc, char **argv)
- {
- iconv_t cd;
- size_t in = 0;
- size_t out = 0;
- cd = iconv_open("utf-8", "iso-8859-1");
- char *a = "ASCII";
- char *iso = "ISO: áéíóú";
- char *b = "UTF-8: áéíóú";
- char c[BUFFER]="";
- char *cp = c;
- in = strlen(b);
- out = BUFFER;
- iconv(cd, &b, &in, &cp, &out);
- printf("ASCII: %s %d\n", a,codificacion(a));
- printf("ISO-8859-1: %s %d\n", iso,codificacion(iso));
- printf("UTF-8: %s %d\n", c,codificacion(c));
- iconv_close(cd);
- }
Ahora, lo único que falta es crear la extensión correspondiente en Ruby, para ahorrar tiempo en catori
| Adjunto | Tamaño |
|---|---|
| dec_utf8.tgz | 3.69 KB |
- 5531 lecturas

I think that the line
} else if ((byte >> 3) == 0x14) {
Should be changed for:
} else if ((byte >> 3) == 0x1E) {
Because UTF-8 codifications are:
* 0xxxxxxx ASCII
* 110xxxxx 10xxxxxx 2-byte >= 0x80
* 1110xxxx 10xxxxxx 10xxxxxx 3-byte >= 0x400
* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 4-byte >= 0x10000
And 11110b == 0x1E
You're right. I'll fix it.
Muchas gracias por este código!
Me ha servido de mucho!
Hola,
vi tu código y me fué muy útil para adaptarlo a una clase Http para obtener el charset.
Dicha clase es la base de unos crawlers y era necesario normalizar cualquier codificación a UTF-8 para homegeneizar los resultados.
Gracias
David Ortega
Research Lab
www.andalucialab.org
void CUrlEasyHttp::getEncoding()
{
const char *ctext = this->httpResponseData.dataIn.c_str();
int c = 0;
unsigned char byte = 0;
this->httpResponseData.charset = "Unknown";
for(int i=0; byte=ctext[i]; i++)
{
if (c>0)
{
if ((byte >> 6)!= 0x2)
{
this->httpResponseData.charset = "ISO_8859_1";
}else
{
c--;
}
}else
{
if(byte & 0x80)
{
this->httpResponseData.charset = "UTF-8";
if ((byte >> 5) == 0x6)
{
c = 1;
}else if ((byte >> 4) == 0xE)
{
c = 2;
}else if ((byte >> 3) == 0x1E)
{
c = 3;
}else
{
this->httpResponseData.charset = "ISO_8859_1";
}
}
}
}
if(this->httpResponseData.charset == "ISO_8859_1")
{
this->responseToUtf8();
}
}
Enviar un comentario nuevo