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