X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fencoding.c;h=bddb18104fda798426d73893972ffc0ea1ec4c12;hp=edb24c70796ff3efc73b36d16aad812df2e12c9a;hb=2a33c303e30fd740f740e21632fd06b9e414b0c7;hpb=ded522fd0a15d740354329c5066ebd3473563e57 diff --git a/src/encoding.c b/src/encoding.c index edb24c70..bddb1810 100644 --- a/src/encoding.c +++ b/src/encoding.c @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2012 Eric Biggers + * Copyright (C) 2012, 2013 Eric Biggers * * This file is part of wimlib, a library for working with WIM files. * @@ -21,6 +21,7 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ +#include "config.h" #include "wimlib.h" #include "util.h" #include "endianness.h" @@ -28,10 +29,13 @@ #include #ifdef WITH_NTFS_3G -#include -#include +# include +# include +#elif defined(__WIN32__) +# include +# include #else -#include +# include #endif /* @@ -41,7 +45,7 @@ * libntfs-3g/unistr.c in the NTFS-3g sources. (Modified slightly to remove * unneeded functionality.) */ -#ifndef WITH_NTFS_3G +#if !defined(WITH_NTFS_3G) && !defined(__WIN32__) /* * Return the amount of 8-bit elements in UTF-8 needed (without the terminating * null) to store a given UTF-16LE string. @@ -130,7 +134,46 @@ static int utf8_to_utf16_size(const char *s) } return count; } -#endif /* !WITH_NTFS_3G */ + +static iconv_t cd_utf8_to_utf16 = (iconv_t)(-1); +static iconv_t cd_utf16_to_utf8 = (iconv_t)(-1); + +int iconv_global_init() +{ + if (cd_utf16_to_utf8 == (iconv_t)(-1)) { + cd_utf16_to_utf8 = iconv_open("UTF-8", "UTF-16LE"); + if (cd_utf16_to_utf8 == (iconv_t)-1) { + ERROR_WITH_ERRNO("Failed to get conversion descriptor " + "for converting UTF-16LE to UTF-8"); + if (errno == ENOMEM) + return WIMLIB_ERR_NOMEM; + else + return WIMLIB_ERR_ICONV_NOT_AVAILABLE; + } + } + + if (cd_utf8_to_utf16 == (iconv_t)(-1)) { + cd_utf8_to_utf16 = iconv_open("UTF-16LE", "UTF-8"); + if (cd_utf8_to_utf16 == (iconv_t)-1) { + ERROR_WITH_ERRNO("Failed to get conversion descriptor " + "for converting UTF-8 to UTF-16LE"); + if (errno == ENOMEM) + return WIMLIB_ERR_NOMEM; + else + return WIMLIB_ERR_ICONV_NOT_AVAILABLE; + } + } + return 0; +} + +void iconv_global_cleanup() +{ + if (cd_utf8_to_utf16 != (iconv_t)(-1)) + iconv_close(cd_utf8_to_utf16); + if (cd_utf16_to_utf8 != (iconv_t)(-1)) + iconv_close(cd_utf16_to_utf8); +} +#endif /* !WITH_NTFS_3G && !__WIN32__ */ /* Converts a string in the UTF-16LE encoding to a newly allocated string in the * UTF-8 encoding. @@ -167,19 +210,28 @@ int utf16_to_utf8(const char *utf16_str, size_t utf16_nbytes, else ret = WIMLIB_ERR_INVALID_UTF16_STRING; } -#else /* WITH_NTFS_3G */ - static iconv_t cd_utf16_to_utf8 = (iconv_t)(-1); - if (cd_utf16_to_utf8 == (iconv_t)(-1)) { - cd_utf16_to_utf8 = iconv_open("UTF-8", "UTF-16LE"); - if (cd_utf16_to_utf8 == (iconv_t)-1) { - ERROR_WITH_ERRNO("Failed to get conversion descriptor " - "for converting UTF-16LE to UTF-8"); - if (errno == ENOMEM) - return WIMLIB_ERR_NOMEM; - else - return WIMLIB_ERR_ICONV_NOT_AVAILABLE; +#elif defined(__WIN32__) + char *utf8_str; + size_t utf8_nbytes; + utf8_nbytes = wcstombs(NULL, (const wchar_t*)utf16_str, 0); + if (utf8_nbytes == (size_t)(-1)) { + ret = WIMLIB_ERR_INVALID_UTF16_STRING; + } else { + utf8_str = MALLOC(utf8_nbytes + 1); + if (!utf8_str) { + ret = WIMLIB_ERR_NOMEM; + } else { + wcstombs(utf8_str, (const wchar_t*)utf16_str, utf8_nbytes + 1); + *utf8_str_ret = utf8_str; + *utf8_nbytes_ret = utf8_nbytes; + ret = 0; } } +#else + ret = iconv_global_init(); + if (ret != 0) + return ret; + ret = utf16_to_utf8_size((const u16*)utf16_str, utf16_nbytes / 2); if (ret >= 0) { size_t utf8_expected_nbytes; @@ -262,20 +314,30 @@ int utf8_to_utf16(const char *utf8_str, size_t utf8_nbytes, else ret = WIMLIB_ERR_INVALID_UTF8_STRING; } -#else /* WITH_NTFS_3G */ - static iconv_t cd_utf8_to_utf16 = (iconv_t)(-1); - if (cd_utf8_to_utf16 == (iconv_t)(-1)) { - cd_utf8_to_utf16 = iconv_open("UTF-16LE", "UTF-8"); - if (cd_utf8_to_utf16 == (iconv_t)-1) { - ERROR_WITH_ERRNO("Failed to get conversion descriptor " - "for converting UTF-8 to UTF-16LE"); - if (errno == ENOMEM) - return WIMLIB_ERR_NOMEM; - else - return WIMLIB_ERR_ICONV_NOT_AVAILABLE; +#elif defined(__WIN32__) + + char *utf16_str; + size_t utf16_nchars; + utf16_nchars = mbstowcs(NULL, utf8_str, 0); + if (utf16_nchars == (size_t)(-1)) { + ret = WIMLIB_ERR_INVALID_UTF8_STRING; + } else { + utf16_str = MALLOC((utf16_nchars + 1) * sizeof(wchar_t)); + if (!utf16_str) { + ret = WIMLIB_ERR_NOMEM; + } else { + mbstowcs((wchar_t*)utf16_str, utf8_str, + utf16_nchars + 1); + *utf16_str_ret = utf16_str; + *utf16_nbytes_ret = utf16_nchars * sizeof(wchar_t); + ret = 0; } } - + +#else + ret = iconv_global_init(); + if (ret != 0) + return ret; ret = utf8_to_utf16_size(utf8_str); if (ret >= 0) { size_t utf16_expected_nbytes;