openMSX
StringOp_test.cc
Go to the documentation of this file.
1 #include "catch.hpp"
2 #include "StringOp.hh"
3 
4 using namespace std;
5 using namespace StringOp;
6 
7 static void testStringToInt(const std::string& s, bool ok, int expected)
8 {
9  int result;
10  bool success = stringToInt(s, result);
11  REQUIRE(success == ok);
12  if (ok) {
13  CHECK(result == expected);
14  CHECK(stringToInt(s) == expected);
15  }
16 }
17 
18 static void checkTrimRight(const string& s, char c, const string& expected)
19 {
20  string test = s;
21  trimRight(test, c);
22  CHECK(test == expected);
23 
24  string_view ref = s;
25  trimRight(ref, c);
26  CHECK(ref == expected);
27 }
28 static void checkTrimRight(const string& s, const char* chars, const string& expected)
29 {
30  string test = s;
31  trimRight(test, chars);
32  CHECK(test == expected);
33 
34  string_view ref = s;
35  trimRight(ref, chars);
36  CHECK(ref == expected);
37 }
38 
39 static void checkTrimLeft(const string& s, char c, const string& expected)
40 {
41  string test = s;
42  trimLeft(test, c);
43  CHECK(test == expected);
44 
45  string_view ref = s;
46  trimLeft(ref, c);
47  CHECK(ref == expected);
48 }
49 static void checkTrimLeft(const string& s, const char* chars, const string& expected)
50 {
51  string test = s;
52  trimLeft(test, chars);
53  CHECK(test == expected);
54 
55  string_view ref = s;
56  trimLeft(ref, chars);
57  CHECK(ref == expected);
58 }
59 
60 static void checkSplitOnFirst(const string& s, const string& first, const string& last)
61 {
62  string_view f1, f2, l1, l2;
63  splitOnFirst(s, '-', f1, l1);
64  splitOnFirst(s, " -+", f2, l2);
65  CHECK(f1 == first);
66  CHECK(f2 == first);
67  CHECK(l1 == last);
68  CHECK(l2 == last);
69 }
70 
71 static void checkSplitOnLast(const string& s, const string& first, const string& last)
72 {
73  string_view f1, f2, l1, l2;
74  splitOnLast(s, '-', f1, l1);
75  splitOnLast(s, " -+", f2, l2);
76  CHECK(f1 == first);
77  CHECK(f2 == first);
78  CHECK(l1 == last);
79  CHECK(l2 == last);
80 }
81 
82 static void checkSplit(const string& s, const vector<string_view> expected)
83 {
84  CHECK(split(s, '-') == expected);
85 }
86 
87 static void checkParseRange(const string& s, const vector<unsigned>& expected)
88 {
89  CHECK(parseRange(s, 0, 99) == expected);
90 }
91 
92 TEST_CASE("StringOp")
93 {
94  SECTION("stringToXXX") {
95  testStringToInt("", true, 0);
96  testStringToInt("0", true, 0);
97  testStringToInt("1234", true, 1234);
98  testStringToInt("-1234", true, -1234);
99  testStringToInt("0xabcd", true, 43981);
100  testStringToInt("0x7fffffff", true, 2147483647);
101  testStringToInt("-0x80000000", true, -2147483648);
102  testStringToInt("bla", false, 0);
103  //testStringToInt("0x80000000", true, 0); not detected correctly
104 
105  // TODO stringToUint
106  // TODO stringToUint64
107 
108  CHECK(stringToBool("0") == false);
109  CHECK(stringToBool("1") == true);
110  CHECK(stringToBool("Yes") == true);
111  CHECK(stringToBool("yes") == true);
112  CHECK(stringToBool("YES") == true);
113  CHECK(stringToBool("No") == false);
114  CHECK(stringToBool("no") == false);
115  CHECK(stringToBool("NO") == false);
116  CHECK(stringToBool("True") == true);
117  CHECK(stringToBool("true") == true);
118  CHECK(stringToBool("TRUE") == true);
119  CHECK(stringToBool("False") == false);
120  CHECK(stringToBool("false") == false);
121  CHECK(stringToBool("FALSE") == false);
122  // These two behave different as Tcl
123  CHECK(stringToBool("2") == false); // is true in Tcl
124  CHECK(stringToBool("foobar") == false); // is error in Tcl
125 
126  // TODO stringToDouble
127  }
128  SECTION("toLower") {
129  CHECK(toLower("") == "");
130  CHECK(toLower("foo") == "foo");
131  CHECK(toLower("FOO") == "foo");
132  CHECK(toLower("fOo") == "foo");
133  CHECK(toLower(string("FoO")) == "foo");
134  }
135  SECTION("startsWith") {
136  CHECK (startsWith("foobar", "foo"));
137  CHECK_FALSE(startsWith("foobar", "bar"));
138  CHECK_FALSE(startsWith("ba", "bar"));
139  CHECK (startsWith("", ""));
140  CHECK_FALSE(startsWith("", "bar"));
141  CHECK (startsWith("foobar", ""));
142 
143  CHECK (startsWith("foobar", 'f'));
144  CHECK_FALSE(startsWith("foobar", 'b'));
145  CHECK_FALSE(startsWith("", 'b'));
146  }
147  SECTION("endsWith") {
148  CHECK (endsWith("foobar", "bar"));
149  CHECK_FALSE(endsWith("foobar", "foo"));
150  CHECK_FALSE(endsWith("ba", "bar"));
151  CHECK_FALSE(endsWith("ba", "baba"));
152  CHECK (endsWith("", ""));
153  CHECK_FALSE(endsWith("", "bar"));
154  CHECK (endsWith("foobar", ""));
155 
156  CHECK (endsWith("foobar", 'r'));
157  CHECK_FALSE(endsWith("foobar", 'o'));
158  CHECK_FALSE(endsWith("", 'b'));
159  }
160  SECTION("trimRight") {
161  checkTrimRight("", ' ', "");
162  checkTrimRight(" ", ' ', "");
163  checkTrimRight("foo", ' ', "foo");
164  checkTrimRight(" foo", ' ', " foo");
165  checkTrimRight("foo ", ' ', "foo");
166 
167  checkTrimRight("", "o ", "");
168  checkTrimRight(" o ", "o ", "");
169  checkTrimRight("foobar", "o ", "foobar");
170  checkTrimRight(" foobar", "o ", " foobar");
171  checkTrimRight("foo ", "o ", "f");
172  }
173  SECTION("trimLeft") {
174  checkTrimLeft("", ' ', "");
175  checkTrimLeft(" ", ' ', "");
176  checkTrimLeft("foo", ' ', "foo");
177  checkTrimLeft("foo ", ' ', "foo ");
178  checkTrimLeft(" foo", ' ', "foo");
179 
180  checkTrimLeft("", "f ", "");
181  checkTrimLeft(" f ", "f ", "");
182  checkTrimLeft("foo", "f ", "oo");
183  checkTrimLeft("barfoo ", "f ", "barfoo ");
184  checkTrimLeft(" foo", "f ", "oo");
185  }
186  SECTION("splitOnFirst") {
187  checkSplitOnFirst("", "", "");
188  checkSplitOnFirst("-", "", "");
189  checkSplitOnFirst("foo-", "foo", "");
190  checkSplitOnFirst("-foo", "", "foo");
191  checkSplitOnFirst("foo-bar", "foo", "bar");
192  checkSplitOnFirst("foo-bar-qux", "foo", "bar-qux");
193  checkSplitOnFirst("-bar-qux", "", "bar-qux");
194  checkSplitOnFirst("foo-bar-", "foo", "bar-");
195  }
196  SECTION("splitOnLast") {
197  checkSplitOnLast("", "", "");
198  checkSplitOnLast("-", "", "");
199  checkSplitOnLast("foo-", "foo", "");
200  checkSplitOnLast("-foo", "", "foo");
201  checkSplitOnLast("foo-bar", "foo", "bar");
202  checkSplitOnLast("foo-bar-qux", "foo-bar", "qux");
203  checkSplitOnLast("-bar-qux", "-bar", "qux");
204  checkSplitOnLast("foo-bar-", "foo-bar", "");
205  }
206  SECTION("split") {
207  checkSplit("", {});
208  checkSplit("-", {""});
209  checkSplit("foo-", {"foo"});
210  checkSplit("-foo", {"", "foo"});
211  checkSplit("foo-bar", {"foo", "bar"});
212  checkSplit("foo-bar-qux", {"foo", "bar", "qux"});
213  checkSplit("-bar-qux", {"", "bar", "qux"});
214  checkSplit("foo-bar-", {"foo", "bar"});
215  }
216  SECTION("parseRange") {
217  checkParseRange("", {});
218  checkParseRange("5", {5});
219  checkParseRange("5,8", {5,8});
220  checkParseRange("5,5", {5});
221  checkParseRange("5-7", {5,6,7});
222  checkParseRange("7-5", {5,6,7});
223  checkParseRange("5-7,19", {5,6,7,19});
224  checkParseRange("15,5-7", {5,6,7,15});
225  checkParseRange("6,5-7", {5,6,7});
226  checkParseRange("5-8,10-12", {5,6,7,8,10,11,12});
227  checkParseRange("5-9,6-10", {5,6,7,8,9,10});
228 
229  CHECK_THROWS (parseRange( "4", 5, 10));
230  CHECK_NOTHROW(parseRange( "5", 5, 10));
231  CHECK_NOTHROW(parseRange("10", 5, 10));
232  CHECK_THROWS (parseRange("11", 5, 10));
233  }
234  SECTION("caseless") {
235  caseless op;
236  CHECK( op("abc", "xyz"));
237  CHECK(!op("xyz", "abc"));
238  CHECK(!op("abc", "abc"));
239  CHECK( op("ABC", "xyz"));
240  CHECK(!op("xyz", "ABC"));
241  CHECK(!op("ABC", "abc"));
242  CHECK( op("aBC", "Xyz"));
243  CHECK(!op("xYz", "AbC"));
244  CHECK(!op("ABc", "abC"));
245 
246  CHECK( op("abc", "ABCdef"));
247  CHECK(!op("AbcDef", "AbC"));
248  }
249  SECTION("casecmp") {
250  casecmp op;
251  CHECK( op("abc", "abc"));
252  CHECK( op("abc", "ABC"));
253  CHECK(!op("abc", "xyz"));
254  CHECK(!op("ab", "abc"));
255  CHECK(!op("ab", "ABC"));
256  CHECK(!op("abc", "ab"));
257  CHECK(!op("abc", "AB"));
258  }
259 }
vector< unsigned > parseRange(string_view str, unsigned min, unsigned max)
Definition: StringOp.cc:255
void splitOnLast(string_view str, string_view chars, string_view &first, string_view &last)
Definition: StringOp.cc:174
void trimLeft(string &str, const char *chars)
Definition: StringOp.cc:118
bool startsWith(string_view total, string_view part)
Definition: StringOp.cc:69
STL namespace.
vector< string_view > split(string_view str, char chars)
Definition: StringOp.cc:197
TEST_CASE("StringOp")
void trimRight(string &str, const char *chars)
Definition: StringOp.cc:87
CHECK(m3==m3)
string toLower(string_view str)
Definition: StringOp.cc:62
bool stringToBool(string_view str)
Definition: StringOp.cc:41
This class implements a (close approximation) of the std::string_view class.
Definition: string_view.hh:16
int stringToInt(const string &str)
Definition: StringOp.cc:14
void splitOnFirst(string_view str, string_view chars, string_view &first, string_view &last)
Definition: StringOp.cc:151
bool endsWith(string_view total, string_view part)
Definition: StringOp.cc:78