1 // Copyright 2017 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "absl/strings/ascii.h"
16
17 #include <cctype>
18 #include <clocale>
19 #include <cstring>
20 #include <string>
21
22 #include "gtest/gtest.h"
23 #include "absl/base/macros.h"
24 #include "absl/base/port.h"
25
26 namespace {
27
TEST(AsciiIsFoo,All)28 TEST(AsciiIsFoo, All) {
29 for (int i = 0; i < 256; i++) {
30 if ((i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z'))
31 EXPECT_TRUE(absl::ascii_isalpha(i)) << ": failed on " << i;
32 else
33 EXPECT_TRUE(!absl::ascii_isalpha(i)) << ": failed on " << i;
34 }
35 for (int i = 0; i < 256; i++) {
36 if ((i >= '0' && i <= '9'))
37 EXPECT_TRUE(absl::ascii_isdigit(i)) << ": failed on " << i;
38 else
39 EXPECT_TRUE(!absl::ascii_isdigit(i)) << ": failed on " << i;
40 }
41 for (int i = 0; i < 256; i++) {
42 if (absl::ascii_isalpha(i) || absl::ascii_isdigit(i))
43 EXPECT_TRUE(absl::ascii_isalnum(i)) << ": failed on " << i;
44 else
45 EXPECT_TRUE(!absl::ascii_isalnum(i)) << ": failed on " << i;
46 }
47 for (int i = 0; i < 256; i++) {
48 if (i != '\0' && strchr(" \r\n\t\v\f", i))
49 EXPECT_TRUE(absl::ascii_isspace(i)) << ": failed on " << i;
50 else
51 EXPECT_TRUE(!absl::ascii_isspace(i)) << ": failed on " << i;
52 }
53 for (int i = 0; i < 256; i++) {
54 if (i >= 32 && i < 127)
55 EXPECT_TRUE(absl::ascii_isprint(i)) << ": failed on " << i;
56 else
57 EXPECT_TRUE(!absl::ascii_isprint(i)) << ": failed on " << i;
58 }
59 for (int i = 0; i < 256; i++) {
60 if (absl::ascii_isprint(i) && !absl::ascii_isspace(i) &&
61 !absl::ascii_isalnum(i))
62 EXPECT_TRUE(absl::ascii_ispunct(i)) << ": failed on " << i;
63 else
64 EXPECT_TRUE(!absl::ascii_ispunct(i)) << ": failed on " << i;
65 }
66 for (int i = 0; i < 256; i++) {
67 if (i == ' ' || i == '\t')
68 EXPECT_TRUE(absl::ascii_isblank(i)) << ": failed on " << i;
69 else
70 EXPECT_TRUE(!absl::ascii_isblank(i)) << ": failed on " << i;
71 }
72 for (int i = 0; i < 256; i++) {
73 if (i < 32 || i == 127)
74 EXPECT_TRUE(absl::ascii_iscntrl(i)) << ": failed on " << i;
75 else
76 EXPECT_TRUE(!absl::ascii_iscntrl(i)) << ": failed on " << i;
77 }
78 for (int i = 0; i < 256; i++) {
79 if (absl::ascii_isdigit(i) || (i >= 'A' && i <= 'F') ||
80 (i >= 'a' && i <= 'f'))
81 EXPECT_TRUE(absl::ascii_isxdigit(i)) << ": failed on " << i;
82 else
83 EXPECT_TRUE(!absl::ascii_isxdigit(i)) << ": failed on " << i;
84 }
85 for (int i = 0; i < 256; i++) {
86 if (i > 32 && i < 127)
87 EXPECT_TRUE(absl::ascii_isgraph(i)) << ": failed on " << i;
88 else
89 EXPECT_TRUE(!absl::ascii_isgraph(i)) << ": failed on " << i;
90 }
91 for (int i = 0; i < 256; i++) {
92 if (i >= 'A' && i <= 'Z')
93 EXPECT_TRUE(absl::ascii_isupper(i)) << ": failed on " << i;
94 else
95 EXPECT_TRUE(!absl::ascii_isupper(i)) << ": failed on " << i;
96 }
97 for (int i = 0; i < 256; i++) {
98 if (i >= 'a' && i <= 'z')
99 EXPECT_TRUE(absl::ascii_islower(i)) << ": failed on " << i;
100 else
101 EXPECT_TRUE(!absl::ascii_islower(i)) << ": failed on " << i;
102 }
103 for (int i = 0; i < 128; i++) {
104 EXPECT_TRUE(absl::ascii_isascii(i)) << ": failed on " << i;
105 }
106 for (int i = 128; i < 256; i++) {
107 EXPECT_TRUE(!absl::ascii_isascii(i)) << ": failed on " << i;
108 }
109
110 // The official is* functions don't accept negative signed chars, but
111 // our absl::ascii_is* functions do.
112 for (int i = 0; i < 256; i++) {
113 signed char sc = static_cast<signed char>(static_cast<unsigned char>(i));
114 EXPECT_EQ(absl::ascii_isalpha(i), absl::ascii_isalpha(sc)) << i;
115 EXPECT_EQ(absl::ascii_isdigit(i), absl::ascii_isdigit(sc)) << i;
116 EXPECT_EQ(absl::ascii_isalnum(i), absl::ascii_isalnum(sc)) << i;
117 EXPECT_EQ(absl::ascii_isspace(i), absl::ascii_isspace(sc)) << i;
118 EXPECT_EQ(absl::ascii_ispunct(i), absl::ascii_ispunct(sc)) << i;
119 EXPECT_EQ(absl::ascii_isblank(i), absl::ascii_isblank(sc)) << i;
120 EXPECT_EQ(absl::ascii_iscntrl(i), absl::ascii_iscntrl(sc)) << i;
121 EXPECT_EQ(absl::ascii_isxdigit(i), absl::ascii_isxdigit(sc)) << i;
122 EXPECT_EQ(absl::ascii_isprint(i), absl::ascii_isprint(sc)) << i;
123 EXPECT_EQ(absl::ascii_isgraph(i), absl::ascii_isgraph(sc)) << i;
124 EXPECT_EQ(absl::ascii_isupper(i), absl::ascii_isupper(sc)) << i;
125 EXPECT_EQ(absl::ascii_islower(i), absl::ascii_islower(sc)) << i;
126 EXPECT_EQ(absl::ascii_isascii(i), absl::ascii_isascii(sc)) << i;
127 }
128 }
129
130 // Checks that absl::ascii_isfoo returns the same value as isfoo in the C
131 // locale.
TEST(AsciiIsFoo,SameAsIsFoo)132 TEST(AsciiIsFoo, SameAsIsFoo) {
133 #ifndef __ANDROID__
134 // temporarily change locale to C. It should already be C, but just for safety
135 const char* old_locale = setlocale(LC_CTYPE, "C");
136 ASSERT_TRUE(old_locale != nullptr);
137 #endif
138
139 for (int i = 0; i < 256; i++) {
140 EXPECT_EQ(isalpha(i) != 0, absl::ascii_isalpha(i)) << i;
141 EXPECT_EQ(isdigit(i) != 0, absl::ascii_isdigit(i)) << i;
142 EXPECT_EQ(isalnum(i) != 0, absl::ascii_isalnum(i)) << i;
143 EXPECT_EQ(isspace(i) != 0, absl::ascii_isspace(i)) << i;
144 EXPECT_EQ(ispunct(i) != 0, absl::ascii_ispunct(i)) << i;
145 EXPECT_EQ(isblank(i) != 0, absl::ascii_isblank(i)) << i;
146 EXPECT_EQ(iscntrl(i) != 0, absl::ascii_iscntrl(i)) << i;
147 EXPECT_EQ(isxdigit(i) != 0, absl::ascii_isxdigit(i)) << i;
148 EXPECT_EQ(isprint(i) != 0, absl::ascii_isprint(i)) << i;
149 EXPECT_EQ(isgraph(i) != 0, absl::ascii_isgraph(i)) << i;
150 EXPECT_EQ(isupper(i) != 0, absl::ascii_isupper(i)) << i;
151 EXPECT_EQ(islower(i) != 0, absl::ascii_islower(i)) << i;
152 EXPECT_EQ(isascii(i) != 0, absl::ascii_isascii(i)) << i;
153 }
154
155 #ifndef __ANDROID__
156 // restore the old locale.
157 ASSERT_TRUE(setlocale(LC_CTYPE, old_locale));
158 #endif
159 }
160
TEST(AsciiToFoo,All)161 TEST(AsciiToFoo, All) {
162 #ifndef __ANDROID__
163 // temporarily change locale to C. It should already be C, but just for safety
164 const char* old_locale = setlocale(LC_CTYPE, "C");
165 ASSERT_TRUE(old_locale != nullptr);
166 #endif
167
168 for (int i = 0; i < 256; i++) {
169 if (absl::ascii_islower(i))
170 EXPECT_EQ(absl::ascii_toupper(i), 'A' + (i - 'a')) << i;
171 else
172 EXPECT_EQ(absl::ascii_toupper(i), static_cast<char>(i)) << i;
173
174 if (absl::ascii_isupper(i))
175 EXPECT_EQ(absl::ascii_tolower(i), 'a' + (i - 'A')) << i;
176 else
177 EXPECT_EQ(absl::ascii_tolower(i), static_cast<char>(i)) << i;
178
179 // These CHECKs only hold in a C locale.
180 EXPECT_EQ(static_cast<char>(tolower(i)), absl::ascii_tolower(i)) << i;
181 EXPECT_EQ(static_cast<char>(toupper(i)), absl::ascii_toupper(i)) << i;
182
183 // The official to* functions don't accept negative signed chars, but
184 // our absl::ascii_to* functions do.
185 signed char sc = static_cast<signed char>(static_cast<unsigned char>(i));
186 EXPECT_EQ(absl::ascii_tolower(i), absl::ascii_tolower(sc)) << i;
187 EXPECT_EQ(absl::ascii_toupper(i), absl::ascii_toupper(sc)) << i;
188 }
189 #ifndef __ANDROID__
190 // restore the old locale.
191 ASSERT_TRUE(setlocale(LC_CTYPE, old_locale));
192 #endif
193 }
194
TEST(AsciiStrTo,Lower)195 TEST(AsciiStrTo, Lower) {
196 const char buf[] = "ABCDEF";
197 const std::string str("GHIJKL");
198 const std::string str2("MNOPQR");
199 const absl::string_view sp(str2);
200
201 EXPECT_EQ("abcdef", absl::AsciiStrToLower(buf));
202 EXPECT_EQ("ghijkl", absl::AsciiStrToLower(str));
203 EXPECT_EQ("mnopqr", absl::AsciiStrToLower(sp));
204
205 char mutable_buf[] = "Mutable";
206 std::transform(mutable_buf, mutable_buf + strlen(mutable_buf),
207 mutable_buf, absl::ascii_tolower);
208 EXPECT_STREQ("mutable", mutable_buf);
209 }
210
TEST(AsciiStrTo,Upper)211 TEST(AsciiStrTo, Upper) {
212 const char buf[] = "abcdef";
213 const std::string str("ghijkl");
214 const std::string str2("mnopqr");
215 const absl::string_view sp(str2);
216
217 EXPECT_EQ("ABCDEF", absl::AsciiStrToUpper(buf));
218 EXPECT_EQ("GHIJKL", absl::AsciiStrToUpper(str));
219 EXPECT_EQ("MNOPQR", absl::AsciiStrToUpper(sp));
220
221 char mutable_buf[] = "Mutable";
222 std::transform(mutable_buf, mutable_buf + strlen(mutable_buf),
223 mutable_buf, absl::ascii_toupper);
224 EXPECT_STREQ("MUTABLE", mutable_buf);
225 }
226
TEST(StripLeadingAsciiWhitespace,FromStringView)227 TEST(StripLeadingAsciiWhitespace, FromStringView) {
228 EXPECT_EQ(absl::string_view{},
229 absl::StripLeadingAsciiWhitespace(absl::string_view{}));
230 EXPECT_EQ("foo", absl::StripLeadingAsciiWhitespace({"foo"}));
231 EXPECT_EQ("foo", absl::StripLeadingAsciiWhitespace({"\t \n\f\r\n\vfoo"}));
232 EXPECT_EQ("foo foo\n ",
233 absl::StripLeadingAsciiWhitespace({"\t \n\f\r\n\vfoo foo\n "}));
234 EXPECT_EQ(absl::string_view{}, absl::StripLeadingAsciiWhitespace(
235 {"\t \n\f\r\v\n\t \n\f\r\v\n"}));
236 }
237
TEST(StripLeadingAsciiWhitespace,InPlace)238 TEST(StripLeadingAsciiWhitespace, InPlace) {
239 std::string str;
240
241 absl::StripLeadingAsciiWhitespace(&str);
242 EXPECT_EQ("", str);
243
244 str = "foo";
245 absl::StripLeadingAsciiWhitespace(&str);
246 EXPECT_EQ("foo", str);
247
248 str = "\t \n\f\r\n\vfoo";
249 absl::StripLeadingAsciiWhitespace(&str);
250 EXPECT_EQ("foo", str);
251
252 str = "\t \n\f\r\n\vfoo foo\n ";
253 absl::StripLeadingAsciiWhitespace(&str);
254 EXPECT_EQ("foo foo\n ", str);
255
256 str = "\t \n\f\r\v\n\t \n\f\r\v\n";
257 absl::StripLeadingAsciiWhitespace(&str);
258 EXPECT_EQ(absl::string_view{}, str);
259 }
260
TEST(StripTrailingAsciiWhitespace,FromStringView)261 TEST(StripTrailingAsciiWhitespace, FromStringView) {
262 EXPECT_EQ(absl::string_view{},
263 absl::StripTrailingAsciiWhitespace(absl::string_view{}));
264 EXPECT_EQ("foo", absl::StripTrailingAsciiWhitespace({"foo"}));
265 EXPECT_EQ("foo", absl::StripTrailingAsciiWhitespace({"foo\t \n\f\r\n\v"}));
266 EXPECT_EQ(" \nfoo foo",
267 absl::StripTrailingAsciiWhitespace({" \nfoo foo\t \n\f\r\n\v"}));
268 EXPECT_EQ(absl::string_view{}, absl::StripTrailingAsciiWhitespace(
269 {"\t \n\f\r\v\n\t \n\f\r\v\n"}));
270 }
271
TEST(StripTrailingAsciiWhitespace,InPlace)272 TEST(StripTrailingAsciiWhitespace, InPlace) {
273 std::string str;
274
275 absl::StripTrailingAsciiWhitespace(&str);
276 EXPECT_EQ("", str);
277
278 str = "foo";
279 absl::StripTrailingAsciiWhitespace(&str);
280 EXPECT_EQ("foo", str);
281
282 str = "foo\t \n\f\r\n\v";
283 absl::StripTrailingAsciiWhitespace(&str);
284 EXPECT_EQ("foo", str);
285
286 str = " \nfoo foo\t \n\f\r\n\v";
287 absl::StripTrailingAsciiWhitespace(&str);
288 EXPECT_EQ(" \nfoo foo", str);
289
290 str = "\t \n\f\r\v\n\t \n\f\r\v\n";
291 absl::StripTrailingAsciiWhitespace(&str);
292 EXPECT_EQ(absl::string_view{}, str);
293 }
294
TEST(StripAsciiWhitespace,FromStringView)295 TEST(StripAsciiWhitespace, FromStringView) {
296 EXPECT_EQ(absl::string_view{},
297 absl::StripAsciiWhitespace(absl::string_view{}));
298 EXPECT_EQ("foo", absl::StripAsciiWhitespace({"foo"}));
299 EXPECT_EQ("foo",
300 absl::StripAsciiWhitespace({"\t \n\f\r\n\vfoo\t \n\f\r\n\v"}));
301 EXPECT_EQ("foo foo", absl::StripAsciiWhitespace(
302 {"\t \n\f\r\n\vfoo foo\t \n\f\r\n\v"}));
303 EXPECT_EQ(absl::string_view{},
304 absl::StripAsciiWhitespace({"\t \n\f\r\v\n\t \n\f\r\v\n"}));
305 }
306
TEST(StripAsciiWhitespace,InPlace)307 TEST(StripAsciiWhitespace, InPlace) {
308 std::string str;
309
310 absl::StripAsciiWhitespace(&str);
311 EXPECT_EQ("", str);
312
313 str = "foo";
314 absl::StripAsciiWhitespace(&str);
315 EXPECT_EQ("foo", str);
316
317 str = "\t \n\f\r\n\vfoo\t \n\f\r\n\v";
318 absl::StripAsciiWhitespace(&str);
319 EXPECT_EQ("foo", str);
320
321 str = "\t \n\f\r\n\vfoo foo\t \n\f\r\n\v";
322 absl::StripAsciiWhitespace(&str);
323 EXPECT_EQ("foo foo", str);
324
325 str = "\t \n\f\r\v\n\t \n\f\r\v\n";
326 absl::StripAsciiWhitespace(&str);
327 EXPECT_EQ(absl::string_view{}, str);
328 }
329
TEST(RemoveExtraAsciiWhitespace,InPlace)330 TEST(RemoveExtraAsciiWhitespace, InPlace) {
331 const char* inputs[] = {"No extra space",
332 " Leading whitespace",
333 "Trailing whitespace ",
334 " Leading and trailing ",
335 " Whitespace \t in\v middle ",
336 "'Eeeeep! \n Newlines!\n",
337 "nospaces",
338 "",
339 "\n\t a\t\n\nb \t\n"};
340
341 const char* outputs[] = {
342 "No extra space",
343 "Leading whitespace",
344 "Trailing whitespace",
345 "Leading and trailing",
346 "Whitespace in middle",
347 "'Eeeeep! Newlines!",
348 "nospaces",
349 "",
350 "a\nb",
351 };
352 const int NUM_TESTS = ABSL_ARRAYSIZE(inputs);
353
354 for (int i = 0; i < NUM_TESTS; i++) {
355 std::string s(inputs[i]);
356 absl::RemoveExtraAsciiWhitespace(&s);
357 EXPECT_EQ(outputs[i], s);
358 }
359 }
360
361 } // namespace
362