root/maint/gnulib/lib/mbmemcasecmp.c

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

DEFINITIONS

This source file includes following definitions.
  1. mbmemcasecmp

   1 /* Compare two memory areas with possibly different lengths, case-insensitive.
   2    Copyright (C) 1998-1999, 2005-2021 Free Software Foundation, Inc.
   3    Written by Bruno Haible <bruno@clisp.org>, 2009,
   4    based on earlier glibc code.
   5 
   6    This file is free software: you can redistribute it and/or modify
   7    it under the terms of the GNU Lesser General Public License as
   8    published by the Free Software Foundation; either version 3 of the
   9    License, or (at your option) any later version.
  10 
  11    This file is distributed in the hope that it will be useful,
  12    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14    GNU Lesser General Public License for more details.
  15 
  16    You should have received a copy of the GNU Lesser General Public License
  17    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  18 
  19 #include <config.h>
  20 
  21 /* Specification.  */
  22 #include "mbmemcasecmp.h"
  23 
  24 #include <ctype.h>
  25 #include <limits.h>
  26 #include <stdlib.h>
  27 
  28 #include "mbiter.h"
  29 
  30 #define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
  31 
  32 int
  33 mbmemcasecmp (const char *s1, size_t n1, const char *s2, size_t n2)
     /* [previous][next][first][last][top][bottom][index][help] */
  34 {
  35   if (s1 == s2)
  36     return _GL_CMP (n1, n2);
  37 
  38   if (MB_CUR_MAX > 1)
  39     {
  40       mbi_iterator_t iter1;
  41       mbi_iterator_t iter2;
  42 
  43       mbi_init (iter1, s1, n1);
  44       mbi_init (iter2, s2, n2);
  45 
  46       while (mbi_avail (iter1) && mbi_avail (iter2))
  47         {
  48           int cmp = mb_casecmp (mbi_cur (iter1), mbi_cur (iter2));
  49 
  50           if (cmp != 0)
  51             return cmp;
  52 
  53           mbi_advance (iter1);
  54           mbi_advance (iter2);
  55         }
  56       if (mbi_avail (iter1))
  57         /* s2 terminated before s1.  */
  58         return 1;
  59       if (mbi_avail (iter2))
  60         /* s1 terminated before s2.  */
  61         return -1;
  62       return 0;
  63     }
  64   else
  65     {
  66       const unsigned char *s1_end = (const unsigned char *) (s1 + n1);
  67       const unsigned char *s2_end = (const unsigned char *) (s2 + n2);
  68       const unsigned char *p1 = (const unsigned char *) s1;
  69       const unsigned char *p2 = (const unsigned char *) s2;
  70 
  71       while (p1 < s1_end && p2 < s2_end)
  72         {
  73           unsigned char c1 = TOLOWER (*p1);
  74           unsigned char c2 = TOLOWER (*p2);
  75           if (c1 != c2)
  76             {
  77               if (UCHAR_MAX <= INT_MAX)
  78                 return c1 - c2;
  79               else
  80                 /* On machines where 'char' and 'int' are types of the same
  81                    size, the difference of two 'unsigned char' values
  82                    - including the sign bit - doesn't fit in an 'int'.  */
  83                 return _GL_CMP (c1, c2);
  84             }
  85           ++p1;
  86           ++p2;
  87         }
  88       if (p1 < s1_end)
  89         /* s2 terminated before s1.  */
  90         return 1;
  91       if (p2 < s2_end)
  92         /* s1 terminated before s2.  */
  93         return -1;
  94       return 0;
  95     }
  96 }

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