Print this page
2964 need POSIX 2008 locale object support
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Approved by: TBD

@@ -1,6 +1,7 @@
 /*
+ * Copyright 2013 Garrett D'Amore <garrett@damore.org>
  * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2002 Tim J. Robbins
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without

@@ -30,21 +31,21 @@
 #include <stdlib.h>
 #include <string.h>
 #include <wchar.h>
 #include <assert.h>
 #include "collate.h"
+#include "localeimpl.h"
 
 int
-wcscoll(const wchar_t *ws1, const wchar_t *ws2)
+wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t loc)
 {
         int len1, len2, pri1, pri2, ret;
         wchar_t *tr1 = NULL, *tr2 = NULL;
         int direc, pass;
+        const struct lc_collate *lcc = loc->collate;
 
-        collate_info_t *info = _collate_info;
-
-        if (_collate_load_error)
+        if (lcc->lc_is_posix)
                 /*
                  * Locale has no special collating order or could not be
                  * loaded, do a fast binary comparison.
                  */
                 return (wcscmp(ws1, ws2));

@@ -61,22 +62,22 @@
          * 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.
          */
-        for (pass = 0; pass <= info->directive_count; pass++) {
+        for (pass = 0; pass <= lcc->lc_directive_count; pass++) {
 
-                int32_t *st1 = NULL;
-                int32_t *st2 = NULL;
+                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 == info->directive_count) {
+                if (pass == lcc->lc_directive_count) {
                         direc = DIRECTIVE_FORWARD | DIRECTIVE_UNDEFINED;
                 } else {
-                        direc = info->directive[pass];
+                        direc = lcc->lc_directive[pass];
                 }
 
                 if (direc & DIRECTIVE_BACKWARD) {
                         wchar_t *bp, *fp, c;
                         if ((tr1 = wcsdup(w1)) == NULL)

@@ -102,19 +103,21 @@
                 }
 
                 if (direc & DIRECTIVE_POSITION) {
                         while ((*w1 || st1) && (*w2 || st2)) {
                                 pri1 = pri2 = 0;
-                                _collate_lookup(w1, &len1, &pri1, pass, &st1);
+                                _collate_lookup(lcc, w1, &len1, &pri1, pass,
+                                    &st1);
                                 if (pri1 <= 0) {
                                         if (pri1 < 0) {
                                                 errno = EINVAL;
                                                 goto fail;
                                         }
                                         pri1 = COLLATE_MAX_PRIORITY;
                                 }
-                                _collate_lookup(w2, &len2, &pri2, pass, &st2);
+                                _collate_lookup(lcc, w2, &len2, &pri2, pass,
+                                    &st2);
                                 if (pri2 <= 0) {
                                         if (pri2 < 0) {
                                                 errno = EINVAL;
                                                 goto fail;
                                         }

@@ -129,11 +132,11 @@
                         }
                 } else {
                         while ((*w1 || st1) && (*w2 || st2)) {
                                 pri1 = pri2 = 0;
                                 while (*w1) {
-                                        _collate_lookup(w1, &len1,
+                                        _collate_lookup(lcc, w1, &len1,
                                             &pri1, pass, &st1);
                                         if (pri1 > 0)
                                                 break;
                                         if (pri1 < 0) {
                                                 errno = EINVAL;

@@ -140,11 +143,11 @@
                                                 goto fail;
                                         }
                                         w1 += len1;
                                 }
                                 while (*w2) {
-                                        _collate_lookup(w2, &len2,
+                                        _collate_lookup(lcc, w2, &len2,
                                             &pri2, pass, &st2);
                                         if (pri2 > 0)
                                                 break;
                                         if (pri2 < 0) {
                                                 errno = EINVAL;

@@ -183,6 +186,13 @@
         return (ret);
 
 fail:
         ret = wcscmp(ws1, ws2);
         goto end;
+}
+
+
+int
+wcscoll(const wchar_t *ws1, const wchar_t *ws2)
+{
+        return (wcscoll_l(ws1, ws2, uselocale(NULL)));
 }