]> git.saurik.com Git - apple/libc.git/blobdiff - string/FreeBSD/wcsxfrm.c
Libc-825.24.tar.gz
[apple/libc.git] / string / FreeBSD / wcsxfrm.c
index 7aea3d13bf1f032b71476cae9089e94790488d61..eae9360170984b1b9164bfa316904ebcfceaf276 100644 (file)
@@ -31,23 +31,23 @@ __FBSDID("FreeBSD: src/lib/libc/string/strxfrm.c,v 1.15 2002/09/06 11:24:06 tjr
 #endif
 __FBSDID("$FreeBSD: src/lib/libc/string/wcsxfrm.c,v 1.3 2004/04/07 09:47:56 tjr Exp $");
 
+#include "xlocale_private.h"
+
 #include <stdlib.h>
 #include <string.h>
 #include <wchar.h>
+#include <errno.h>
 #include "collate.h"
 
-static char *__mbsdup(const wchar_t *);
+#define WCS_XFRM_OFFSET        1
 
-/*
- * Placeholder wcsxfrm() implementation. See wcscoll.c for a description of
- * the logic used.
- */
 size_t
-wcsxfrm(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len)
+wcsxfrm_l(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len,
+    locale_t loc)
 {
-       int prim, sec, l;
        size_t slen;
-       char *mbsrc, *s, *ss;
+       wchar_t *xf[2];
+       int sverrno;
 
        if (*src == L'\0') {
                if (len != 0)
@@ -55,7 +55,8 @@ wcsxfrm(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len)
                return (0);
        }
 
-       if (__collate_load_error || MB_CUR_MAX > 1) {
+       NORMALIZE_LOCALE(loc);
+       if (loc->__collate_load_error) {
                slen = wcslen(src);
                if (len > 0) {
                        if (slen < len)
@@ -68,49 +69,41 @@ wcsxfrm(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len)
                return (slen);
        }
 
-       mbsrc = __mbsdup(src);
-       slen = 0;
-       prim = sec = 0;
-       ss = s = __collate_substitute(mbsrc);
-       while (*s != '\0') {
-               while (*s != '\0' && prim == 0) {
-                       __collate_lookup(s, &l, &prim, &sec);
-                       s += l;
+       __collate_xfrm(src, xf, loc);
+
+       slen = wcslen(xf[0]);
+       if (xf[1])
+               slen += wcslen(xf[1]) + 1;
+       if (len > 0) {
+               wchar_t *w = xf[0];
+               while (len > 1) {
+                       if (!*w)
+                               break;
+                       *dest++ = *w++ + WCS_XFRM_OFFSET;
+                       len--;
                }
-               if (prim != 0) {
-                       if (len > 1) {
-                               *dest++ = (wchar_t)prim;
+               if ((w = xf[1]) != NULL) {
+                       if (len > 1)
+                               *dest++ = WCS_XFRM_OFFSET;
+                       while (len > 1) {
+                               if (!*w)
+                                       break;
+                               *dest++ = *w++ + WCS_XFRM_OFFSET;
                                len--;
                        }
-                       slen++;
-                       prim = 0;
                }
-       }
-       free(ss);
-       free(mbsrc);
-       if (len != 0)
-               *dest = L'\0';
-
+               *dest = 0;
+       }
+       sverrno = errno;
+       free(xf[0]);
+       free(xf[1]);
+       errno = sverrno;
        return (slen);
 }
 
-static char *
-__mbsdup(const wchar_t *ws)
+size_t
+wcsxfrm(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len)
 {
-       static const mbstate_t initial;
-       mbstate_t st;
-       const wchar_t *wcp;
-       size_t len;
-       char *mbs;
-
-       wcp = ws;
-       st = initial;
-       if ((len = wcsrtombs(NULL, &wcp, 0, &st)) == (size_t)-1)
-               return (NULL);
-       if ((mbs = malloc(len + 1)) == NULL)
-               return (NULL);
-       st = initial;
-       wcsrtombs(mbs, &ws, len + 1, &st);
-
-       return (mbs);
+       return wcsxfrm_l(dest, src, len, __current_locale());
 }