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 std::string mutable_str("STUVWX");
201
202 EXPECT_EQ("abcdef", absl::AsciiStrToLower(buf));
203 EXPECT_EQ("ghijkl", absl::AsciiStrToLower(str));
204 EXPECT_EQ("mnopqr", absl::AsciiStrToLower(sp));
205
206 absl::AsciiStrToLower(&mutable_str);
207 EXPECT_EQ("stuvwx", mutable_str);
208
209 char mutable_buf[] = "Mutable";
210 std::transform(mutable_buf, mutable_buf + strlen(mutable_buf),
211 mutable_buf, absl::ascii_tolower);
212 EXPECT_STREQ("mutable", mutable_buf);
213 }
214
TEST(AsciiStrTo,Upper)215 TEST(AsciiStrTo, Upper) {
216 const char buf[] = "abcdef";
217 const std::string str("ghijkl");
218 const std::string str2("mnopqr");
219 const absl::string_view sp(str2);
220
221 EXPECT_EQ("ABCDEF", absl::AsciiStrToUpper(buf));
222 EXPECT_EQ("GHIJKL", absl::AsciiStrToUpper(str));
223 EXPECT_EQ("MNOPQR", absl::AsciiStrToUpper(sp));
224
225 char mutable_buf[] = "Mutable";
226 std::transform(mutable_buf, mutable_buf + strlen(mutable_buf),
227 mutable_buf, absl::ascii_toupper);
228 EXPECT_STREQ("MUTABLE", mutable_buf);
229 }
230
TEST(StripLeadingAsciiWhitespace,FromStringView)231 TEST(StripLeadingAsciiWhitespace, FromStringView) {
232 EXPECT_EQ(absl::string_view{},
233 absl::StripLeadingAsciiWhitespace(absl::string_view{}));
234 EXPECT_EQ("foo", absl::StripLeadingAsciiWhitespace({"foo"}));
235 EXPECT_EQ("foo", absl::StripLeadingAsciiWhitespace({"\t \n\f\r\n\vfoo"}));
236 EXPECT_EQ("foo foo\n ",
237 absl::StripLeadingAsciiWhitespace({"\t \n\f\r\n\vfoo foo\n "}));
238 EXPECT_EQ(absl::string_view{}, absl::StripLeadingAsciiWhitespace(
239 {"\t \n\f\r\v\n\t \n\f\r\v\n"}));
240 }
241
TEST(StripLeadingAsciiWhitespace,InPlace)242 TEST(StripLeadingAsciiWhitespace, InPlace) {
243 std::string str;
244
245 absl::StripLeadingAsciiWhitespace(&str);
246 EXPECT_EQ("", str);
247
248 str = "foo";
249 absl::StripLeadingAsciiWhitespace(&str);
250 EXPECT_EQ("foo", str);
251
252 str = "\t \n\f\r\n\vfoo";
253 absl::StripLeadingAsciiWhitespace(&str);
254 EXPECT_EQ("foo", str);
255
256 str = "\t \n\f\r\n\vfoo foo\n ";
257 absl::StripLeadingAsciiWhitespace(&str);
258 EXPECT_EQ("foo foo\n ", str);
259
260 str = "\t \n\f\r\v\n\t \n\f\r\v\n";
261 absl::StripLeadingAsciiWhitespace(&str);
262 EXPECT_EQ(absl::string_view{}, str);
263 }
264
TEST(StripTrailingAsciiWhitespace,FromStringView)265 TEST(StripTrailingAsciiWhitespace, FromStringView) {
266 EXPECT_EQ(absl::string_view{},
267 absl::StripTrailingAsciiWhitespace(absl::string_view{}));
268 EXPECT_EQ("foo", absl::StripTrailingAsciiWhitespace({"foo"}));
269 EXPECT_EQ("foo", absl::StripTrailingAsciiWhitespace({"foo\t \n\f\r\n\v"}));
270 EXPECT_EQ(" \nfoo foo",
271 absl::StripTrailingAsciiWhitespace({" \nfoo foo\t \n\f\r\n\v"}));
272 EXPECT_EQ(absl::string_view{}, absl::StripTrailingAsciiWhitespace(
273 {"\t \n\f\r\v\n\t \n\f\r\v\n"}));
274 }
275
TEST(StripTrailingAsciiWhitespace,InPlace)276 TEST(StripTrailingAsciiWhitespace, InPlace) {
277 std::string str;
278
279 absl::StripTrailingAsciiWhitespace(&str);
280 EXPECT_EQ("", str);
281
282 str = "foo";
283 absl::StripTrailingAsciiWhitespace(&str);
284 EXPECT_EQ("foo", str);
285
286 str = "foo\t \n\f\r\n\v";
287 absl::StripTrailingAsciiWhitespace(&str);
288 EXPECT_EQ("foo", str);
289
290 str = " \nfoo foo\t \n\f\r\n\v";
291 absl::StripTrailingAsciiWhitespace(&str);
292 EXPECT_EQ(" \nfoo foo", str);
293
294 str = "\t \n\f\r\v\n\t \n\f\r\v\n";
295 absl::StripTrailingAsciiWhitespace(&str);
296 EXPECT_EQ(absl::string_view{}, str);
297 }
298
TEST(StripAsciiWhitespace,FromStringView)299 TEST(StripAsciiWhitespace, FromStringView) {
300 EXPECT_EQ(absl::string_view{},
301 absl::StripAsciiWhitespace(absl::string_view{}));
302 EXPECT_EQ("foo", absl::StripAsciiWhitespace({"foo"}));
303 EXPECT_EQ("foo",
304 absl::StripAsciiWhitespace({"\t \n\f\r\n\vfoo\t \n\f\r\n\v"}));
305 EXPECT_EQ("foo foo", absl::StripAsciiWhitespace(
306 {"\t \n\f\r\n\vfoo foo\t \n\f\r\n\v"}));
307 EXPECT_EQ(absl::string_view{},
308 absl::StripAsciiWhitespace({"\t \n\f\r\v\n\t \n\f\r\v\n"}));
309 }
310
TEST(StripAsciiWhitespace,InPlace)311 TEST(StripAsciiWhitespace, InPlace) {
312 std::string str;
313
314 absl::StripAsciiWhitespace(&str);
315 EXPECT_EQ("", str);
316
317 str = "foo";
318 absl::StripAsciiWhitespace(&str);
319 EXPECT_EQ("foo", str);
320
321 str = "\t \n\f\r\n\vfoo\t \n\f\r\n\v";
322 absl::StripAsciiWhitespace(&str);
323 EXPECT_EQ("foo", str);
324
325 str = "\t \n\f\r\n\vfoo foo\t \n\f\r\n\v";
326 absl::StripAsciiWhitespace(&str);
327 EXPECT_EQ("foo foo", str);
328
329 str = "\t \n\f\r\v\n\t \n\f\r\v\n";
330 absl::StripAsciiWhitespace(&str);
331 EXPECT_EQ(absl::string_view{}, str);
332 }
333
TEST(RemoveExtraAsciiWhitespace,InPlace)334 TEST(RemoveExtraAsciiWhitespace, InPlace) {
335 const char* inputs[] = {"No extra space",
336 " Leading whitespace",
337 "Trailing whitespace ",
338 " Leading and trailing ",
339 " Whitespace \t in\v middle ",
340 "'Eeeeep! \n Newlines!\n",
341 "nospaces",
342 "",
343 "\n\t a\t\n\nb \t\n"};
344
345 const char* outputs[] = {
346 "No extra space",
347 "Leading whitespace",
348 "Trailing whitespace",
349 "Leading and trailing",
350 "Whitespace in middle",
351 "'Eeeeep! Newlines!",
352 "nospaces",
353 "",
354 "a\nb",
355 };
356 const int NUM_TESTS = ABSL_ARRAYSIZE(inputs);
357
358 for (int i = 0; i < NUM_TESTS; i++) {
359 std::string s(inputs[i]);
360 absl::RemoveExtraAsciiWhitespace(&s);
361 EXPECT_EQ(outputs[i], s);
362 }
363 }
364
365 } // namespace
366