/*
* Copyright (C) 2012, 2013 Eric Biggers
*
- * This file is part of wimlib, a library for working with WIM files.
+ * This file is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 3 of the License, or (at your option) any
+ * later version.
*
- * wimlib is free software; you can redistribute it and/or modify it under the
- * terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 3 of the License, or (at your option)
- * any later version.
- *
- * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * This file is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
- * You should have received a copy of the GNU General Public License
- * along with wimlib; if not, see http://www.gnu.org/licenses/.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this file; if not, see http://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
struct iconv_list_head name = { \
.from_encoding = from, \
.to_encoding = to, \
- .list = LIST_HEAD_INIT(name.list), \
- .mutex = PTHREAD_MUTEX_INITIALIZER, \
}
static iconv_t *
errno = errno_save;
}
-/* Prevent printing an error message if a character conversion error occurs
- * while printing an error message. (This variable is not per-thread but it
- * doesn't matter too much since it's just the error messages.) */
-static bool error_message_being_printed = false;
-
#define DEFINE_CHAR_CONVERSION_FUNCTIONS(varname1, longname1, chartype1,\
varname2, longname2, chartype2,\
earlyreturn_on_utf8_locale, \
\
len = iconv(*cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft); \
if (len == (size_t)-1) { \
- if (!error_message_being_printed) { \
- error_message_being_printed = true; \
- err_msg; \
- error_message_being_printed = false; \
- } \
+ err_msg; \
ret = err_return; \
} else { \
*out_nbytes_ret = bufsize - outbytesleft; \
\
len = iconv(*cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft); \
if (len == (size_t)-1) { \
- if (!error_message_being_printed) { \
- error_message_being_printed = true; \
- err_msg; \
- error_message_being_printed = false; \
- } \
+ err_msg; \
ret = err_return; \
} else { \
out[(LARGE_NUMBER-outbytesleft)/sizeof(chartype2)] = 0; \
return utf8_to_tstr(utf8str, strlen(utf8str), out, &out_nbytes);
}
+static void
+iconv_init(struct iconv_list_head *head)
+{
+ pthread_mutex_init(&head->mutex, NULL);
+ INIT_LIST_HEAD(&head->list);
+}
+
static void
iconv_cleanup(struct iconv_list_head *head)
{
}
}
+void
+iconv_global_init(void)
+{
+ iconv_init(&iconv_utf8_to_tstr);
+ iconv_init(&iconv_tstr_to_utf8);
+#if !TCHAR_IS_UTF16LE
+ iconv_init(&iconv_utf16le_to_tstr);
+ iconv_init(&iconv_tstr_to_utf16le);
+ iconv_init(&iconv_utf16le_to_utf8);
+ iconv_init(&iconv_utf8_to_utf16le);
+#endif
+}
+
void
iconv_global_cleanup(void)
{
return (n1 < n2) ? -1 : 1;
}
-/* Duplicates a string of system-dependent encoding into a UTF-16LE string and
- * returns the string and its length, in bytes, in the pointer arguments. Frees
- * any existing string at the return location before overwriting it. */
-int
-get_utf16le_string(const tchar *name, utf16lechar **name_utf16le_ret,
- u16 *name_utf16le_nbytes_ret)
+/* Duplicate a UTF16-LE string. The input string might not be null terminated
+ * and might be misaligned, but the returned string is guaranteed to be null
+ * terminated and properly aligned. */
+utf16lechar *
+utf16le_dupz(const void *ustr, size_t usize)
{
- utf16lechar *name_utf16le;
- size_t name_utf16le_nbytes;
- int ret;
-#if TCHAR_IS_UTF16LE
- name_utf16le_nbytes = tstrlen(name) * sizeof(utf16lechar);
- name_utf16le = MALLOC(name_utf16le_nbytes + sizeof(utf16lechar));
- if (name_utf16le == NULL)
- return WIMLIB_ERR_NOMEM;
- memcpy(name_utf16le, name, name_utf16le_nbytes + sizeof(utf16lechar));
- ret = 0;
-#else
-
- ret = tstr_to_utf16le(name, tstrlen(name), &name_utf16le,
- &name_utf16le_nbytes);
- if (ret == 0) {
- if (name_utf16le_nbytes > 0xffff) {
- FREE(name_utf16le);
- ERROR("Multibyte string \"%"TS"\" is too long!", name);
- ret = WIMLIB_ERR_INVALID_UTF8_STRING;
- }
+ utf16lechar *dup = MALLOC(usize + sizeof(utf16lechar));
+ if (dup) {
+ memcpy(dup, ustr, usize);
+ dup[usize / sizeof(utf16lechar)] = 0;
}
-#endif
- if (ret == 0) {
- FREE(*name_utf16le_ret);
- *name_utf16le_ret = name_utf16le;
- *name_utf16le_nbytes_ret = name_utf16le_nbytes;
- }
- return ret;
+ return dup;
}
-