blob: 24bcca93270a7f93cb763d8c0b40f7a68a52eaf4 [file] [log] [blame]
Kristian Monsen5ab50182010-05-14 18:53:44 +01001/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
Alex Deymo486467e2017-12-19 19:04:07 +01008 * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
Kristian Monsen5ab50182010-05-14 18:53:44 +01009 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
Alex Deymo8f1a2142016-06-28 14:49:26 -070012 * are also available at https://curl.haxx.se/docs/copyright.html.
Kristian Monsen5ab50182010-05-14 18:53:44 +010013 *
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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070023#include "curl_setup.h"
Kristian Monsen5ab50182010-05-14 18:53:44 +010024
Elliott Hughescee03382017-06-23 12:17:18 -070025#include <curl/curl.h>
26
27#include "strcase.h"
Kristian Monsen5ab50182010-05-14 18:53:44 +010028
29/* Portable, consistent toupper (remember EBCDIC). Do not use toupper() because
30 its behavior is altered by the current locale. */
31char Curl_raw_toupper(char in)
32{
Alex Deymo8f1a2142016-06-28 14:49:26 -070033#if !defined(CURL_DOES_CONVERSIONS)
34 if(in >= 'a' && in <= 'z')
35 return (char)('A' + in - 'a');
36#else
Elliott Hughes82be86d2017-09-20 17:00:17 -070037 switch(in) {
Kristian Monsen5ab50182010-05-14 18:53:44 +010038 case 'a':
39 return 'A';
40 case 'b':
41 return 'B';
42 case 'c':
43 return 'C';
44 case 'd':
45 return 'D';
46 case 'e':
47 return 'E';
48 case 'f':
49 return 'F';
50 case 'g':
51 return 'G';
52 case 'h':
53 return 'H';
54 case 'i':
55 return 'I';
56 case 'j':
57 return 'J';
58 case 'k':
59 return 'K';
60 case 'l':
61 return 'L';
62 case 'm':
63 return 'M';
64 case 'n':
65 return 'N';
66 case 'o':
67 return 'O';
68 case 'p':
69 return 'P';
70 case 'q':
71 return 'Q';
72 case 'r':
73 return 'R';
74 case 's':
75 return 'S';
76 case 't':
77 return 'T';
78 case 'u':
79 return 'U';
80 case 'v':
81 return 'V';
82 case 'w':
83 return 'W';
84 case 'x':
85 return 'X';
86 case 'y':
87 return 'Y';
88 case 'z':
89 return 'Z';
90 }
Alex Deymo8f1a2142016-06-28 14:49:26 -070091#endif
92
Kristian Monsen5ab50182010-05-14 18:53:44 +010093 return in;
94}
95
96/*
Alex Deymo486467e2017-12-19 19:04:07 +010097 * Curl_strcasecompare() is for doing "raw" case insensitive strings. This is
98 * meant to be locale independent and only compare strings we know are safe
99 * for this. See
100 * https://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for some
101 * further explanation to why this function is necessary.
Kristian Monsen5ab50182010-05-14 18:53:44 +0100102 *
103 * The function is capable of comparing a-z case insensitively even for
104 * non-ascii.
Elliott Hughescee03382017-06-23 12:17:18 -0700105 *
106 * @unittest: 1301
Kristian Monsen5ab50182010-05-14 18:53:44 +0100107 */
108
Elliott Hughescee03382017-06-23 12:17:18 -0700109int Curl_strcasecompare(const char *first, const char *second)
Kristian Monsen5ab50182010-05-14 18:53:44 +0100110{
111 while(*first && *second) {
112 if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second))
113 /* get out of the loop as soon as they don't match */
114 break;
115 first++;
116 second++;
117 }
118 /* we do the comparison here (possibly again), just to make sure that if the
119 loop above is skipped because one of the strings reached zero, we must not
120 return this as a successful match */
121 return (Curl_raw_toupper(*first) == Curl_raw_toupper(*second));
122}
123
Elliott Hughescee03382017-06-23 12:17:18 -0700124int Curl_safe_strcasecompare(const char *first, const char *second)
125{
126 if(first && second)
127 /* both pointers point to something then compare them */
128 return Curl_strcasecompare(first, second);
Elliott Hughes82be86d2017-09-20 17:00:17 -0700129
130 /* if both pointers are NULL then treat them as equal */
131 return (NULL == first && NULL == second);
Elliott Hughescee03382017-06-23 12:17:18 -0700132}
133
134/*
135 * @unittest: 1301
136 */
137int Curl_strncasecompare(const char *first, const char *second, size_t max)
Kristian Monsen5ab50182010-05-14 18:53:44 +0100138{
139 while(*first && *second && max) {
140 if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) {
141 break;
142 }
143 max--;
144 first++;
145 second++;
146 }
147 if(0 == max)
148 return 1; /* they are equal this far */
149
150 return Curl_raw_toupper(*first) == Curl_raw_toupper(*second);
151}
152
153/* Copy an upper case version of the string from src to dest. The
154 * strings may overlap. No more than n characters of the string are copied
155 * (including any NUL) and the destination string will NOT be
156 * NUL-terminated if that limit is reached.
157 */
158void Curl_strntoupper(char *dest, const char *src, size_t n)
159{
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700160 if(n < 1)
Kristian Monsen5ab50182010-05-14 18:53:44 +0100161 return;
162
163 do {
164 *dest++ = Curl_raw_toupper(*src);
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700165 } while(*src++ && --n);
Kristian Monsen5ab50182010-05-14 18:53:44 +0100166}
Elliott Hughescee03382017-06-23 12:17:18 -0700167
168/* --- public functions --- */
169
170int curl_strequal(const char *first, const char *second)
171{
172 return Curl_strcasecompare(first, second);
173}
174int curl_strnequal(const char *first, const char *second, size_t max)
175{
176 return Curl_strncasecompare(first, second, max);
177}