2010-02-17 7 views
2

Je suis familier avec les conversions WideCharToMultiByte et MultiByteToWideChar et pourrait les utiliser pour faire quelque chose comme:API Windows C pour UTF8 1252

UTF8 -> UTF16 -> 1252

Je sais que iconv va faire ce que J'ai besoin, mais quelqu'un connaît-il des bibliothèques MS qui permettent cela en un seul appel?

Je devrais probablement juste tirer dans la bibliothèque iconv, mais je me sens paresseux.

Merci

Répondre

0

de Windows 1252 est le plus souvent équivalent à latin-1, alias ISO-8859-1: Windows 1252 a juste quelques caractères supplémentaires attribués dans la plage réservée latin-1 128-159. Si vous êtes prêt à ignorer ces caractères supplémentaires et à rester dans latin-1, la conversion est plutôt facile. Essayez ceci:

#include <stddef.h> 

/* 
* Convert from UTF-8 to latin-1. Invalid encodings, and encodings of 
* code points beyond 255, are replaced by question marks. No more than 
* dst_max_len bytes are stored in the destination array. Returned value 
* is the length that the latin-1 string would have had, assuming a big 
* enough destination buffer. 
*/ 
size_t 
utf8_to_latin1(char *src, size_t src_len, 
    char *dst, size_t dst_max_len) 
{ 
    unsigned char *sb; 
    size_t u, v; 

    u = v = 0; 
    sb = (unsigned char *)src; 
    while (u < src_len) { 
     int c = sb[u ++]; 
     if (c >= 0x80) { 
      if (c >= 0xC0 && c < 0xE0) { 
       if (u == src_len) { 
        c = '?'; 
       } else { 
        int w = sb[u]; 
        if (w >= 0x80 && w < 0xC0) { 
         u ++; 
         c = ((c & 0x1F) << 6) 
          + (w & 0x3F); 
        } else { 
         c = '?'; 
        } 
       } 
      } else { 
       int i; 

       for (i = 6; i >= 0; i --) 
        if (!(c & (1 << i))) 
         break; 
       c = '?'; 
       u += i; 
      } 
     } 
     if (v < dst_max_len) 
      dst[v] = (char)c; 
     v ++; 
    } 
    return v; 
} 

/* 
* Convert from latin-1 to UTF-8. No more than dst_max_len bytes are 
* stored in the destination array. Returned value is the length that 
* the UTF-8 string would have had, assuming a big enough destination 
* buffer. 
*/ 
size_t 
latin1_to_utf8(char *src, size_t src_len, 
    char *dst, size_t dst_max_len) 
{ 
    unsigned char *sb; 
    size_t u, v; 

    u = v = 0; 
    sb = (unsigned char *)src; 
    while (u < src_len) { 
     int c = sb[u ++]; 
     if (c < 0x80) { 
      if (v < dst_max_len) 
       dst[v] = (char)c; 
      v ++; 
     } else { 
      int h = 0xC0 + (c >> 6); 
      int l = 0x80 + (c & 0x3F); 
      if (v < dst_max_len) { 
       dst[v] = (char)h; 
       if ((v + 1) < dst_max_len) 
        dst[v + 1] = (char)l; 
      } 
      v += 2; 
     } 
    } 
    return v; 
} 

Notez que je fais aucune garantie sur ce code. Ceci est complètement non testé.

+1

Et comment cela vaut-il mieux que d'utiliser une API testée en appelant MultiByteToWideChar suivi de WideCharToMultiByte? – Sofahamster

+1

"Mieux"? Quelle notion controversée. La question était de le faire dans un appel de fonction au lieu de deux, surtout si les deux sont 'MultiByteToWideChar()' et 'WideCharToMultiByte()'. Mon code fait ça. Je ne prétends pas que c'est _wise_ pour éviter 'MultiByteToWideChar()'. Nitpickingly, on pourrait signaler que mes fonctions évitent l'allocation d'un tampon temporaire. –