AC_PROG_RANLIB obsoleted by libtool.
[libidn.git] / toutf8.c
blobf1587849b0ae5f4e133caf1b0b7c0ae53d8f228e
1 /* toutf8.c convert strings from system locale into UTF-8
2 * Copyright (C) 2002 Simon Josefsson
4 * This file is part of libstringprep.
6 * Libstringprep is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * Libstringprep is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with libstringprep; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
26 #ifdef HAVE_ICONV
28 #include <iconv.h>
30 #ifdef STDC_HEADERS
31 #include <stdlib.h>
32 #endif
33 #if HAVE_STRING_H
34 # if !STDC_HEADERS && HAVE_MEMORY_H
35 # include <memory.h>
36 # endif
37 # include <string.h>
38 #endif
39 #if HAVE_STRINGS_H
40 # include <strings.h>
41 #endif
43 #ifdef HAVE_ERRNO_H
44 #include <errno.h>
45 #endif
46 extern int errno;
48 #if LOCALE_WORKS
49 #include <langinfo.h>
50 #include <locale.h>
51 #endif
53 static const char *
54 stringprep_locale_charset_slow ()
56 const char *charset = getenv("CHARSET");
57 char *p;
59 if (charset && *charset)
60 return charset;
62 #if LOCALE_WORKS
63 p = setlocale(LC_CTYPE, NULL);
64 setlocale(LC_CTYPE, "");
66 charset = nl_langinfo (CODESET);
68 setlocale(LC_CTYPE, p);
69 #endif
71 if (charset && *charset)
72 return charset;
74 return "ASCII";
77 static const char *stringprep_locale_charset_cache = NULL;
79 const char *
80 stringprep_locale_charset ()
82 if (!stringprep_locale_charset_cache)
83 stringprep_locale_charset_cache = stringprep_locale_charset_slow ();
85 return stringprep_locale_charset_cache;
88 char*
89 stringprep_convert (const char *str,
90 const char *to_codeset,
91 const char *from_codeset)
93 iconv_t cd;
94 char *dest;
95 char *outp;
96 char *p;
97 size_t inbytes_remaining;
98 size_t outbytes_remaining;
99 size_t err;
100 size_t outbuf_size;
101 int have_error = 0;
102 int len;
104 if (strcmp(to_codeset, from_codeset) == 0)
105 return strdup(str);
107 cd = iconv_open (to_codeset, from_codeset);
109 if (cd == (iconv_t) -1)
110 return NULL;
112 len = strlen(str);
114 p = (char*) str;
115 inbytes_remaining = len;
116 outbuf_size = len + 1; /* + 1 for nul in case len == 1 */
118 outbytes_remaining = outbuf_size - 1; /* -1 for nul */
119 outp = dest = malloc (outbuf_size);
121 again:
123 err = iconv (cd, &p, &inbytes_remaining, &outp, &outbytes_remaining);
125 if (err == (size_t) -1)
127 switch (errno)
129 case EINVAL:
130 /* Incomplete text, do not report an error */
131 break;
133 case E2BIG:
135 size_t used = outp - dest;
137 outbuf_size *= 2;
138 dest = realloc (dest, outbuf_size);
140 outp = dest + used;
141 outbytes_remaining = outbuf_size - used - 1; /* -1 for nul */
143 goto again;
145 break;
147 case EILSEQ:
148 have_error = 1;
149 break;
151 default:
152 have_error = 1;
153 break;
157 *outp = '\0';
159 if ((p - str) != len)
160 have_error = 1;
162 iconv_close (cd);
164 if (have_error)
166 free (dest);
167 dest = NULL;
170 return dest;
173 #else
175 const char *
176 stringprep_locale_charset ()
178 return NULL;
181 char*
182 stringprep_convert (const char *str,
183 const char *to_codeset,
184 const char *from_codeset)
186 return NULL;
189 #endif
191 char *
192 stringprep_locale_to_utf8 (const char *str)
194 return stringprep_convert (str, "UTF-8", stringprep_locale_charset ());