1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at http://curl.haxx.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22 
23 /* These functions are borrowed from libcurl's lib/rawstr.c with minor
24  * modifications to style and naming. Curl_raw_equal and Curl_raw_nequal are
25  * further modified to be true cmp style functions, returning negative, zero,
26  * or positive. */
27 
28 #include <stdlib.h>
29 
30 #include "util.h"
31 
32 /* Portable, consistent toupper (remember EBCDIC). Do not use toupper() because
33 	 its behavior is altered by the current locale. */
raw_toupper(char in)34 static char raw_toupper(char in)
35 {
36 	switch(in) {
37 	case 'a':
38 		return 'A';
39 	case 'b':
40 		return 'B';
41 	case 'c':
42 		return 'C';
43 	case 'd':
44 		return 'D';
45 	case 'e':
46 		return 'E';
47 	case 'f':
48 		return 'F';
49 	case 'g':
50 		return 'G';
51 	case 'h':
52 		return 'H';
53 	case 'i':
54 		return 'I';
55 	case 'j':
56 		return 'J';
57 	case 'k':
58 		return 'K';
59 	case 'l':
60 		return 'L';
61 	case 'm':
62 		return 'M';
63 	case 'n':
64 		return 'N';
65 	case 'o':
66 		return 'O';
67 	case 'p':
68 		return 'P';
69 	case 'q':
70 		return 'Q';
71 	case 'r':
72 		return 'R';
73 	case 's':
74 		return 'S';
75 	case 't':
76 		return 'T';
77 	case 'u':
78 		return 'U';
79 	case 'v':
80 		return 'V';
81 	case 'w':
82 		return 'W';
83 	case 'x':
84 		return 'X';
85 	case 'y':
86 		return 'Y';
87 	case 'z':
88 		return 'Z';
89 	}
90 	return in;
91 }
92 
93 /*
94  * _alpm_raw_cmp() is for doing "raw" case insensitive strings. This is meant
95  * to be locale independent and only compare strings we know are safe for
96  * this.  See http://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for
97  * some further explanation to why this function is necessary.
98  *
99  * The function is capable of comparing a-z case insensitively even for
100  * non-ascii.
101  */
102 
_alpm_raw_cmp(const char * first,const char * second)103 int _alpm_raw_cmp(const char *first, const char *second)
104 {
105 	while(*first && *second) {
106 		if(raw_toupper(*first) != raw_toupper(*second)) {
107 			/* get out of the loop as soon as they don't match */
108 			break;
109 		}
110 		first++;
111 		second++;
112 	}
113 	/* we do the comparison here (possibly again), just to make sure that if the
114 		 loop above is skipped because one of the strings reached zero, we must not
115 		 return this as a successful match */
116 	return (raw_toupper(*first) - raw_toupper(*second));
117 }
118 
_alpm_raw_ncmp(const char * first,const char * second,size_t max)119 int _alpm_raw_ncmp(const char *first, const char *second, size_t max)
120 {
121 	while(*first && *second && max) {
122 		if(raw_toupper(*first) != raw_toupper(*second)) {
123 			break;
124 		}
125 		max--;
126 		first++;
127 		second++;
128 	}
129 	if(0 == max) {
130 		/* they are equal this far */
131 		return 0;
132 	}
133 
134 	return (raw_toupper(*first) - raw_toupper(*second));
135 }
136