]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Use wcsnrtombs() at archive_string_append_from_wcs_to_mbs() if available.
authorMichihiro NAKAJIMA <ggcueroad@gmail.com>
Sun, 10 Apr 2011 15:57:06 +0000 (11:57 -0400)
committerMichihiro NAKAJIMA <ggcueroad@gmail.com>
Sun, 10 Apr 2011 15:57:06 +0000 (11:57 -0400)
It's faster than use of wcrtomb/wctomb.

SVN-Revision: 3203

CMakeLists.txt
build/cmake/config.h.in
configure.ac
libarchive/archive_string.c

index 16248e345453b9ad669ed41f540f9553a8cd4dff..a12e719e992c693013922d9c4c570387281b051f 100644 (file)
@@ -610,6 +610,7 @@ CHECK_FUNCTION_EXISTS_GLIBC(wcrtomb HAVE_WCRTOMB)
 CHECK_FUNCTION_EXISTS_GLIBC(wcscmp HAVE_WCSCMP)
 CHECK_FUNCTION_EXISTS_GLIBC(wcscpy HAVE_WCSCPY)
 CHECK_FUNCTION_EXISTS_GLIBC(wcslen HAVE_WCSLEN)
+CHECK_FUNCTION_EXISTS_GLIBC(wcsnrtombs HAVE_WCSNRTOMBS)
 CHECK_FUNCTION_EXISTS_GLIBC(wctomb HAVE_WCTOMB)
 CHECK_FUNCTION_EXISTS_GLIBC(_ctime64_s HAVE__CTIME64_S)
 CHECK_FUNCTION_EXISTS_GLIBC(_fseeki64 HAVE__FSEEKI64)
index c348aa6ad762fcb658e19dbdd33859a2635d0e7a..2300551693d3c0c88ea296ecf039bd423c7a3f5f 100644 (file)
@@ -901,6 +901,9 @@ typedef uint64_t uintmax_t;
 /* Define to 1 if you have the `wcslen' function. */
 #cmakedefine HAVE_WCSLEN 1
 
+/* Define to 1 if you have the `wcsnrtombs' function. */
+#cmakedefine HAVE_WCSNRTOMBS 1
+
 /* Define to 1 if you have the `wctomb' function. */
 #cmakedefine HAVE_WCTOMB 1
 
index 9ae48d58c83b2ad831fb55664a9b3ae9976515fe..e6d8099354f3c497eb8a7972dade0e8f8b3c1cef 100644 (file)
@@ -444,7 +444,7 @@ AC_CHECK_FUNCS([nl_langinfo openat pipe poll readlink readlinkat])
 AC_CHECK_FUNCS([select setenv setlocale sigaction statfs statvfs])
 AC_CHECK_FUNCS([strchr strdup strerror strncpy_s strrchr symlink timegm])
 AC_CHECK_FUNCS([tzset unsetenv utime utimensat utimes vfork])
-AC_CHECK_FUNCS([wcrtomb wcscmp wcscpy wcslen wctomb wmemcmp wmemcpy])
+AC_CHECK_FUNCS([wcrtomb wcscmp wcscpy wcslen wcsnrtombs wctomb wmemcmp wmemcpy])
 AC_CHECK_FUNCS([_ctime64_s _fseeki64])
 AC_CHECK_FUNCS([_get_timezone _localtime64_s _mkgmtime64])
 # detects cygwin-1.7, as opposed to older versions
index 224f90b67b641b00015f9d35681078a20a311a8d..c10e7b6c0db9137af11a0884e1b3f08ed67486cb 100644 (file)
@@ -488,6 +488,49 @@ archive_string_append_from_wcs_to_mbs(struct archive *a,
        return (0);
 }
 
+#elif defined(HAVE_WCSNRTOMBS)
+
+/*
+ * Translates a wide character string into current locale character set
+ * and appends to the archive_string.  Note: returns -1 if conversion
+ * fails.
+ */
+int
+archive_string_append_from_wcs_to_mbs(struct archive *a,
+    struct archive_string *as, const wchar_t *w, size_t len)
+{
+       mbstate_t shift_state;
+       size_t r, ndest, nwc;
+       char *dest;
+       const wchar_t *wp, *wpp;
+
+       wp = w;
+       nwc = len;
+       ndest = len * 2;
+       /* Initialize the shift state. */
+       memset(&shift_state, 0, sizeof(shift_state));
+       for (;;) {
+               /* Allocate buffer for MBS. */
+               if (archive_string_ensure(as, as->length + ndest + 1) == NULL)
+                       __archive_errx(1, "Out of memory");
+
+               dest = as->s + as->length;
+               wpp = wp;
+               r = wcsnrtombs(dest, &wp, nwc, as->buffer_length -1,
+                   &shift_state);
+               if (r == (size_t)-1)
+                       return (-1);
+               as->length += r;
+               if (wp == NULL || (wp - wpp) >= nwc) {
+                       /* All WCS translated to MBS. */
+                       as->s[as->length] = '\0';
+                       return (0);
+               }
+               /* Get a remaining WCS lenth. */
+               nwc -= wp - wpp;
+       }
+}
+
 #elif defined(HAVE_WCTOMB) || defined(HAVE_WCRTOMB)
 
 /*