summaryrefslogtreecommitdiffstats
path: root/lib/libc/string/strxfrm.c
diff options
context:
space:
mode:
authorbapt <bapt@FreeBSD.org>2015-08-07 23:41:26 +0000
committerbapt <bapt@FreeBSD.org>2015-08-07 23:41:26 +0000
commit11a5726cda4d7b191129ed4220970bf8e00a8db6 (patch)
tree063f1101225b65ad20c1a8be3c96300b958d5a20 /lib/libc/string/strxfrm.c
parentcbf6cdcbbb6c0212ee9911bbbe9e87053b54ab9f (diff)
downloadFreeBSD-src-11a5726cda4d7b191129ed4220970bf8e00a8db6.zip
FreeBSD-src-11a5726cda4d7b191129ed4220970bf8e00a8db6.tar.gz
The collate functions within libc have been using version 1 and 1.2 of the
packed LC_COLLATE binary formats. These were generated with the colldef tool, but the new LC_COLLATE files are going to be generated by the new localedef tool using CLDR POSIX files as input. The BSD-flavored version of localedef identifies the format as "BSD 1.0". Any LC_COLLATE file with a different version will simply not be loaded, and all LC* categories will get set to "C" (aka "POSIX") locale. This work is based off of Nexenta's contribution to Illumos. The integration with xlocale is John Marino's work for Dragonfly. The following commits will enable localedef tool, disable the colldef tool, add generated colldef directory, and finally remove colldef from base. The only difference with Dragonfly are: - a few fixes to build with clang - And identification of the flavor as "BSD 1.0" instead of "Dragonfly 4.4" Obtained from: Dragonfly
Diffstat (limited to 'lib/libc/string/strxfrm.c')
-rw-r--r--lib/libc/string/strxfrm.c66
1 files changed, 41 insertions, 25 deletions
diff --git a/lib/libc/string/strxfrm.c b/lib/libc/string/strxfrm.c
index b758b0c..8b25b0e 100644
--- a/lib/libc/string/strxfrm.c
+++ b/lib/libc/string/strxfrm.c
@@ -1,4 +1,5 @@
/*-
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
* at Electronni Visti IA, Kiev, Ukraine.
* All rights reserved.
@@ -35,6 +36,8 @@ __FBSDID("$FreeBSD$");
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
+#include <wchar.h>
#include "collate.h"
size_t
@@ -48,9 +51,10 @@ strxfrm(char * __restrict dest, const char * __restrict src, size_t len)
size_t
strxfrm_l(char * __restrict dest, const char * __restrict src, size_t len, locale_t locale)
{
- int prim, sec, l;
size_t slen;
- char *s, *ss;
+ size_t xlen;
+ wchar_t *wcs = NULL;
+
FIX_LOCALE(locale);
struct xlocale_collate *table =
(struct xlocale_collate*)locale->components[XLC_COLLATE];
@@ -58,32 +62,44 @@ strxfrm_l(char * __restrict dest, const char * __restrict src, size_t len, local
if (!*src) {
if (len > 0)
*dest = '\0';
- return 0;
+ return (0);
}
+ /*
+ * The conversion from multibyte to wide character strings is
+ * strictly reducing (one byte of an mbs cannot expand to more
+ * than one wide character.)
+ */
+ slen = strlen(src);
+
if (table->__collate_load_error)
- return strlcpy(dest, src, len);
-
- slen = 0;
- prim = sec = 0;
- ss = s = __collate_substitute(table, src);
- while (*s) {
- while (*s && !prim) {
- __collate_lookup(table, s, &l, &prim, &sec);
- s += l;
- }
- if (prim) {
- if (len > 1) {
- *dest++ = (char)prim;
- len--;
- }
- slen++;
- prim = 0;
- }
+ goto error;
+
+ if ((wcs = malloc((slen + 1) * sizeof (wchar_t))) == NULL)
+ goto error;
+
+ if (mbstowcs_l(wcs, src, slen + 1, locale) == (size_t)-1)
+ goto error;
+
+ if ((xlen = _collate_sxfrm(table, wcs, dest, len)) == (size_t)-1)
+ goto error;
+
+ if (wcs)
+ free(wcs);
+
+ if (len > xlen) {
+ dest[xlen] = 0;
+ } else if (len) {
+ dest[len-1] = 0;
}
- free(ss);
- if (len > 0)
- *dest = '\0';
- return slen;
+ return (xlen);
+
+error:
+ /* errno should be set to ENOMEM if malloc failed */
+ if (wcs)
+ free(wcs);
+ (void) strlcpy(dest, src, len);
+
+ return (slen);
}
OpenPOWER on IntegriCloud