Detectando UTF8 en C

Enviado por clbustos el Mar, 27/12/2005 - 01:07.

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

  1.  #include <string.h>
  2.  #include <iconv.h>
  3.  
  4.  #define UTF_8 1
  5.  #define ASCII 2
  6.  #define ISO_8859_1 3
  7.  
  8.  #define TRUE 1
  9.  #define FALSE 0
  10.  #define BUFFER 255
  11.  
  12.  typedef short int t_encoding;
  13.  typedef short int bool;
  14.  t_encoding codificacion(const char *texto);
  15.  
  16.  t_encoding
  17.  codificacion(const char *texto)
  18.  {
  19.   int c = 0,
  20.   i = 0;
  21.   unsigned char byte = 0;
  22.   bool ascii = TRUE;
  23.   for (i = 0; byte = texto[i]; i++) {
  24.   if (c > 0) {
  25.   if ((byte >> 6) != 0x2) {
  26.   return ISO_8859_1;
  27.   } else {
  28.   c--;
  29.   }
  30.   } else if (byte & 0x80) {
  31.   ascii = FALSE;
  32.   if ((byte >> 5) == 0x6) {
  33.   c = 1;
  34.   } else if ((byte >> 4) == 0xE) {
  35.   c = 2;
  36.   } else if ((byte >> 3) == 0x1E) {
  37.   c = 3;
  38.   } else {
  39.   return ISO_8859_1;
  40.   }
  41.   }
  42.   }
  43.   return (ascii) ? ASCII : UTF_8;
  44.  }
  45.  
  46.  
  47.  int
  48.  main(int argc, char **argv)
  49.  {
  50.   iconv_t cd;
  51.   size_t in = 0;
  52.   size_t out = 0;
  53.   cd = iconv_open("utf-8", "iso-8859-1");
  54.   char *a = "ASCII";
  55.   char *iso = "ISO: áéíóú";
  56.   char *b = "UTF-8: áéíóú";
  57.   char c[BUFFER]="";
  58.   char *cp = c;
  59.   in = strlen(b);
  60.   out = BUFFER;
  61.   iconv(cd, &b, &in, &cp, &out);
  62.   printf("ASCII: %s %d\n", a,codificacion(a));
  63.   printf("ISO-8859-1: %s %d\n", iso,codificacion(iso));
  64.   printf("UTF-8: %s %d\n", c,codificacion(c));
  65.   iconv_close(cd);
  66.  }

Ahora, lo único que falta es crear la extensión correspondiente en Ruby, para ahorrar tiempo en catori

AdjuntoTamaño
dec_utf8.tgz3.69 KB
Imagen de dvdjg

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

Enviado por dvdjg (no verificado) el Vie, 30/03/2007 - 03:38.
Imagen de Perejilillo desconocido

You're right. I'll fix it.

Enviado por Perejilillo desconocido el Mié, 18/07/2007 - 12:45.
Imagen de Perejilillo desconocido

Muchas gracias por este código!

Me ha servido de mucho!

Enviado por Perejilillo desconocido el Vie, 07/09/2007 - 03:21.
Imagen de David Ortega

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();
}
}

Enviado por David Ortega (no verificado) el Mié, 27/01/2010 - 09:21.

Enviar un comentario nuevo

El contenido de este campo se mantiene como privado y no se muestra públicamente.
If you have a Gravatar account, used to display your avatar.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Saltos automáticos de líneas y de párrafos.

Más información sobre opciones de formato