Loading...
--- Libc/Libc-1725.40.4/string/FreeBSD/wcscoll.c
+++ Libc/Libc-498/string/FreeBSD/wcscoll.c
@@ -1,14 +1,6 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright 2017 Nexenta Systems, Inc.
* Copyright (c) 2002 Tim J. Robbins
* All rights reserved.
- *
- * Copyright (c) 2011 The FreeBSD Foundation
- *
- * Portions of this software were developed by David Chisnall
- * under sponsorship from the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -32,201 +24,75 @@
* SUCH DAMAGE.
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/wcscoll.c,v 1.3 2004/04/07 09:47:56 tjr Exp $");
+
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "collate.h"
-int
-wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t locale)
-{
- int len1, len2, pri1, pri2;
- wchar_t *tr1 = NULL, *tr2 = NULL;
- int direc, pass;
- int ret = wcscmp(ws1, ws2);
+static char *__mbsdup(const wchar_t *);
- NORMALIZE_LOCALE(locale);
- struct xlocale_collate *table = XLOCALE_COLLATE(locale);
-
- if (table->__collate_load_error || ret == 0)
- return (ret);
-
- if (*ws1 == 0 && *ws2 != 0)
- return (-1);
- if (*ws1 != 0 && *ws2 == 0)
- return (1);
-
- /*
- * Once upon a time we had code to try to optimize this, but
- * it turns out that you really can't make many assumptions
- * safely. You absolutely have to run this pass by pass,
- * because some passes will be ignored for a given character,
- * while others will not. Simpler locales will benefit from
- * having fewer passes, and most comparisons should resolve
- * during the primary pass anyway.
- *
- * Note that we do one final extra pass at the end to pick
- * up UNDEFINED elements. There is special handling for them.
- */
-#ifdef __APPLE__
- for (pass = 0; pass < table->info->directive_count; pass++) {
-#else
- for (pass = 0; pass <= table->info->directive_count; pass++) {
-#endif
- const int32_t *st1 = NULL;
- const int32_t *st2 = NULL;
- const wchar_t *w1 = ws1;
- const wchar_t *w2 = ws2;
-
- /* special pass for UNDEFINED */
- if (pass == table->info->directive_count) {
- direc = DIRECTIVE_FORWARD;
- } else {
- direc = table->info->directive[pass];
- }
-
- if (direc & DIRECTIVE_BACKWARD) {
- wchar_t *bp, *fp, c;
- free(tr1);
- if ((tr1 = wcsdup(w1)) == NULL)
- goto end;
- bp = tr1;
- fp = tr1 + wcslen(tr1) - 1;
- while (bp < fp) {
- c = *bp;
- *bp++ = *fp;
- *fp-- = c;
- }
- free(tr2);
- if ((tr2 = wcsdup(w2)) == NULL)
- goto end;
- bp = tr2;
- fp = tr2 + wcslen(tr2) - 1;
- while (bp < fp) {
- c = *bp;
- *bp++ = *fp;
- *fp-- = c;
- }
- w1 = tr1;
- w2 = tr2;
- }
-
- if (direc & DIRECTIVE_POSITION) {
- int check1, check2;
- while (*w1 && *w2) {
- pri1 = pri2 = 0;
- check1 = check2 = 1;
- while ((pri1 == pri2) && (check1 || check2)) {
- if (check1) {
- _collate_lookup(table, w1, &len1,
- &pri1, pass, &st1);
- if (pri1 < 0) {
- errno = EINVAL;
- goto end;
- }
- if (!pri1) {
- pri1 = COLLATE_MAX_PRIORITY;
- st1 = NULL;
- }
- check1 = (st1 != NULL);
- }
- if (check2) {
- _collate_lookup(table, w2, &len2,
- &pri2, pass, &st2);
- if (pri2 < 0) {
- errno = EINVAL;
- goto end;
- }
- if (!pri2) {
- pri2 = COLLATE_MAX_PRIORITY;
- st2 = NULL;
- }
- check2 = (st2 != NULL);
- }
- }
- if (pri1 != pri2) {
- ret = pri1 - pri2;
- goto end;
- }
- w1 += len1;
- w2 += len2;
- }
- if (!*w1) {
- if (*w2) {
- ret = -(int)*w2;
- goto end;
- }
- } else {
- ret = *w1;
- goto end;
- }
- } else {
- int vpri1 = 0, vpri2 = 0;
- while (*w1 || *w2 || st1 || st2) {
- pri1 = 1;
- while (*w1 || st1) {
- _collate_lookup(table, w1, &len1, &pri1,
- pass, &st1);
- w1 += len1;
- if (pri1 > 0) {
- vpri1++;
- break;
- }
-
- if (pri1 < 0) {
- errno = EINVAL;
- goto end;
- }
- st1 = NULL;
- }
- pri2 = 1;
- while (*w2 || st2) {
- _collate_lookup(table, w2, &len2, &pri2,
- pass, &st2);
- w2 += len2;
- if (pri2 > 0) {
- vpri2++;
- break;
- }
- if (pri2 < 0) {
- errno = EINVAL;
- goto end;
- }
- st2 = NULL;
- }
- if ((!pri1 || !pri2) && (vpri1 == vpri2))
- break;
- if (pri1 != pri2) {
- ret = pri1 - pri2;
- goto end;
- }
- }
- if (vpri1 && !vpri2) {
- ret = 1;
- goto end;
- }
- if (!vpri1 && vpri2) {
- ret = -1;
- goto end;
- }
- }
- }
- ret = 0;
-
-end:
- free(tr1);
- free(tr2);
-
- return (ret);
-}
-
+/*
+ * Placeholder implementation of wcscoll(). Attempts to use the single-byte
+ * collation ordering where possible, and falls back on wcscmp() in locales
+ * with extended character sets.
+ */
int
wcscoll(const wchar_t *ws1, const wchar_t *ws2)
{
-#ifdef __APPLE__
- return wcscoll_l(ws1, ws2, __current_locale());
-#else
- return wcscoll_l(ws1, ws2, __get_locale());
-#endif
+ char *mbs1, *mbs2;
+ int diff, sverrno;
+
+ if (__collate_load_error || MB_CUR_MAX > 1)
+ /*
+ * Locale has no special collating order, could not be
+ * loaded, or has an extended character set; do a fast binary
+ * comparison.
+ */
+ return (wcscmp(ws1, ws2));
+
+ if ((mbs1 = __mbsdup(ws1)) == NULL || (mbs2 = __mbsdup(ws2)) == NULL) {
+ /*
+ * Out of memory or illegal wide chars; fall back to wcscmp()
+ * but leave errno indicating the error. Callers that don't
+ * check for error will get a reasonable but often slightly
+ * incorrect result.
+ */
+ sverrno = errno;
+ free(mbs1);
+ errno = sverrno;
+ return (wcscmp(ws1, ws2));
+ }
+
+ diff = strcoll(mbs1, mbs2);
+ sverrno = errno;
+ free(mbs1);
+ free(mbs2);
+ errno = sverrno;
+
+ return (diff);
}
+
+static char *
+__mbsdup(const wchar_t *ws)
+{
+ 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);
+}