1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2000-2012 Jeffrey Stedfast
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public License
7 * as published by the Free Software Foundation; either version 2.1
8 * of the License, or (at your option) any later version.
10 * This library 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 GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
30 #include "gmime-iconv-utils.h"
31 #include "gmime-charset.h"
33 #ifdef ENABLE_WARNINGS
37 #endif /* ENABLE_WARNINGS */
41 * SECTION: gmime-iconv-utils
42 * @title: gmime-iconv-utils
43 * @short_description: High-level routines for converting text from one charset to another
46 * Charset conversion utility functions.
50 #ifdef G_THREADS_ENABLED
51 static GStaticMutex lock = G_STATIC_MUTEX_INIT;
52 #define LOCK() g_static_mutex_lock (&lock)
53 #define UNLOCK() g_static_mutex_unlock (&lock)
57 #endif /* G_THREADS_ENABLED */
59 static iconv_t utf8_to_locale = (iconv_t) -1;
60 static iconv_t locale_to_utf8 = (iconv_t) -1;
64 iconv_utils_init (void)
66 static gboolean initialized = FALSE;
67 const char *utf8, *locale;
72 g_mime_charset_map_init ();
74 utf8 = g_mime_charset_iconv_name ("UTF-8");
76 if (!(locale = g_mime_locale_charset ()))
79 if ((locale = g_mime_charset_iconv_name (locale))) {
80 utf8_to_locale = iconv_open (locale, utf8);
81 locale_to_utf8 = iconv_open (utf8, locale);
89 * g_mime_iconv_strndup:
90 * @cd: conversion descriptor
91 * @str: string in source charset
92 * @n: number of bytes to convert
94 * Allocates a new string buffer containing the first @n bytes of @str
95 * converted to the destination charset as described by the conversion
98 * Returns: a new string buffer containing the first @n bytes of
99 * @str converted to the destination charset as described by the
100 * conversion descriptor @cd.
103 g_mime_iconv_strndup (iconv_t cd, const char *str, size_t n)
105 size_t inleft, outleft, converted = 0;
111 if (cd == (iconv_t) -1)
112 return g_strndup (str, n);
115 out = g_malloc (outlen + 4);
122 outbuf = out + converted;
123 outleft = outlen - converted;
125 converted = iconv (cd, (char **) &inbuf, &inleft, &outbuf, &outleft);
126 if (converted != (size_t) -1 || errno == EINVAL) {
128 * EINVAL An incomplete multibyte sequence has been encounĀ
129 * tered in the input.
131 * We'll just have to ignore it...
136 if (errno != E2BIG) {
139 w(g_warning ("g_mime_iconv_strndup: %s at byte %lu",
140 strerror (errno), n - inleft));
145 iconv (cd, NULL, NULL, NULL, NULL);
153 * E2BIG There is not sufficient room at *outbuf.
155 * We just need to grow our outbuffer and try again.
158 converted = outbuf - out;
159 outlen += inleft * 2 + 16;
160 out = g_realloc (out, outlen + 4);
161 outbuf = out + converted;
164 /* flush the iconv conversion */
165 while (iconv (cd, NULL, NULL, &outbuf, &outleft) == (size_t) -1) {
170 converted = outbuf - out;
171 out = g_realloc (out, outlen + 4);
172 outleft = outlen - converted;
173 outbuf = out + converted;
176 /* Note: not all charsets can be nul-terminated with a single
177 nul byte. UCS2, for example, needs 2 nul bytes and UCS4
178 needs 4. I hope that 4 nul bytes is enough to terminate all
179 multibyte charsets? */
181 /* nul-terminate the string */
182 memset (outbuf, 0, 4);
185 iconv (cd, NULL, NULL, NULL, NULL);
192 * g_mime_iconv_strdup:
193 * @cd: conversion descriptor
194 * @str: string in source charset
196 * Allocates a new string buffer containing @str converted to the
197 * destination charset described in @cd.
199 * Returns: a new string buffer containing the original string
200 * converted to the new charset.
203 g_mime_iconv_strdup (iconv_t cd, const char *str)
205 return g_mime_iconv_strndup (cd, str, strlen (str));
210 * g_mime_iconv_locale_to_utf8:
211 * @str: string in locale charset
213 * Allocates a new string buffer containing @str in UTF-8.
215 * Returns: a new string buffer containing @str converted to UTF-8.
218 g_mime_iconv_locale_to_utf8 (const char *str)
225 buf = g_mime_iconv_strdup (locale_to_utf8, str);
233 * g_mime_iconv_locale_to_utf8_length:
234 * @str: string in locale charset
235 * @n: number of bytes to convert
237 * Allocates a new string buffer containing the first @n bytes of
238 * @str converted to UTF-8.
240 * Returns: a new string buffer containing the first @n bytes of
241 * @str converted to UTF-8.
244 g_mime_iconv_locale_to_utf8_length (const char *str, size_t n)
251 buf = g_mime_iconv_strndup (locale_to_utf8, str, n);
259 * g_mime_iconv_utf8_to_locale:
260 * @str: string in UTF-8 charset
262 * Allocates a new string buffer containing @str converted to the
263 * user's locale charset.
265 * Returns: a new string buffer containing @str converted to the
266 * user's locale charset.
269 g_mime_iconv_utf8_to_locale (const char *str)
276 buf = g_mime_iconv_strdup (utf8_to_locale, str);
284 * g_mime_iconv_utf8_to_locale_length:
285 * @str: string in UTF-8 charset
286 * @n: number of bytes to convert
288 * Allocates a new string buffer containing the first @n bytes of
289 * @str converted to the user's locale charset.
291 * Returns: a new string buffer containing the first @n bytes of
292 * @str converted to the user's locale charset.
295 g_mime_iconv_utf8_to_locale_length (const char *str, size_t n)
302 buf = g_mime_iconv_strndup (utf8_to_locale, str, n);