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/strcoll.c
          +++ new/usr/src/lib/libc/port/locale/strcoll.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) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
   4    5   *              at Electronni Visti IA, Kiev, Ukraine.
   5    6   *                      All rights reserved.
   6    7   *
   7    8   * Redistribution and use in source and binary forms, with or without
   8    9   * modification, are permitted provided that the following conditions
   9   10   * are met:
  10   11   * 1. Redistributions of source code must retain the above copyright
  11   12   *    notice, this list of conditions and the following disclaimer.
↓ open down ↓ 14 lines elided ↑ open up ↑
  26   27   * SUCH DAMAGE.
  27   28   */
  28   29  
  29   30  #include "lint.h"
  30   31  #include "file64.h"
  31   32  #include <alloca.h>
  32   33  #include <stdlib.h>
  33   34  #include <string.h>
  34   35  #include <errno.h>
  35   36  #include <wchar.h>
       37 +#include <xlocale.h>
       38 +#include "localeimpl.h"
  36   39  #include "collate.h"
  37   40  
  38   41  #define ALLOCA_LIMIT    16
  39   42  
  40   43  /*
  41   44   * In order to properly handle multibyte locales, its easiet to just
  42   45   * convert to wide characters and then use wcscoll.  However if an
  43   46   * error occurs, we gracefully fall back to simple strcmp.  Caller
  44   47   * should check errno.
  45   48   */
  46   49  int
  47      -strcoll(const char *s1, const char *s2)
       50 +strcoll_l(const char *s1, const char *s2, locale_t loc)
  48   51  {
  49   52          int ret;
  50   53          wchar_t *t1 = NULL, *t2 = NULL;
  51   54          wchar_t *w1 = NULL, *w2 = NULL;
  52   55          size_t sz1, sz2;
       56 +        const struct lc_collate *lcc = loc->collate;
  53   57  
  54      -        if (_collate_load_error)
  55      -                goto error;
       58 +        mbstate_t mbs1 = { 0 }; /* initial states */
       59 +        mbstate_t mbs2 = { 0 };
  56   60  
       61 +        if (lcc->lc_is_posix)
       62 +                return (strcmp(s1, s2));
       63 +
  57   64          sz1 = strlen(s1) + 1;
  58   65          sz2 = strlen(s2) + 1;
  59   66  
  60   67          /*
  61   68           * Simple assumption: conversion to wide format is strictly
  62   69           * reducing, i.e. a single byte (or multibyte character)
  63   70           * cannot result in multiple wide characters.
  64   71           *
  65   72           * We gain a bit of performance by giving preference to alloca
  66   73           * for small string allocations.
↓ open down ↓ 8 lines elided ↑ open up ↑
  75   82          }
  76   83          if (sz2 > ALLOCA_LIMIT) {
  77   84                  if ((t2 = malloc(sz2 * sizeof (wchar_t))) == NULL)
  78   85                          goto error;
  79   86                  w2 = t2;
  80   87          } else {
  81   88                  if ((w2 = alloca(sz2 * sizeof (wchar_t))) == NULL)
  82   89                          goto error;
  83   90          }
  84   91  
  85      -        if ((mbstowcs(w1, s1, sz1)) == (size_t)-1)
       92 +        if ((mbsrtowcs_l(w1, &s1, sz1, &mbs1, loc)) == (size_t)-1)
  86   93                  goto error;
  87   94  
  88      -        if ((mbstowcs(w2, s2, sz2)) == (size_t)-1)
       95 +        if ((mbsrtowcs_l(w2, &s2, sz2, &mbs2, loc)) == (size_t)-1)
  89   96                  goto error;
  90   97  
  91      -        ret = wcscoll(w1, w2);
       98 +        ret = wcscoll_l(w1, w2, loc);
  92   99          if (t1)
  93  100                  free(t1);
  94  101          if (t2)
  95  102                  free(t2);
  96  103  
  97  104          return (ret);
  98  105  
  99  106  error:
 100  107          if (t1)
 101  108                  free(t1);
 102  109          if (t2)
 103  110                  free(t2);
 104  111          return (strcmp(s1, s2));
      112 +}
      113 +
      114 +int
      115 +strcoll(const char *s1, const char *s2)
      116 +{
      117 +        return (strcoll_l(s1, s2, uselocale(NULL)));
 105  118  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX