198038Sache/* Locale-specific memory comparison. 2133543Stjr Copyright (C) 1999, 2002, 2003, 2004 Free Software Foundation, Inc. 398038Sache 498038Sache This program is free software; you can redistribute it and/or modify 598038Sache it under the terms of the GNU General Public License as published by 698038Sache the Free Software Foundation; either version 2, or (at your option) 798038Sache any later version. 898038Sache 998038Sache This program is distributed in the hope that it will be useful, 1098038Sache but WITHOUT ANY WARRANTY; without even the implied warranty of 1198038Sache MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1298038Sache GNU General Public License for more details. 1398038Sache 1498038Sache You should have received a copy of the GNU General Public License 1598038Sache along with this program; if not, write to the Free Software Foundation, 1698038Sache Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 1798038Sache 1898038Sache/* Contributed by Paul Eggert <eggert@twinsun.com>. */ 1998038Sache 2098038Sache#if HAVE_CONFIG_H 2198038Sache# include <config.h> 2298038Sache#endif 2398038Sache 24131447Stjr#include "memcoll.h" 25131447Stjr 2698038Sache#include <errno.h> 27131447Stjr#include <string.h> 2898038Sache 2998038Sache/* Compare S1 (with length S1LEN) and S2 (with length S2LEN) according 3098038Sache to the LC_COLLATE locale. S1 and S2 do not overlap, and are not 31131447Stjr adjacent. Perhaps temporarily modify the bytes after S1 and S2, 32131447Stjr but restore their original contents before returning. Set errno to an 3398038Sache error number if there is an error, and to zero otherwise. */ 3498038Sacheint 3598038Sachememcoll (char *s1, size_t s1len, char *s2, size_t s2len) 3698038Sache{ 3798038Sache int diff; 38131447Stjr 39131447Stjr#if HAVE_STRCOLL 40131447Stjr 4198038Sache char n1 = s1[s1len]; 4298038Sache char n2 = s2[s2len]; 4398038Sache 4498038Sache s1[s1len++] = '\0'; 4598038Sache s2[s2len++] = '\0'; 4698038Sache 4798038Sache while (! (errno = 0, (diff = strcoll (s1, s2)) || errno)) 4898038Sache { 4998038Sache /* strcoll found no difference, but perhaps it was fooled by NUL 5098038Sache characters in the data. Work around this problem by advancing 5198038Sache past the NUL chars. */ 5298038Sache size_t size1 = strlen (s1) + 1; 5398038Sache size_t size2 = strlen (s2) + 1; 5498038Sache s1 += size1; 5598038Sache s2 += size2; 5698038Sache s1len -= size1; 5798038Sache s2len -= size2; 5898038Sache 5998038Sache if (s1len == 0) 6098038Sache { 6198038Sache if (s2len != 0) 6298038Sache diff = -1; 6398038Sache break; 6498038Sache } 6598038Sache else if (s2len == 0) 6698038Sache { 6798038Sache diff = 1; 6898038Sache break; 6998038Sache } 7098038Sache } 7198038Sache 7298038Sache s1[s1len - 1] = n1; 7398038Sache s2[s2len - 1] = n2; 7498038Sache 75131447Stjr#else 76131447Stjr 77131447Stjr diff = memcmp (s1, s2, s1len < s2len ? s1len : s2len); 78131447Stjr if (! diff) 79131447Stjr diff = s1len < s2len ? -1 : s1len != s2len; 80131447Stjr errno = 0; 81131447Stjr 82131447Stjr#endif 83131447Stjr 8498038Sache return diff; 8598038Sache} 86