root/maint/gnulib/lib/mbmemcasecoll.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. apply_towlower
  2. apply_tolower
  3. mbmemcasecoll

   1 /* Locale-specific case-ignoring memory comparison.
   2    Copyright (C) 2001, 2009-2021 Free Software Foundation, Inc.
   3    Written by Bruno Haible <bruno@clisp.org>, 2001.
   4 
   5    This file is free software: you can redistribute it and/or modify
   6    it under the terms of the GNU General Public License as published
   7    by the Free Software Foundation; either version 3 of the License,
   8    or (at your option) any later version.
   9 
  10    This file is distributed in the hope that it will be useful,
  11    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13    GNU General Public License for more details.
  14 
  15    You should have received a copy of the GNU General Public License
  16    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  17 
  18 #include <config.h>
  19 
  20 /* Specification.  */
  21 #include "mbmemcasecoll.h"
  22 
  23 #include <errno.h>
  24 #include <stdlib.h>
  25 #include <string.h>
  26 
  27 /* Get tolower().  */
  28 #include <ctype.h>
  29 
  30 /* Get mbstate_t, mbrtowc(), wcrtomb().  */
  31 #include <wchar.h>
  32 
  33 /* Get towlower().  */
  34 #include <wctype.h>
  35 
  36 #include "malloca.h"
  37 #include "memcmp2.h"
  38 #include "memcoll.h"
  39 
  40 #define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
  41 
  42 /* Apply towlower() to the multibyte character sequence in INBUF, storing the
  43    result as a multibyte character sequence in OUTBUF.  */
  44 static size_t
  45 apply_towlower (const char *inbuf, size_t inbufsize,
     /* [previous][next][first][last][top][bottom][index][help] */
  46                 char *outbuf, size_t outbufsize)
  47 {
  48   char *outbuf_orig = outbuf;
  49   size_t remaining;
  50 
  51   remaining = inbufsize;
  52   while (remaining > 0)
  53     {
  54       wchar_t wc1;
  55       size_t n1;
  56       mbstate_t state;
  57 
  58       memset (&state, '\0', sizeof (mbstate_t));
  59       n1 = mbrtowc (&wc1, inbuf, remaining, &state);
  60       if (n1 == (size_t)(-2))
  61         break;
  62       if (n1 != (size_t)(-1))
  63         {
  64           wint_t wc2;
  65 
  66           if (n1 == 0) /* NUL character? */
  67             n1 = 1;
  68 
  69           wc2 = towlower (wc1);
  70           if (wc2 != wc1)
  71             {
  72               size_t n2;
  73 
  74               memset (&state, '\0', sizeof (mbstate_t));
  75               n2 = wcrtomb (outbuf, wc2, &state);
  76               if (n2 != (size_t)(-1))
  77                 {
  78                   /* Store the translated multibyte character.  */
  79                   inbuf += n1;
  80                   remaining -= n1;
  81                   outbuf += n2;
  82                   continue;
  83                 }
  84             }
  85 
  86           /* Nothing to translate. */
  87           memcpy (outbuf, inbuf, n1);
  88           inbuf += n1;
  89           remaining -= n1;
  90           outbuf += n1;
  91           continue;
  92         }
  93 
  94       /* Invalid multibyte character on input.
  95          Copy one byte without modification.  */
  96       *outbuf++ = *inbuf++;
  97       remaining -= 1;
  98     }
  99   /* Incomplete multibyte sequence on input.
 100      Pass it through unmodified.  */
 101   while (remaining > 0)
 102     {
 103       *outbuf++ = *inbuf++;
 104       remaining -= 1;
 105     }
 106 
 107   /* Verify the output buffer was large enough.  */
 108   if (outbuf - outbuf_orig > outbufsize)
 109     abort ();
 110 
 111   /* Return the number of written output bytes.  */
 112   return outbuf - outbuf_orig;
 113 }
 114 
 115 /* Apply tolower() to the unibyte character sequence in INBUF, storing the
 116    result as a unibyte character sequence in OUTBUF.  */
 117 static void
 118 apply_tolower (const char *inbuf, char *outbuf, size_t bufsize)
     /* [previous][next][first][last][top][bottom][index][help] */
 119 {
 120   for (; bufsize > 0; bufsize--)
 121     {
 122       *outbuf = TOLOWER ((unsigned char) *inbuf);
 123       inbuf++;
 124       outbuf++;
 125     }
 126 }
 127 
 128 int
 129 mbmemcasecoll (const char *s1, size_t s1len, const char *s2, size_t s2len,
     /* [previous][next][first][last][top][bottom][index][help] */
 130                bool hard_LC_COLLATE)
 131 {
 132   char *t1;
 133   size_t t1len;
 134   char *t2;
 135   size_t t2len;
 136   char *memory;
 137   int cmp;
 138 
 139   if (MB_CUR_MAX > 1)
 140     {
 141       /* Application of towlower grows each character by a factor 2
 142          at most.  */
 143       t1len = 2 * s1len;
 144       t2len = 2 * s2len;
 145     }
 146   else
 147     {
 148       /* Application of tolower doesn't change the size.  */
 149       t1len = s1len;
 150       t2len = s2len;
 151     }
 152   /* Allocate memory for t1 and t2.  */
 153   memory = (char *) malloca (t1len + 1 + t2len + 1);
 154   if (memory == NULL)
 155     {
 156       errno = ENOMEM;
 157       return 0;
 158     }
 159   t1 = memory;
 160   t2 = memory + t1len + 1;
 161 
 162   /* Csae-fold the two argument strings.  */
 163   if (MB_CUR_MAX > 1)
 164     {
 165       t1len = apply_towlower (s1, s1len, t1, t1len);
 166       t2len = apply_towlower (s2, s2len, t2, t2len);
 167     }
 168   else
 169     {
 170       apply_tolower (s1, t1, s1len);
 171       apply_tolower (s2, t2, s2len);
 172     }
 173 
 174   /* Compare the two case-folded strings.  */
 175   if (hard_LC_COLLATE)
 176     cmp = memcoll (t1, t1len, t2, t2len);
 177   else
 178     {
 179       cmp = memcmp2 (t1, t1len, t2, t2len);
 180       errno = 0;
 181     }
 182 
 183   {
 184     int saved_errno = errno;
 185     freea (memory);
 186     errno = saved_errno;
 187   }
 188 
 189   return cmp;
 190 }

/* [previous][next][first][last][top][bottom][index][help] */