summaryrefslogtreecommitdiff
path: root/lib/memcoll.c
blob: 65cb57676e475dd440480d3e2116fbb922dacbf7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/* Locale-specific memory comparison.
   Copyright 1999 Free Software Foundation, Inc.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software Foundation,
   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */

/* Contributed by Paul Eggert <eggert@twinsun.com>.  */

#if HAVE_CONFIG_H
# include <config.h>
#endif

#include <sys/types.h>

#if HAVE_STRING_H
# include <string.h>
#endif

/* Compare S1 (with length S1LEN) and S2 (with length S2LEN) according
   to the LC_COLLATE locale.  S1 and S2 do not overlap, and are not
   adjacent.  Temporarily modify the bytes after S1 and S2, but
   restore their original contents before returning.  */
int
memcoll (char *s1, size_t s1len, char *s2, size_t s2len)
{
  int diff;
  char n1 = s1[s1len];
  char n2 = s2[s2len];

  s1[s1len++] = '\0';
  s2[s2len++] = '\0';

  while (! (diff = strcoll (s1, s2)))
    {
      /* strcoll found no difference, but perhaps it was fooled by NUL
	 characters in the data.  Work around this problem by advancing
	 past the NUL chars.  */
      size_t size1 = strlen (s1) + 1;
      size_t size2 = strlen (s2) + 1;
      s1 += size1;
      s2 += size2;
      s1len -= size1;
      s2len -= size2;

      if (s1len == 0)
	{
	  if (s2len != 0)
	    diff = -1;
	  break;
	}
      else if (s2len == 0)
	{
	  diff = 1;
	  break;
	}
    }

  s1[s1len - 1] = n1;
  s2[s2len - 1] = n2;

  return diff;
}