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

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/libc/port/locale/wcscoll.c
          +++ new/usr/src/lib/libc/port/locale/wcscoll.c
   1    1  /*
        2 + * Copyright 2013 Garrett D'Amore <garrett@damore.org>
   2    3   * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
   3    4   * Copyright (c) 2002 Tim J. Robbins
   4    5   * All rights reserved.
   5    6   *
   6    7   * Redistribution and use in source and binary forms, with or without
   7    8   * modification, are permitted provided that the following conditions
   8    9   * are met:
   9   10   * 1. Redistributions of source code must retain the above copyright
  10   11   *    notice, this list of conditions and the following disclaimer.
  11   12   * 2. Redistributions in binary form must reproduce the above copyright
↓ open down ↓ 13 lines elided ↑ open up ↑
  25   26   * SUCH DAMAGE.
  26   27   */
  27   28  
  28   29  #include "lint.h"
  29   30  #include <errno.h>
  30   31  #include <stdlib.h>
  31   32  #include <string.h>
  32   33  #include <wchar.h>
  33   34  #include <assert.h>
  34   35  #include "collate.h"
       36 +#include "localeimpl.h"
  35   37  
  36   38  int
  37      -wcscoll(const wchar_t *ws1, const wchar_t *ws2)
       39 +wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t loc)
  38   40  {
  39   41          int len1, len2, pri1, pri2, ret;
  40   42          wchar_t *tr1 = NULL, *tr2 = NULL;
  41   43          int direc, pass;
       44 +        const struct lc_collate *lcc = loc->collate;
  42   45  
  43      -        collate_info_t *info = _collate_info;
  44      -
  45      -        if (_collate_load_error)
       46 +        if (lcc->lc_is_posix)
  46   47                  /*
  47   48                   * Locale has no special collating order or could not be
  48   49                   * loaded, do a fast binary comparison.
  49   50                   */
  50   51                  return (wcscmp(ws1, ws2));
  51   52  
  52   53          ret = 0;
  53   54  
  54   55          /*
  55   56           * Once upon a time we had code to try to optimize this, but
  56   57           * it turns out that you really can't make many assumptions
  57   58           * safely.  You absolutely have to run this pass by pass,
  58   59           * because some passes will be ignored for a given character,
  59   60           * while others will not.  Simpler locales will benefit from
  60   61           * having fewer passes, and most comparisions should resolve
  61   62           * during the primary pass anyway.
  62   63           *
  63   64           * Note that we do one final extra pass at the end to pick
  64   65           * up UNDEFINED elements.  There is special handling for them.
  65   66           */
  66      -        for (pass = 0; pass <= info->directive_count; pass++) {
       67 +        for (pass = 0; pass <= lcc->lc_directive_count; pass++) {
  67   68  
  68      -                int32_t *st1 = NULL;
  69      -                int32_t *st2 = NULL;
       69 +                const int32_t *st1 = NULL;
       70 +                const int32_t *st2 = NULL;
  70   71                  const wchar_t   *w1 = ws1;
  71   72                  const wchar_t   *w2 = ws2;
  72   73  
  73   74                  /* special pass for UNDEFINED */
  74      -                if (pass == info->directive_count) {
       75 +                if (pass == lcc->lc_directive_count) {
  75   76                          direc = DIRECTIVE_FORWARD | DIRECTIVE_UNDEFINED;
  76   77                  } else {
  77      -                        direc = info->directive[pass];
       78 +                        direc = lcc->lc_directive[pass];
  78   79                  }
  79   80  
  80   81                  if (direc & DIRECTIVE_BACKWARD) {
  81   82                          wchar_t *bp, *fp, c;
  82   83                          if ((tr1 = wcsdup(w1)) == NULL)
  83   84                                  goto fail;
  84   85                          bp = tr1;
  85   86                          fp = tr1 + wcslen(tr1) - 1;
  86   87                          while (bp < fp) {
  87   88                                  c = *bp;
↓ open down ↓ 9 lines elided ↑ open up ↑
  97   98                                  *bp++ = *fp;
  98   99                                  *fp-- = c;
  99  100                          }
 100  101                          w1 = tr1;
 101  102                          w2 = tr2;
 102  103                  }
 103  104  
 104  105                  if (direc & DIRECTIVE_POSITION) {
 105  106                          while ((*w1 || st1) && (*w2 || st2)) {
 106  107                                  pri1 = pri2 = 0;
 107      -                                _collate_lookup(w1, &len1, &pri1, pass, &st1);
      108 +                                _collate_lookup(lcc, w1, &len1, &pri1, pass,
      109 +                                    &st1);
 108  110                                  if (pri1 <= 0) {
 109  111                                          if (pri1 < 0) {
 110  112                                                  errno = EINVAL;
 111  113                                                  goto fail;
 112  114                                          }
 113  115                                          pri1 = COLLATE_MAX_PRIORITY;
 114  116                                  }
 115      -                                _collate_lookup(w2, &len2, &pri2, pass, &st2);
      117 +                                _collate_lookup(lcc, w2, &len2, &pri2, pass,
      118 +                                    &st2);
 116  119                                  if (pri2 <= 0) {
 117  120                                          if (pri2 < 0) {
 118  121                                                  errno = EINVAL;
 119  122                                                  goto fail;
 120  123                                          }
 121  124                                          pri2 = COLLATE_MAX_PRIORITY;
 122  125                                  }
 123  126                                  if (pri1 != pri2) {
 124  127                                          ret = pri1 - pri2;
 125  128                                          goto end;
 126  129                                  }
 127  130                                  w1 += len1;
 128  131                                  w2 += len2;
 129  132                          }
 130  133                  } else {
 131  134                          while ((*w1 || st1) && (*w2 || st2)) {
 132  135                                  pri1 = pri2 = 0;
 133  136                                  while (*w1) {
 134      -                                        _collate_lookup(w1, &len1,
      137 +                                        _collate_lookup(lcc, w1, &len1,
 135  138                                              &pri1, pass, &st1);
 136  139                                          if (pri1 > 0)
 137  140                                                  break;
 138  141                                          if (pri1 < 0) {
 139  142                                                  errno = EINVAL;
 140  143                                                  goto fail;
 141  144                                          }
 142  145                                          w1 += len1;
 143  146                                  }
 144  147                                  while (*w2) {
 145      -                                        _collate_lookup(w2, &len2,
      148 +                                        _collate_lookup(lcc, w2, &len2,
 146  149                                              &pri2, pass, &st2);
 147  150                                          if (pri2 > 0)
 148  151                                                  break;
 149  152                                          if (pri2 < 0) {
 150  153                                                  errno = EINVAL;
 151  154                                                  goto fail;
 152  155                                          }
 153  156                                          w2 += len2;
 154  157                                  }
 155  158                                  if (!pri1 || !pri2)
↓ open down ↓ 22 lines elided ↑ open up ↑
 178  181          if (tr1)
 179  182                  free(tr1);
 180  183          if (tr2)
 181  184                  free(tr2);
 182  185  
 183  186          return (ret);
 184  187  
 185  188  fail:
 186  189          ret = wcscmp(ws1, ws2);
 187  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)));
 188  198  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX