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