Print this page
2964 need POSIX 2008 locale object support
Reviewed by: Robert Mustacchi <rm@joyent.com>
   1 /*

   2  * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
   3  * Copyright (c) 2002 Tim J. Robbins
   4  * All rights reserved.
   5  *
   6  * Redistribution and use in source and binary forms, with or without
   7  * modification, are permitted provided that the following conditions
   8  * are met:
   9  * 1. Redistributions of source code must retain the above copyright
  10  *    notice, this list of conditions and the following disclaimer.
  11  * 2. Redistributions in binary form must reproduce the above copyright
  12  *    notice, this list of conditions and the following disclaimer in the
  13  *    documentation and/or other materials provided with the distribution.
  14  *
  15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  25  * SUCH DAMAGE.
  26  */
  27 
  28 #include "lint.h"
  29 #include <errno.h>
  30 #include <stdlib.h>
  31 #include <string.h>
  32 #include <wchar.h>
  33 #include <assert.h>
  34 #include "collate.h"

  35 
  36 int
  37 wcscoll(const wchar_t *ws1, const wchar_t *ws2)
  38 {
  39         int len1, len2, pri1, pri2, ret;
  40         wchar_t *tr1 = NULL, *tr2 = NULL;
  41         int direc, pass;

  42 
  43         collate_info_t *info = _collate_info;
  44 
  45         if (_collate_load_error)
  46                 /*
  47                  * Locale has no special collating order or could not be
  48                  * loaded, do a fast binary comparison.
  49                  */
  50                 return (wcscmp(ws1, ws2));
  51 
  52         ret = 0;
  53 
  54         /*
  55          * Once upon a time we had code to try to optimize this, but
  56          * it turns out that you really can't make many assumptions
  57          * safely.  You absolutely have to run this pass by pass,
  58          * because some passes will be ignored for a given character,
  59          * while others will not.  Simpler locales will benefit from
  60          * having fewer passes, and most comparisions should resolve
  61          * during the primary pass anyway.
  62          *
  63          * Note that we do one final extra pass at the end to pick
  64          * up UNDEFINED elements.  There is special handling for them.
  65          */
  66         for (pass = 0; pass <= info->directive_count; pass++) {
  67 
  68                 int32_t *st1 = NULL;
  69                 int32_t *st2 = NULL;
  70                 const wchar_t   *w1 = ws1;
  71                 const wchar_t   *w2 = ws2;
  72 
  73                 /* special pass for UNDEFINED */
  74                 if (pass == info->directive_count) {
  75                         direc = DIRECTIVE_FORWARD | DIRECTIVE_UNDEFINED;
  76                 } else {
  77                         direc = info->directive[pass];
  78                 }
  79 
  80                 if (direc & DIRECTIVE_BACKWARD) {
  81                         wchar_t *bp, *fp, c;
  82                         if ((tr1 = wcsdup(w1)) == NULL)
  83                                 goto fail;
  84                         bp = tr1;
  85                         fp = tr1 + wcslen(tr1) - 1;
  86                         while (bp < fp) {
  87                                 c = *bp;
  88                                 *bp++ = *fp;
  89                                 *fp-- = c;
  90                         }
  91                         if ((tr2 = wcsdup(w2)) == NULL)
  92                                 goto fail;
  93                         bp = tr2;
  94                         fp = tr2 + wcslen(tr2) - 1;
  95                         while (bp < fp) {
  96                                 c = *bp;
  97                                 *bp++ = *fp;
  98                                 *fp-- = c;
  99                         }
 100                         w1 = tr1;
 101                         w2 = tr2;
 102                 }
 103 
 104                 if (direc & DIRECTIVE_POSITION) {
 105                         while ((*w1 || st1) && (*w2 || st2)) {
 106                                 pri1 = pri2 = 0;
 107                                 _collate_lookup(w1, &len1, &pri1, pass, &st1);

 108                                 if (pri1 <= 0) {
 109                                         if (pri1 < 0) {
 110                                                 errno = EINVAL;
 111                                                 goto fail;
 112                                         }
 113                                         pri1 = COLLATE_MAX_PRIORITY;
 114                                 }
 115                                 _collate_lookup(w2, &len2, &pri2, pass, &st2);

 116                                 if (pri2 <= 0) {
 117                                         if (pri2 < 0) {
 118                                                 errno = EINVAL;
 119                                                 goto fail;
 120                                         }
 121                                         pri2 = COLLATE_MAX_PRIORITY;
 122                                 }
 123                                 if (pri1 != pri2) {
 124                                         ret = pri1 - pri2;
 125                                         goto end;
 126                                 }
 127                                 w1 += len1;
 128                                 w2 += len2;
 129                         }
 130                 } else {
 131                         while ((*w1 || st1) && (*w2 || st2)) {
 132                                 pri1 = pri2 = 0;
 133                                 while (*w1) {
 134                                         _collate_lookup(w1, &len1,
 135                                             &pri1, pass, &st1);
 136                                         if (pri1 > 0)
 137                                                 break;
 138                                         if (pri1 < 0) {
 139                                                 errno = EINVAL;
 140                                                 goto fail;
 141                                         }
 142                                         w1 += len1;
 143                                 }
 144                                 while (*w2) {
 145                                         _collate_lookup(w2, &len2,
 146                                             &pri2, pass, &st2);
 147                                         if (pri2 > 0)
 148                                                 break;
 149                                         if (pri2 < 0) {
 150                                                 errno = EINVAL;
 151                                                 goto fail;
 152                                         }
 153                                         w2 += len2;
 154                                 }
 155                                 if (!pri1 || !pri2)
 156                                         break;
 157                                 if (pri1 != pri2) {
 158                                         ret = pri1 - pri2;
 159                                         goto end;
 160                                 }
 161                                 w1 += len1;
 162                                 w2 += len2;
 163                         }
 164                 }
 165                 if (!*w1) {


 168                                 goto end;
 169                         }
 170                 } else {
 171                         ret = *w1;
 172                         goto end;
 173                 }
 174         }
 175         ret = 0;
 176 
 177 end:
 178         if (tr1)
 179                 free(tr1);
 180         if (tr2)
 181                 free(tr2);
 182 
 183         return (ret);
 184 
 185 fail:
 186         ret = wcscmp(ws1, ws2);
 187         goto end;







 188 }
   1 /*
   2  * Copyright 2013 Garrett D'Amore <garrett@damore.org>
   3  * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
   4  * Copyright (c) 2002 Tim J. Robbins
   5  * All rights reserved.
   6  *
   7  * Redistribution and use in source and binary forms, with or without
   8  * modification, are permitted provided that the following conditions
   9  * are met:
  10  * 1. Redistributions of source code must retain the above copyright
  11  *    notice, this list of conditions and the following disclaimer.
  12  * 2. Redistributions in binary form must reproduce the above copyright
  13  *    notice, this list of conditions and the following disclaimer in the
  14  *    documentation and/or other materials provided with the distribution.
  15  *
  16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  26  * SUCH DAMAGE.
  27  */
  28 
  29 #include "lint.h"
  30 #include <errno.h>
  31 #include <stdlib.h>
  32 #include <string.h>
  33 #include <wchar.h>
  34 #include <assert.h>
  35 #include "collate.h"
  36 #include "localeimpl.h"
  37 
  38 int
  39 wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t loc)
  40 {
  41         int len1, len2, pri1, pri2, ret;
  42         wchar_t *tr1 = NULL, *tr2 = NULL;
  43         int direc, pass;
  44         const struct lc_collate *lcc = loc->collate;
  45 
  46         if (lcc->lc_is_posix)


  47                 /*
  48                  * Locale has no special collating order or could not be
  49                  * loaded, do a fast binary comparison.
  50                  */
  51                 return (wcscmp(ws1, ws2));
  52 
  53         ret = 0;
  54 
  55         /*
  56          * Once upon a time we had code to try to optimize this, but
  57          * it turns out that you really can't make many assumptions
  58          * safely.  You absolutely have to run this pass by pass,
  59          * because some passes will be ignored for a given character,
  60          * while others will not.  Simpler locales will benefit from
  61          * having fewer passes, and most comparisions should resolve
  62          * during the primary pass anyway.
  63          *
  64          * Note that we do one final extra pass at the end to pick
  65          * up UNDEFINED elements.  There is special handling for them.
  66          */
  67         for (pass = 0; pass <= lcc->lc_directive_count; pass++) {
  68 
  69                 const int32_t *st1 = NULL;
  70                 const int32_t *st2 = NULL;
  71                 const wchar_t   *w1 = ws1;
  72                 const wchar_t   *w2 = ws2;
  73 
  74                 /* special pass for UNDEFINED */
  75                 if (pass == lcc->lc_directive_count) {
  76                         direc = DIRECTIVE_FORWARD | DIRECTIVE_UNDEFINED;
  77                 } else {
  78                         direc = lcc->lc_directive[pass];
  79                 }
  80 
  81                 if (direc & DIRECTIVE_BACKWARD) {
  82                         wchar_t *bp, *fp, c;
  83                         if ((tr1 = wcsdup(w1)) == NULL)
  84                                 goto fail;
  85                         bp = tr1;
  86                         fp = tr1 + wcslen(tr1) - 1;
  87                         while (bp < fp) {
  88                                 c = *bp;
  89                                 *bp++ = *fp;
  90                                 *fp-- = c;
  91                         }
  92                         if ((tr2 = wcsdup(w2)) == NULL)
  93                                 goto fail;
  94                         bp = tr2;
  95                         fp = tr2 + wcslen(tr2) - 1;
  96                         while (bp < fp) {
  97                                 c = *bp;
  98                                 *bp++ = *fp;
  99                                 *fp-- = c;
 100                         }
 101                         w1 = tr1;
 102                         w2 = tr2;
 103                 }
 104 
 105                 if (direc & DIRECTIVE_POSITION) {
 106                         while ((*w1 || st1) && (*w2 || st2)) {
 107                                 pri1 = pri2 = 0;
 108                                 _collate_lookup(lcc, w1, &len1, &pri1, pass,
 109                                     &st1);
 110                                 if (pri1 <= 0) {
 111                                         if (pri1 < 0) {
 112                                                 errno = EINVAL;
 113                                                 goto fail;
 114                                         }
 115                                         pri1 = COLLATE_MAX_PRIORITY;
 116                                 }
 117                                 _collate_lookup(lcc, w2, &len2, &pri2, pass,
 118                                     &st2);
 119                                 if (pri2 <= 0) {
 120                                         if (pri2 < 0) {
 121                                                 errno = EINVAL;
 122                                                 goto fail;
 123                                         }
 124                                         pri2 = COLLATE_MAX_PRIORITY;
 125                                 }
 126                                 if (pri1 != pri2) {
 127                                         ret = pri1 - pri2;
 128                                         goto end;
 129                                 }
 130                                 w1 += len1;
 131                                 w2 += len2;
 132                         }
 133                 } else {
 134                         while ((*w1 || st1) && (*w2 || st2)) {
 135                                 pri1 = pri2 = 0;
 136                                 while (*w1) {
 137                                         _collate_lookup(lcc, w1, &len1,
 138                                             &pri1, pass, &st1);
 139                                         if (pri1 > 0)
 140                                                 break;
 141                                         if (pri1 < 0) {
 142                                                 errno = EINVAL;
 143                                                 goto fail;
 144                                         }
 145                                         w1 += len1;
 146                                 }
 147                                 while (*w2) {
 148                                         _collate_lookup(lcc, w2, &len2,
 149                                             &pri2, pass, &st2);
 150                                         if (pri2 > 0)
 151                                                 break;
 152                                         if (pri2 < 0) {
 153                                                 errno = EINVAL;
 154                                                 goto fail;
 155                                         }
 156                                         w2 += len2;
 157                                 }
 158                                 if (!pri1 || !pri2)
 159                                         break;
 160                                 if (pri1 != pri2) {
 161                                         ret = pri1 - pri2;
 162                                         goto end;
 163                                 }
 164                                 w1 += len1;
 165                                 w2 += len2;
 166                         }
 167                 }
 168                 if (!*w1) {


 171                                 goto end;
 172                         }
 173                 } else {
 174                         ret = *w1;
 175                         goto end;
 176                 }
 177         }
 178         ret = 0;
 179 
 180 end:
 181         if (tr1)
 182                 free(tr1);
 183         if (tr2)
 184                 free(tr2);
 185 
 186         return (ret);
 187 
 188 fail:
 189         ret = wcscmp(ws1, ws2);
 190         goto end;
 191 }
 192 
 193 
 194 int
 195 wcscoll(const wchar_t *ws1, const wchar_t *ws2)
 196 {
 197         return (wcscoll_l(ws1, ws2, uselocale(NULL)));
 198 }