iconv.c

Go to the documentation of this file.
00001 /*
00002  ** Copyright 2004,2005 - INL
00003  ** Written by Eric Leblond <regit@inl.fr>
00004  ** INL http://www.inl.fr/
00005  **
00006  ** $Id: iconv.c 5213 2008-11-19 13:54:31Z pollux $
00007  **
00008  ** This program is free software; you can redistribute it and/or modify
00009  ** it under the terms of the GNU General Public License as published by
00010  ** the Free Software Foundation, version 3 of the License.
00011  **
00012  ** This program is distributed in the hope that it will be useful,
00013  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  ** GNU General Public License for more details.
00016  **
00017  ** You should have received a copy of the GNU General Public License
00018  ** along with this program; if not, write to the Free Software
00019  ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00020  */
00021 
00022 #include "libnuclient.h"
00023 #include <stdlib.h>
00024 #include <errno.h>
00025 #include <string.h>
00026 #include <iconv.h>
00027 #include <langinfo.h>
00028 #include <stdio.h>
00029 #include <locale.h>
00030 
00044 char *nu_client_to_utf8(const char *inbuf, char *from_charset)
00045 {
00046         iconv_t ctx;
00047         size_t inlen = strlen(inbuf);
00048         size_t maxlen = inlen * 4;
00049         char *outbuf;
00050         char *targetbuf;
00051         size_t real_outlen;
00052         size_t orig_inlen = inlen;
00053         size_t outbuflen = 3;
00054         size_t outbufleft;
00055         int ret;
00056 
00057         /* just returns NULL if input is NULL */
00058         if (inbuf == NULL) {
00059                 return NULL;
00060         }
00061 
00062         /* create an iconv context to convert locale charset to UTF-8 */
00063         ctx = iconv_open("UTF-8", from_charset);
00064 
00065         /* allocate a buffer */
00066         outbuf = calloc(outbuflen, sizeof(char));
00067         nu_assert(outbuf != NULL, "iconv fail to allocate output buffer!");
00068 
00069         /* iconv convert */
00070         outbufleft = outbuflen - 1;     /* -1 because we keep last byte for nul byte */
00071         targetbuf = outbuf;
00072         ret = iconv(ctx, (char **) &inbuf, &inlen, &targetbuf, &outbufleft);
00073         real_outlen = targetbuf - outbuf;
00074 
00075         /* is buffer too small? */
00076         if (ret == -1) {
00077                 if (errno != E2BIG) {
00078                         free(outbuf);
00079                         iconv_close(ctx);
00080                         panic("iconv error code %i!", ret);
00081                 }
00082 
00083                 while ((ret == -1) && (errno == E2BIG)
00084                        && (outbuflen < maxlen)) {
00085                         /* realloc outbuf */
00086                         outbuflen += orig_inlen;
00087                         outbuf = realloc(outbuf, outbuflen);
00088                         if (outbuf == NULL) {
00089                                 free(outbuf);
00090                                 iconv_close(ctx);
00091                                 panic
00092                                     ("iconv error: can't rellocate buffer!");
00093                         }
00094 
00095                         /* run iconv once more */
00096                         outbufleft = outbuflen - real_outlen - 1;       /* -1 because we keep last byte for nul byte */
00097                         targetbuf = outbuf + real_outlen;
00098                         ret = iconv(ctx, (char **) &inbuf, &inlen,
00099                                   &targetbuf, &outbufleft);
00100                         real_outlen = targetbuf - outbuf;
00101                 }
00102         }
00103 
00104         /* close iconv context */
00105         iconv_close(ctx);
00106 
00107         /* realloc output to have a correct size */
00108         outbuflen = real_outlen + 1;
00109         outbuf = realloc(outbuf, outbuflen);
00110         outbuf[outbuflen - 1] = 0;
00111         return outbuf;
00112 }
00113 

Generated on Sat Nov 22 04:00:37 2008 for NuFW by  doxygen 1.4.7