Blame lib/mbscasecmp.c

Packit 709fb3
/* Case-insensitive string comparison function.
Packit 709fb3
   Copyright (C) 1998-1999, 2005-2017 Free Software Foundation, Inc.
Packit 709fb3
   Written by Bruno Haible <bruno@clisp.org>, 2005,
Packit 709fb3
   based on earlier glibc code.
Packit 709fb3
Packit 709fb3
   This program is free software: you can redistribute it and/or modify
Packit 709fb3
   it under the terms of the GNU General Public License as published by
Packit 709fb3
   the Free Software Foundation; either version 3 of the License, or
Packit 709fb3
   (at your option) any later version.
Packit 709fb3
Packit 709fb3
   This program is distributed in the hope that it will be useful,
Packit 709fb3
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 709fb3
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 709fb3
   GNU General Public License for more details.
Packit 709fb3
Packit 709fb3
   You should have received a copy of the GNU General Public License
Packit 709fb3
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit 709fb3
Packit 709fb3
#include <config.h>
Packit 709fb3
Packit 709fb3
/* Specification.  */
Packit 709fb3
#include <string.h>
Packit 709fb3
Packit 709fb3
#include <ctype.h>
Packit 709fb3
#include <limits.h>
Packit 709fb3
Packit 709fb3
#include "mbuiter.h"
Packit 709fb3
Packit 709fb3
#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
Packit 709fb3
Packit 709fb3
/* Compare the character strings S1 and S2, ignoring case, returning less than,
Packit 709fb3
   equal to or greater than zero if S1 is lexicographically less than, equal to
Packit 709fb3
   or greater than S2.
Packit 709fb3
   Note: This function may, in multibyte locales, return 0 for strings of
Packit 709fb3
   different lengths!  */
Packit 709fb3
int
Packit 709fb3
mbscasecmp (const char *s1, const char *s2)
Packit 709fb3
{
Packit 709fb3
  if (s1 == s2)
Packit 709fb3
    return 0;
Packit 709fb3
Packit 709fb3
  /* Be careful not to look at the entire extent of s1 or s2 until needed.
Packit 709fb3
     This is useful because when two strings differ, the difference is
Packit 709fb3
     most often already in the very few first characters.  */
Packit 709fb3
  if (MB_CUR_MAX > 1)
Packit 709fb3
    {
Packit 709fb3
      mbui_iterator_t iter1;
Packit 709fb3
      mbui_iterator_t iter2;
Packit 709fb3
Packit 709fb3
      mbui_init (iter1, s1);
Packit 709fb3
      mbui_init (iter2, s2);
Packit 709fb3
Packit 709fb3
      while (mbui_avail (iter1) && mbui_avail (iter2))
Packit 709fb3
        {
Packit 709fb3
          int cmp = mb_casecmp (mbui_cur (iter1), mbui_cur (iter2));
Packit 709fb3
Packit 709fb3
          if (cmp != 0)
Packit 709fb3
            return cmp;
Packit 709fb3
Packit 709fb3
          mbui_advance (iter1);
Packit 709fb3
          mbui_advance (iter2);
Packit 709fb3
        }
Packit 709fb3
      if (mbui_avail (iter1))
Packit 709fb3
        /* s2 terminated before s1.  */
Packit 709fb3
        return 1;
Packit 709fb3
      if (mbui_avail (iter2))
Packit 709fb3
        /* s1 terminated before s2.  */
Packit 709fb3
        return -1;
Packit 709fb3
      return 0;
Packit 709fb3
    }
Packit 709fb3
  else
Packit 709fb3
    {
Packit 709fb3
      const unsigned char *p1 = (const unsigned char *) s1;
Packit 709fb3
      const unsigned char *p2 = (const unsigned char *) s2;
Packit 709fb3
      unsigned char c1, c2;
Packit 709fb3
Packit 709fb3
      do
Packit 709fb3
        {
Packit 709fb3
          c1 = TOLOWER (*p1);
Packit 709fb3
          c2 = TOLOWER (*p2);
Packit 709fb3
Packit 709fb3
          if (c1 == '\0')
Packit 709fb3
            break;
Packit 709fb3
Packit 709fb3
          ++p1;
Packit 709fb3
          ++p2;
Packit 709fb3
        }
Packit 709fb3
      while (c1 == c2);
Packit 709fb3
Packit 709fb3
      if (UCHAR_MAX <= INT_MAX)
Packit 709fb3
        return c1 - c2;
Packit 709fb3
      else
Packit 709fb3
        /* On machines where 'char' and 'int' are types of the same size, the
Packit 709fb3
           difference of two 'unsigned char' values - including the sign bit -
Packit 709fb3
           doesn't fit in an 'int'.  */
Packit 709fb3
        return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
Packit 709fb3
    }
Packit 709fb3
}