1*9356374aSAndroid Build Coastguard Worker // Copyright 2020 The Abseil Authors.
2*9356374aSAndroid Build Coastguard Worker //
3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9356374aSAndroid Build Coastguard Worker //
7*9356374aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0
8*9356374aSAndroid Build Coastguard Worker //
9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9356374aSAndroid Build Coastguard Worker // limitations under the License.
14*9356374aSAndroid Build Coastguard Worker
15*9356374aSAndroid Build Coastguard Worker #include "absl/strings/charset.h"
16*9356374aSAndroid Build Coastguard Worker
17*9356374aSAndroid Build Coastguard Worker #include <stdio.h>
18*9356374aSAndroid Build Coastguard Worker #include <stdlib.h>
19*9356374aSAndroid Build Coastguard Worker
20*9356374aSAndroid Build Coastguard Worker #include <string>
21*9356374aSAndroid Build Coastguard Worker #include <vector>
22*9356374aSAndroid Build Coastguard Worker
23*9356374aSAndroid Build Coastguard Worker #include "gtest/gtest.h"
24*9356374aSAndroid Build Coastguard Worker #include "absl/strings/ascii.h"
25*9356374aSAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
26*9356374aSAndroid Build Coastguard Worker
27*9356374aSAndroid Build Coastguard Worker namespace {
28*9356374aSAndroid Build Coastguard Worker
29*9356374aSAndroid Build Coastguard Worker constexpr absl::CharSet everything_map = ~absl::CharSet();
30*9356374aSAndroid Build Coastguard Worker constexpr absl::CharSet nothing_map = absl::CharSet();
31*9356374aSAndroid Build Coastguard Worker
TEST(Charmap,AllTests)32*9356374aSAndroid Build Coastguard Worker TEST(Charmap, AllTests) {
33*9356374aSAndroid Build Coastguard Worker const absl::CharSet also_nothing_map("");
34*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(everything_map.contains('\0'));
35*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(nothing_map.contains('\0'));
36*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(also_nothing_map.contains('\0'));
37*9356374aSAndroid Build Coastguard Worker for (unsigned char ch = 1; ch != 0; ++ch) {
38*9356374aSAndroid Build Coastguard Worker SCOPED_TRACE(ch);
39*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(everything_map.contains(ch));
40*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(nothing_map.contains(ch));
41*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(also_nothing_map.contains(ch));
42*9356374aSAndroid Build Coastguard Worker }
43*9356374aSAndroid Build Coastguard Worker
44*9356374aSAndroid Build Coastguard Worker const absl::CharSet symbols(absl::string_view("&@#@^!@?", 5));
45*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(symbols.contains('&'));
46*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(symbols.contains('@'));
47*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(symbols.contains('#'));
48*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(symbols.contains('^'));
49*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(symbols.contains('!'));
50*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(symbols.contains('?'));
51*9356374aSAndroid Build Coastguard Worker int cnt = 0;
52*9356374aSAndroid Build Coastguard Worker for (unsigned char ch = 1; ch != 0; ++ch) cnt += symbols.contains(ch);
53*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(cnt, 4);
54*9356374aSAndroid Build Coastguard Worker
55*9356374aSAndroid Build Coastguard Worker const absl::CharSet lets(absl::string_view("^abcde", 3));
56*9356374aSAndroid Build Coastguard Worker const absl::CharSet lets2(absl::string_view("fghij\0klmnop", 10));
57*9356374aSAndroid Build Coastguard Worker const absl::CharSet lets3("fghij\0klmnop");
58*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(lets2.contains('k'));
59*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(lets3.contains('k'));
60*9356374aSAndroid Build Coastguard Worker
61*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE((symbols & lets).empty());
62*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((lets2 & lets).empty());
63*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE((lets & symbols).empty());
64*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE((lets & lets2).empty());
65*9356374aSAndroid Build Coastguard Worker
66*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(nothing_map.empty());
67*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(lets.empty());
68*9356374aSAndroid Build Coastguard Worker }
69*9356374aSAndroid Build Coastguard Worker
Members(const absl::CharSet & m)70*9356374aSAndroid Build Coastguard Worker std::string Members(const absl::CharSet& m) {
71*9356374aSAndroid Build Coastguard Worker std::string r;
72*9356374aSAndroid Build Coastguard Worker for (size_t i = 0; i < 256; ++i)
73*9356374aSAndroid Build Coastguard Worker if (m.contains(i)) r.push_back(i);
74*9356374aSAndroid Build Coastguard Worker return r;
75*9356374aSAndroid Build Coastguard Worker }
76*9356374aSAndroid Build Coastguard Worker
ClosedRangeString(unsigned char lo,unsigned char hi)77*9356374aSAndroid Build Coastguard Worker std::string ClosedRangeString(unsigned char lo, unsigned char hi) {
78*9356374aSAndroid Build Coastguard Worker // Don't depend on lo<hi. Just increment until lo==hi.
79*9356374aSAndroid Build Coastguard Worker std::string s;
80*9356374aSAndroid Build Coastguard Worker while (true) {
81*9356374aSAndroid Build Coastguard Worker s.push_back(lo);
82*9356374aSAndroid Build Coastguard Worker if (lo == hi) break;
83*9356374aSAndroid Build Coastguard Worker ++lo;
84*9356374aSAndroid Build Coastguard Worker }
85*9356374aSAndroid Build Coastguard Worker return s;
86*9356374aSAndroid Build Coastguard Worker }
87*9356374aSAndroid Build Coastguard Worker
TEST(Charmap,Constexpr)88*9356374aSAndroid Build Coastguard Worker TEST(Charmap, Constexpr) {
89*9356374aSAndroid Build Coastguard Worker constexpr absl::CharSet kEmpty = absl::CharSet();
90*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(Members(kEmpty), "");
91*9356374aSAndroid Build Coastguard Worker constexpr absl::CharSet kA = absl::CharSet::Char('A');
92*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(Members(kA), "A");
93*9356374aSAndroid Build Coastguard Worker constexpr absl::CharSet kAZ = absl::CharSet::Range('A', 'Z');
94*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(Members(kAZ), "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
95*9356374aSAndroid Build Coastguard Worker constexpr absl::CharSet kIdentifier =
96*9356374aSAndroid Build Coastguard Worker absl::CharSet::Range('0', '9') | absl::CharSet::Range('A', 'Z') |
97*9356374aSAndroid Build Coastguard Worker absl::CharSet::Range('a', 'z') | absl::CharSet::Char('_');
98*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(Members(kIdentifier),
99*9356374aSAndroid Build Coastguard Worker "0123456789"
100*9356374aSAndroid Build Coastguard Worker "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
101*9356374aSAndroid Build Coastguard Worker "_"
102*9356374aSAndroid Build Coastguard Worker "abcdefghijklmnopqrstuvwxyz");
103*9356374aSAndroid Build Coastguard Worker constexpr absl::CharSet kAll = ~absl::CharSet();
104*9356374aSAndroid Build Coastguard Worker for (size_t i = 0; i < 256; ++i) {
105*9356374aSAndroid Build Coastguard Worker SCOPED_TRACE(i);
106*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(kAll.contains(i));
107*9356374aSAndroid Build Coastguard Worker }
108*9356374aSAndroid Build Coastguard Worker constexpr absl::CharSet kHello = absl::CharSet("Hello, world!");
109*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(Members(kHello), " !,Hdelorw");
110*9356374aSAndroid Build Coastguard Worker
111*9356374aSAndroid Build Coastguard Worker // test negation and intersection
112*9356374aSAndroid Build Coastguard Worker constexpr absl::CharSet kABC =
113*9356374aSAndroid Build Coastguard Worker absl::CharSet::Range('A', 'Z') & ~absl::CharSet::Range('D', 'Z');
114*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(Members(kABC), "ABC");
115*9356374aSAndroid Build Coastguard Worker
116*9356374aSAndroid Build Coastguard Worker // contains
117*9356374aSAndroid Build Coastguard Worker constexpr bool kContainsA = absl::CharSet("abc").contains('a');
118*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(kContainsA);
119*9356374aSAndroid Build Coastguard Worker constexpr bool kContainsD = absl::CharSet("abc").contains('d');
120*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(kContainsD);
121*9356374aSAndroid Build Coastguard Worker
122*9356374aSAndroid Build Coastguard Worker // empty
123*9356374aSAndroid Build Coastguard Worker constexpr bool kEmptyIsEmpty = absl::CharSet().empty();
124*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(kEmptyIsEmpty);
125*9356374aSAndroid Build Coastguard Worker constexpr bool kNotEmptyIsEmpty = absl::CharSet("abc").empty();
126*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(kNotEmptyIsEmpty);
127*9356374aSAndroid Build Coastguard Worker }
128*9356374aSAndroid Build Coastguard Worker
TEST(Charmap,Range)129*9356374aSAndroid Build Coastguard Worker TEST(Charmap, Range) {
130*9356374aSAndroid Build Coastguard Worker // Exhaustive testing takes too long, so test some of the boundaries that
131*9356374aSAndroid Build Coastguard Worker // are perhaps going to cause trouble.
132*9356374aSAndroid Build Coastguard Worker std::vector<size_t> poi = {0, 1, 2, 3, 4, 7, 8, 9, 15,
133*9356374aSAndroid Build Coastguard Worker 16, 17, 30, 31, 32, 33, 63, 64, 65,
134*9356374aSAndroid Build Coastguard Worker 127, 128, 129, 223, 224, 225, 254, 255};
135*9356374aSAndroid Build Coastguard Worker for (auto lo = poi.begin(); lo != poi.end(); ++lo) {
136*9356374aSAndroid Build Coastguard Worker SCOPED_TRACE(*lo);
137*9356374aSAndroid Build Coastguard Worker for (auto hi = lo; hi != poi.end(); ++hi) {
138*9356374aSAndroid Build Coastguard Worker SCOPED_TRACE(*hi);
139*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(Members(absl::CharSet::Range(*lo, *hi)),
140*9356374aSAndroid Build Coastguard Worker ClosedRangeString(*lo, *hi));
141*9356374aSAndroid Build Coastguard Worker }
142*9356374aSAndroid Build Coastguard Worker }
143*9356374aSAndroid Build Coastguard Worker }
144*9356374aSAndroid Build Coastguard Worker
TEST(Charmap,NullByteWithStringView)145*9356374aSAndroid Build Coastguard Worker TEST(Charmap, NullByteWithStringView) {
146*9356374aSAndroid Build Coastguard Worker char characters[5] = {'a', 'b', '\0', 'd', 'x'};
147*9356374aSAndroid Build Coastguard Worker absl::string_view view(characters, 5);
148*9356374aSAndroid Build Coastguard Worker absl::CharSet tester(view);
149*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(tester.contains('a'));
150*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(tester.contains('b'));
151*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(tester.contains('\0'));
152*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(tester.contains('d'));
153*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(tester.contains('x'));
154*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(tester.contains('c'));
155*9356374aSAndroid Build Coastguard Worker }
156*9356374aSAndroid Build Coastguard Worker
TEST(CharmapCtype,Match)157*9356374aSAndroid Build Coastguard Worker TEST(CharmapCtype, Match) {
158*9356374aSAndroid Build Coastguard Worker for (int c = 0; c < 256; ++c) {
159*9356374aSAndroid Build Coastguard Worker SCOPED_TRACE(c);
160*9356374aSAndroid Build Coastguard Worker SCOPED_TRACE(static_cast<char>(c));
161*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::ascii_isupper(c),
162*9356374aSAndroid Build Coastguard Worker absl::CharSet::AsciiUppercase().contains(c));
163*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::ascii_islower(c),
164*9356374aSAndroid Build Coastguard Worker absl::CharSet::AsciiLowercase().contains(c));
165*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::ascii_isdigit(c), absl::CharSet::AsciiDigits().contains(c));
166*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::ascii_isalpha(c),
167*9356374aSAndroid Build Coastguard Worker absl::CharSet::AsciiAlphabet().contains(c));
168*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::ascii_isalnum(c),
169*9356374aSAndroid Build Coastguard Worker absl::CharSet::AsciiAlphanumerics().contains(c));
170*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::ascii_isxdigit(c),
171*9356374aSAndroid Build Coastguard Worker absl::CharSet::AsciiHexDigits().contains(c));
172*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::ascii_isprint(c),
173*9356374aSAndroid Build Coastguard Worker absl::CharSet::AsciiPrintable().contains(c));
174*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::ascii_isspace(c),
175*9356374aSAndroid Build Coastguard Worker absl::CharSet::AsciiWhitespace().contains(c));
176*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::ascii_ispunct(c),
177*9356374aSAndroid Build Coastguard Worker absl::CharSet::AsciiPunctuation().contains(c));
178*9356374aSAndroid Build Coastguard Worker }
179*9356374aSAndroid Build Coastguard Worker }
180*9356374aSAndroid Build Coastguard Worker
181*9356374aSAndroid Build Coastguard Worker } // namespace
182