openMSX
StringOp.cc
Go to the documentation of this file.
1#include "StringOp.hh"
2#include "MSXException.hh"
3#include "ranges.hh"
4#include "stl.hh"
5#include <cstdlib>
6
7using std::string;
8using std::string_view;
9
10namespace StringOp {
11
12bool stringToBool(string_view str)
13{
14 if (str == "1") return true;
15 if ((str.size() == 4) && (strncasecmp(str.data(), "true", 4) == 0))
16 return true;
17 if ((str.size() == 3) && (strncasecmp(str.data(), "yes", 3) == 0))
18 return true;
19 return false;
20}
21
22std::string toLower(std::string_view str)
23{
24 std::string result(str);
25 transform_in_place(result, ::tolower);
26 return result;
27}
28
29void trimRight(string& str, const char* chars)
30{
31 if (auto pos = str.find_last_not_of(chars); pos != string::npos) {
32 str.erase(pos + 1);
33 } else {
34 str.clear();
35 }
36}
37void trimRight(string& str, char chars)
38{
39 if (auto pos = str.find_last_not_of(chars); pos != string::npos) {
40 str.erase(pos + 1);
41 } else {
42 str.clear();
43 }
44}
45void trimRight(string_view& str, string_view chars)
46{
47 while (!str.empty() && (chars.find(str.back()) != string_view::npos)) {
48 str.remove_suffix(1);
49 }
50}
51void trimRight(string_view& str, char chars)
52{
53 while (!str.empty() && (str.back() == chars)) {
54 str.remove_suffix(1);
55 }
56}
57
58void trimLeft(string& str, const char* chars)
59{
60 str.erase(0, str.find_first_not_of(chars));
61}
62void trimLeft(string& str, char chars)
63{
64 str.erase(0, str.find_first_not_of(chars));
65}
66void trimLeft(string_view& str, string_view chars)
67{
68 while (!str.empty() && (chars.find(str.front()) != string_view::npos)) {
69 str.remove_prefix(1);
70 }
71}
72void trimLeft(string_view& str, char chars)
73{
74 while (!str.empty() && (str.front() == chars)) {
75 str.remove_prefix(1);
76 }
77}
78
79void trim(string_view& str, string_view chars)
80{
81 trimRight(str, chars);
82 trimLeft (str, chars);
83}
84
85void trim(string_view& str, char chars)
86{
87 trimRight(str, chars);
88 trimLeft (str, chars);
89}
90
91std::pair<string_view, string_view> splitOnFirst(string_view str, string_view chars)
92{
93 if (auto pos = str.find_first_of(chars); pos == string_view::npos) {
94 return {str, string_view{}};
95 } else {
96 return {str.substr(0, pos), str.substr(pos + 1)};
97 }
98}
99std::pair<string_view, string_view> splitOnFirst(string_view str, char chars)
100{
101 if (auto pos = str.find_first_of(chars); pos == string_view::npos) {
102 return {str, string_view{}};
103 } else {
104 return {str.substr(0, pos), str.substr(pos + 1)};
105 }
106}
107
108std::pair<string_view, string_view> splitOnLast(string_view str, string_view chars)
109{
110 if (auto pos = str.find_last_of(chars); pos == string_view::npos) {
111 return {string_view{}, str};
112 } else {
113 return {str.substr(0, pos), str.substr(pos + 1)};
114 }
115}
116std::pair<string_view, string_view> splitOnLast(string_view str, char chars)
117{
118 if (auto pos = str.find_last_of(chars); pos == string_view::npos) {
119 return {string_view{}, str};
120 } else {
121 return {str.substr(0, pos), str.substr(pos + 1)};
122 }
123}
124
125//std::vector<string_view> split(string_view str, char chars)
126//{
127// std::vector<string_view> result;
128// while (!str.empty()) {
129// auto [first, last] = splitOnFirst(str, chars);
130// result.push_back(first);
131// str = last;
132// }
133// return result;
134//}
135
136static unsigned parseNumber(string_view str)
137{
138 trim(str, " \t");
139 auto r = stringToBase<10, unsigned>(str);
140 if (!r) {
141 throw openmsx::MSXException("Invalid integer: ", str);
142 }
143 return *r;
144}
145
146static void checkRange(unsigned x, unsigned min, unsigned max)
147{
148 if ((min <= x) && (x <= max)) return;
150 "Out of range, should be between [, ", min, ", ", max,
151 "], but got: ", x);
152}
153
154static void parseRange2(string_view str, IterableBitSet<64>& result,
155 unsigned min, unsigned max)
156{
157 // trimRight only: here we only care about all spaces
158 trimRight(str, " \t");
159 if (str.empty()) return;
160
161 if (auto pos = str.find('-'); pos == string_view::npos) {
162 auto x = parseNumber(str);
163 checkRange(x, min, max);
164 result.set(x);
165 } else {
166 unsigned begin = parseNumber(str.substr(0, pos));
167 unsigned end = parseNumber(str.substr(pos + 1));
168 if (end < begin) {
169 std::swap(begin, end);
170 }
171 checkRange(begin, min, max);
172 checkRange(end, min, max);
173 result.setRange(begin, end + 1);
174 }
175}
176
177IterableBitSet<64> parseRange(string_view str, unsigned min, unsigned max)
178{
179 assert(min <= max);
180 assert(max < 64);
181
182 IterableBitSet<64> result;
183 while (true) {
184 auto next = str.find(',');
185 string_view sub = (next == string_view::npos)
186 ? str
187 : str.substr(0, next++);
188 parseRange2(sub, result, min, max);
189 if (next == string_view::npos) break;
190 str = str.substr(next);
191 }
192 return result;
193}
194
195#if defined(__APPLE__)
196
197std::string fromCFString(CFStringRef str)
198{
199 // Try the quick route first.
200 const char *cstr = CFStringGetCStringPtr(str, kCFStringEncodingUTF8);
201 if (cstr) {
202 // String was already in UTF8 encoding.
203 return std::string(cstr);
204 }
205
206 // Convert to UTF8 encoding.
207 CFIndex len = CFStringGetLength(str);
208 CFRange range = CFRangeMake(0, len);
209 CFIndex usedBufLen = 0;
210 CFStringGetBytes(
211 str, range, kCFStringEncodingUTF8, '?', false, nullptr, len, &usedBufLen);
212 UInt8 buffer[usedBufLen];
213 CFStringGetBytes(
214 str, range, kCFStringEncodingUTF8, '?', false, buffer, len, &usedBufLen);
215 return std::string(reinterpret_cast<const char *>(buffer), usedBufLen);
216}
217
218#endif
219
220} // namespace StringOp
IterableBitSet.
void setRange(size_t begin, size_t end)
Set all bits in the half-open range [begin, end) to '1'.
void set(size_t pos)
Set the (single) bit at position 'pos' to '1'.
void trim(string_view &str, string_view chars)
Definition StringOp.cc:79
IterableBitSet< 64 > parseRange(string_view str, unsigned min, unsigned max)
Definition StringOp.cc:177
bool stringToBool(string_view str)
Definition StringOp.cc:12
std::pair< string_view, string_view > splitOnLast(string_view str, string_view chars)
Definition StringOp.cc:108
void trimRight(string &str, const char *chars)
Definition StringOp.cc:29
std::pair< string_view, string_view > splitOnFirst(string_view str, string_view chars)
Definition StringOp.cc:91
void trimLeft(string &str, const char *chars)
Definition StringOp.cc:58
std::string toLower(std::string_view str)
Definition StringOp.cc:22
auto transform_in_place(ForwardRange &&range, UnaryOperation op)
Definition stl.hh:196
constexpr auto begin(const zstring_view &x)
constexpr auto end(const zstring_view &x)