utf8.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:7k
源码类别:

Windows CE

开发平台:

C/C++

  1. /*
  2.  * Copyright (C) 2001 Peter Harris <peter.harris@hummingbird.com>
  3.  * Copyright (C) 2001 Edmund Grimley Evans <edmundo@rano.org>
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or
  8.  * (at your option) any later version.
  9.  * 
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  * 
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  */
  19. /*
  20.  * Convert a string between UTF-8 and the locale's charset.
  21.  */
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #ifdef HAVE_CONFIG_H
  25. #include <config.h>
  26. #endif
  27. #include "utf8.h"
  28. #include "charset.h"
  29. #ifdef _WIN32
  30. /* Thanks to Peter Harris <peter.harris@hummingbird.com> for this win32
  31.  * code.
  32.  */
  33. #include <stdio.h>
  34. #include <windows.h>
  35. static unsigned char *make_utf8_string(const wchar_t *unicode)
  36. {
  37.     int size = 0, index = 0, out_index = 0;
  38.     unsigned char *out;
  39.     unsigned short c;
  40.     /* first calculate the size of the target string */
  41.     c = unicode[index++];
  42.     while(c) {
  43.         if(c < 0x0080) {
  44.             size += 1;
  45.         } else if(c < 0x0800) {
  46.             size += 2;
  47.         } else {
  48.             size += 3;
  49.         }
  50.         c = unicode[index++];
  51.     }
  52.     out = malloc(size + 1);
  53.     if (out == NULL)
  54.         return NULL;
  55.     index = 0;
  56.     c = unicode[index++];
  57.     while(c)
  58.     {
  59.         if(c < 0x080) {
  60.             out[out_index++] = (unsigned char)c;
  61.         } else if(c < 0x800) {
  62.             out[out_index++] = 0xc0 | (c >> 6);
  63.             out[out_index++] = 0x80 | (c & 0x3f);
  64.         } else {
  65.             out[out_index++] = 0xe0 | (c >> 12);
  66.             out[out_index++] = 0x80 | ((c >> 6) & 0x3f);
  67.             out[out_index++] = 0x80 | (c & 0x3f);
  68.         }
  69.         c = unicode[index++];
  70.     }
  71.     out[out_index] = 0x00;
  72.     return out;
  73. }
  74. static wchar_t *make_unicode_string(const unsigned char *utf8)
  75. {
  76.     int size = 0, index = 0, out_index = 0;
  77.     wchar_t *out;
  78.     unsigned char c;
  79.     /* first calculate the size of the target string */
  80.     c = utf8[index++];
  81.     while(c) {
  82.         if((c & 0x80) == 0) {
  83.             index += 0;
  84.         } else if((c & 0xe0) == 0xe0) {
  85.             index += 2;
  86.         } else {
  87.             index += 1;
  88.         }
  89.         size += 1;
  90.         c = utf8[index++];
  91.     }
  92.     out = malloc((size + 1) * sizeof(wchar_t));
  93.     if (out == NULL)
  94.         return NULL;
  95.     index = 0;
  96.     c = utf8[index++];
  97.     while(c)
  98.     {
  99.         if((c & 0x80) == 0) {
  100.             out[out_index++] = c;
  101.         } else if((c & 0xe0) == 0xe0) {
  102.             out[out_index] = (c & 0x1F) << 12;
  103.         c = utf8[index++];
  104.             out[out_index] |= (c & 0x3F) << 6;
  105.         c = utf8[index++];
  106.             out[out_index++] |= (c & 0x3F);
  107.         } else {
  108.             out[out_index] = (c & 0x3F) << 6;
  109.         c = utf8[index++];
  110.             out[out_index++] |= (c & 0x3F);
  111.         }
  112.         c = utf8[index++];
  113.     }
  114.     out[out_index] = 0;
  115.     return out;
  116. }
  117. int utf8_encode(const char *from, char **to)
  118. {
  119. wchar_t *unicode;
  120. int wchars, err;
  121. wchars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from,
  122. strlen(from), NULL, 0);
  123. if(wchars == 0)
  124. {
  125. fprintf(stderr, "Unicode translation error %dn", GetLastError());
  126. return -1;
  127. }
  128. unicode = calloc(wchars + 1, sizeof(unsigned short));
  129. if(unicode == NULL) 
  130. {
  131. fprintf(stderr, "Out of memory processing string to UTF8n");
  132. return -1;
  133. }
  134. err = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from, 
  135. strlen(from), unicode, wchars);
  136. if(err != wchars)
  137. {
  138. free(unicode);
  139. fprintf(stderr, "Unicode translation error %dn", GetLastError());
  140. return -1;
  141. }
  142. /* On NT-based windows systems, we could use WideCharToMultiByte(), but 
  143.  * MS doesn't actually have a consistent API across win32.
  144.  */
  145. *to = make_utf8_string(unicode);
  146. free(unicode);
  147. return 0;
  148. }
  149. int utf8_decode(const char *from, char **to)
  150. {
  151.     wchar_t *unicode;
  152.     int chars, err;
  153.     /* On NT-based windows systems, we could use MultiByteToWideChar(CP_UTF8), but 
  154.      * MS doesn't actually have a consistent API across win32.
  155.      */
  156.     unicode = make_unicode_string(from);
  157.     if(unicode == NULL) 
  158.     {
  159.         fprintf(stderr, "Out of memory processing string from UTF8 to UNICODE16n");
  160.         return -1;
  161.     }
  162.     chars = WideCharToMultiByte(GetConsoleCP(), WC_COMPOSITECHECK, unicode,
  163.             -1, NULL, 0, NULL, NULL);
  164.     if(chars == 0)
  165.     {
  166.         fprintf(stderr, "Unicode translation error %dn", GetLastError());
  167.         free(unicode);
  168.         return -1;
  169.     }
  170.     *to = calloc(chars + 1, sizeof(unsigned char));
  171.     if(*to == NULL) 
  172.     {
  173.         fprintf(stderr, "Out of memory processing string to local charsetn");
  174.         free(unicode);
  175.         return -1;
  176.     }
  177.     err = WideCharToMultiByte(GetConsoleCP(), WC_COMPOSITECHECK, unicode, 
  178.             -1, *to, chars, NULL, NULL);
  179.     if(err != chars)
  180.     {
  181.         fprintf(stderr, "Unicode translation error %dn", GetLastError());
  182.         free(unicode);
  183.         free(*to);
  184.         *to = NULL;
  185.         return -1;
  186.     }
  187.     free(unicode);
  188.     return 0;
  189. }
  190. #else /* End win32. Rest is for real operating systems */
  191. #ifdef HAVE_LANGINFO_CODESET
  192. #include <langinfo.h>
  193. #endif
  194. int iconvert(const char *fromcode, const char *tocode,
  195.      const char *from, size_t fromlen,
  196.      char **to, size_t *tolen);
  197. static char *current_charset = 0; /* means "US-ASCII" */
  198. void convert_set_charset(const char *charset)
  199. {
  200. #ifdef HAVE_LANGINFO_CODESET
  201.   if (!charset)
  202.     charset = nl_langinfo(CODESET);
  203. #endif
  204.   if (!charset)
  205.     charset = getenv("CHARSET");
  206.   free(current_charset);
  207.   current_charset = 0;
  208.   if (charset && *charset)
  209.     current_charset = strdup(charset);
  210. }
  211. static int convert_buffer(const char *fromcode, const char *tocode,
  212.   const char *from, size_t fromlen,
  213.   char **to, size_t *tolen)
  214. {
  215.   int ret = -1;
  216. #ifdef HAVE_ICONV
  217.   ret = iconvert(fromcode, tocode, from, fromlen, to, tolen);
  218.   if (ret != -1)
  219.     return ret;
  220. #endif
  221. #ifndef HAVE_ICONV /* should be ifdef USE_CHARSET_CONVERT */
  222.   ret = charset_convert(fromcode, tocode, from, fromlen, to, tolen);
  223.   if (ret != -1)
  224.     return ret;
  225. #endif
  226.   return ret;
  227. }
  228. static int convert_string(const char *fromcode, const char *tocode,
  229.   const char *from, char **to, char replace)
  230. {
  231.   int ret;
  232.   size_t fromlen;
  233.   char *s;
  234.   fromlen = strlen(from);
  235.   ret = convert_buffer(fromcode, tocode, from, fromlen, to, 0);
  236.   if (ret == -2)
  237.     return -1;
  238.   if (ret != -1)
  239.     return ret;
  240.   s = malloc(fromlen + 1);
  241.   if (!s)
  242.     return -1;
  243.   strcpy(s, from);
  244.   *to = s;
  245.   for (; *s; s++)
  246.     if (*s & ~0x7f)
  247.       *s = replace;
  248.   return 3;
  249. }
  250. int utf8_encode(const char *from, char **to)
  251. {
  252.   char *charset;
  253.   if (!current_charset)
  254.     convert_set_charset(0);
  255.   charset = current_charset ? current_charset : "US-ASCII";
  256.   return convert_string(charset, "UTF-8", from, to, '#');
  257. }
  258. int utf8_decode(const char *from, char **to)
  259. {
  260.   char *charset;
  261.   if (!current_charset)
  262.     convert_set_charset(0);
  263.   charset = current_charset ? current_charset : "US-ASCII";
  264.   return convert_string("UTF-8", charset, from, to, '?');
  265. }
  266. #endif