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 
7 using std::string;
8 using std::string_view;
9 
10 namespace StringOp {
11 
12 bool 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 
22 //string toLower(string_view str)
23 //{
24 // string result(str);
25 // transform_in_place(result, ::tolower);
26 // return result;
27 //}
28 
29 void 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 }
37 void 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 }
45 void 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 }
51 void trimRight(string_view& str, char chars)
52 {
53  while (!str.empty() && (str.back() == chars)) {
54  str.remove_suffix(1);
55  }
56 }
57 
58 void trimLeft(string& str, const char* chars)
59 {
60  str.erase(0, str.find_first_not_of(chars));
61 }
62 void trimLeft(string& str, char chars)
63 {
64  str.erase(0, str.find_first_not_of(chars));
65 }
66 void 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 }
72 void trimLeft(string_view& str, char chars)
73 {
74  while (!str.empty() && (str.front() == chars)) {
75  str.remove_prefix(1);
76  }
77 }
78 
79 void trim(string_view& str, string_view chars)
80 {
81  trimRight(str, chars);
82  trimLeft (str, chars);
83 }
84 
85 void trim(string_view& str, char chars)
86 {
87  trimRight(str, chars);
88  trimLeft (str, chars);
89 }
90 
91 std::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 }
99 std::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 
108 std::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 }
116 std::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 
136 static 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 
146 static void checkRange(unsigned x, unsigned min, unsigned max)
147 {
148  if ((min <= x) && (x <= max)) return;
149  throw openmsx::MSXException(
150  "Out of range, should be between [, ", min, ", ", max,
151  "], but got: ", x);
152 }
153 
154 static 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 
177 IterableBitSet<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 
197 std::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
void swap(openmsx::MemBuffer< T > &l, openmsx::MemBuffer< T > &r) noexcept
Definition: MemBuffer.hh:202
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
constexpr vecN< N, T > min(const vecN< N, T > &x, const vecN< N, T > &y)
Definition: gl_vec.hh:258
constexpr vecN< N, T > max(const vecN< N, T > &x, const vecN< N, T > &y)
Definition: gl_vec.hh:276
constexpr KeyMatrixPosition x
Keyboard bindings.
Definition: Keyboard.cc:127
constexpr auto begin(const zstring_view &x)
constexpr auto end(const zstring_view &x)