Add <functional> to files that use std::function
[lsnes.git] / include / library / string.hpp
blob2bd0373809229307ddebe0b8d7e2462590903488
1 #ifndef _library__string__hpp__included__
2 #define _library__string__hpp__included__
4 #include <functional>
5 #include <string>
6 #include <sstream>
7 #include <set>
8 #include <list>
9 #include <stdexcept>
10 #include <vector>
11 #include <boost/lexical_cast.hpp>
12 #include "utf8.hpp"
13 #include "int24.hpp"
15 /**
16 * Strip trailing CR if any.
18 std::string strip_CR(const std::string& str);
20 /**
21 * Strip trailing CR if any.
23 void istrip_CR(std::string& str);
25 /**
26 * Return first character or -1 if empty.
28 int firstchar(const std::string& str);
30 /**
31 * String formatter
33 class stringfmt
35 public:
36 stringfmt() {}
37 std::string str() { return x.str(); }
38 std::u32string str32() { return utf8::to32(x.str()); }
39 template<typename T> stringfmt& operator<<(const T& y) { x << y; return *this; }
40 void throwex() { throw std::runtime_error(x.str()); }
41 private:
42 std::ostringstream x;
45 /**
46 * Lambda iterator.
48 template<typename T> class lambda_output_iterator
50 public:
51 template<typename U> class helper
53 public:
54 helper(std::function<void(const U& val)> _fn)
55 : fn(_fn)
58 helper& operator=(const U& v)
60 fn(v);
61 return *this;
63 private:
64 std::function<void(const U& val)> fn;
66 typedef std::output_iterator_tag iterator_category;
67 typedef helper<T> value_type;
68 typedef int difference_type;
69 typedef helper<T>& reference;
70 typedef helper<T>* pointer;
71 /**
72 * Constructor.
74 lambda_output_iterator(std::function<void(const T& val)> _fn)
75 : h(_fn)
78 /**
79 * Dereference.
81 helper<T>& operator*() throw()
83 return h;
85 /**
86 * Increment.
88 lambda_output_iterator<T>& operator++() throw()
90 return *this;
92 /**
93 * Increment.
95 lambda_output_iterator<T> operator++(int) throw()
97 return *this;
99 private:
100 helper<T> h;
104 * Token iterator.
106 template<typename T> class token_iterator
108 public:
109 typedef std::forward_iterator_tag iterator_category;
110 typedef std::basic_string<T> value_type;
111 typedef int difference_type;
112 typedef const std::basic_string<T>& reference;
113 typedef const std::basic_string<T>* pointer;
115 * Create new end-of-sequence iterator.
117 token_iterator() : str(tmp) { ctor_eos(); }
119 * Create a new start-of-sequence iterator.
121 * Parameter s: The string to iterate. Must remain valid during lifetime of iterator.
122 * Parameter sep: The set of separators.
123 * Parameter whole_sequence: If true, after seeing one separator, throw away separators until none more are found.
125 token_iterator(const std::basic_string<T>& s, std::initializer_list<const T*> sep,
126 bool whole_sequence = false) throw(std::bad_alloc) : str(s) { ctor_itr(sep, whole_sequence); }
128 * Compare.
130 bool operator==(const token_iterator<T>& itr) const throw() { return equals_op(itr); }
132 * Compare.
134 bool operator!=(const token_iterator<T>& itr) const throw() { return !equals_op(itr); }
136 * Dereference.
138 const std::basic_string<T>& operator*() const throw() { return dereference(); }
140 * Increment.
142 token_iterator<T>& operator++() throw(std::bad_alloc) { return preincrement(); }
144 * Increment.
146 token_iterator<T> operator++(int) throw(std::bad_alloc) { return postincrement(); }
148 * Do nothing, pull everything.
150 static void pull_fn();
151 private:
153 * Foreach helper.
155 template<typename U> class _foreach
157 public:
159 * Create helper.
161 _foreach(const std::basic_string<U>& _s,
162 std::initializer_list<const U*> sep, bool whole_sequence = false)
163 : s(_s, sep, whole_sequence)
167 * Starting iterator.
169 token_iterator<U> begin() throw() { return s; }
171 * Ending iterator.
173 token_iterator<U> end() throw() { return e; }
174 private:
175 token_iterator<U> s;
176 token_iterator<U> e;
179 void ctor_eos();
180 void ctor_itr(std::initializer_list<const T*> sep, bool whole_sequence = false) throw(std::bad_alloc);
181 token_iterator<T> postincrement() throw(std::bad_alloc);
182 token_iterator<T>& preincrement() throw(std::bad_alloc);
183 const std::basic_string<T>& dereference() const throw();
184 bool equals_op(const token_iterator<T>& itr) const throw();
185 size_t is_sep(size_t pos);
186 void load_helper();
187 const std::basic_string<T>& str;
188 size_t bidx;
189 size_t eidx;
190 std::basic_string<T> tmp;
191 std::set<std::basic_string<T>> spliton;
192 bool is_end_iterator;
193 bool whole_seq;
194 public:
196 * Return an container referencing tokens of string.
198 static _foreach<T> foreach(const std::basic_string<T>& _s,
199 std::initializer_list<const T*> sep, bool whole_sequence = false)
201 return _foreach<T>(_s, sep, whole_sequence);
207 class regex_results
209 public:
210 regex_results();
211 regex_results(std::vector<std::string> res, std::vector<std::pair<size_t, size_t>> mch);
212 operator bool() const;
213 bool operator!() const;
214 size_t size() const;
215 const std::string& operator[](size_t i) const;
216 std::pair<size_t, size_t> match(size_t i) const;
217 private:
218 bool matched;
219 std::vector<std::string> results;
220 std::vector<std::pair<size_t, size_t>> matches;
224 * Regexp a string and return matches.
226 * Parameter regex: The regexp to apply.
227 * Parameter str: The string to apply the regexp to.
228 * Parameter ex: If non-null and string does not match, throw this as std::runtime_error.
229 * Returns: The captures.
231 regex_results regex(const std::string& regex, const std::string& str, const char* ex = NULL)
232 throw(std::bad_alloc, std::runtime_error);
234 enum regex_match_mode
236 REGEX_MATCH_REGEX = 0,
237 REGEX_MATCH_LITERIAL = 1,
238 REGEX_MATCH_IWILDCARDS = 2,
239 REGEX_MATCH_IREGEX = 3,
243 * Regexp a string and return match result.
245 * Parameter regex: The regexp to apply.
246 * Parameter str: The string to apply the regexp to.
247 * Parameter mode: Match mode.
248 * Returns: True if matches, false if not.
250 bool regex_match(const std::string& regex, const std::string& str, enum regex_match_mode mode = REGEX_MATCH_REGEX)
251 throw(std::bad_alloc, std::runtime_error);
254 * Try match a case-insensitive string fragment and return the result.
256 * \param pattern The pattern to match a
260 * Cast string to bool.
262 * The following is true: 'on', 'true', 'yes', '1', 'enable', 'enabled'.
263 * The following is false: 'off', 'false', 'no', '0', 'disable', 'disabled'.
264 * Parameter str: The string to cast.
265 * Returns: -1 if string is bad, 0 if false, 1 if true.
267 int string_to_bool(const std::string& cast_to_bool);
269 template<typename T> T raw_lexical_cast(const std::string& value)
271 return boost::lexical_cast<T>(value);
275 * \brief Typeconvert string.
277 template<typename T> inline T parse_value(const std::string& value) throw(std::bad_alloc, std::runtime_error)
279 //Floating-point case.
280 try {
281 if(std::numeric_limits<T>::is_integer) {
282 if(!std::numeric_limits<T>::is_signed && value.length() && value[0] == '-') {
283 throw std::runtime_error("Unsigned values can't be negative");
285 size_t idx = 0;
286 if(value[idx] == '-' || value[idx] == '+')
287 idx++;
288 bool sign = (value[0] == '-');
289 T bound = sign ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
290 T val = 0;
291 if(value.length() > idx + 2 && value[idx] == '0' && value[idx + 1] == 'x') {
292 //Hexadecimal
293 for(size_t i = idx + 2; i < value.length(); i++) {
294 char ch = value[i];
295 T v = 0;
296 if(ch >= '0' && ch <= '9')
297 v = ch - '0';
298 else if(ch >= 'A' && ch <= 'F')
299 v = ch - 'A' + 10;
300 else if(ch >= 'a' && ch <= 'f')
301 v = ch - 'a' + 10;
302 else
303 throw std::runtime_error("Invalid character in number");
304 if((sign && (bound + v) / 16 > val) || (!sign && (bound - v) / 16 < val))
305 throw std::runtime_error("Value exceeds range");
306 val = 16 * val + (sign ? -v : v);
308 } else {
309 //Decimal.
310 for(size_t i = idx; i < value.length(); i++) {
311 char ch = value[i];
312 T v = 0;
313 if(ch >= '0' && ch <= '9')
314 v = ch - '0';
315 else
316 throw std::runtime_error("Invalid character in number");
317 if((sign && (bound + v) / 10 > val) || (!sign && (bound - v) / 10 < val))
318 throw std::runtime_error("Value exceeds range");
319 val = 10 * val + (sign ? -v : v);
322 return val;
324 return raw_lexical_cast<T>(value);
325 } catch(std::exception& e) {
326 throw std::runtime_error("Can't parse value '" + value + "': " + e.what());
330 template<> inline ss_int24_t parse_value(const std::string& value) throw(std::bad_alloc, std::runtime_error)
332 int32_t v = parse_value<int32_t>(value);
333 if(v < -8388608 || v > 8388607)
334 throw std::runtime_error("Can't parse value '" + value + "': Value out of valid range");
335 return v;
338 template<> inline ss_uint24_t parse_value(const std::string& value) throw(std::bad_alloc, std::runtime_error)
340 uint32_t v = parse_value<uint32_t>(value);
341 if(v > 0xFFFFFF)
342 throw std::runtime_error("Can't parse value '" + value + "': Value out of valid range");
343 return v;
346 template<> inline std::string parse_value(const std::string& value) throw(std::bad_alloc, std::runtime_error)
348 return value;
351 template<typename T>
352 class string_list
354 public:
355 string_list();
356 string_list(const std::list<std::basic_string<T>>& list);
357 bool empty();
358 string_list strip_one() const;
359 size_t size() const;
360 const std::basic_string<T>& operator[](size_t idx) const;
361 bool operator<(const string_list<T>& x) const;
362 bool operator==(const string_list<T>& x) const;
363 bool prefix_of(const string_list<T>& x) const;
364 std::basic_string<T> debug_name() const;
365 private:
366 string_list(const std::basic_string<T>* array, size_t arrsize);
367 std::vector<std::basic_string<T>> v;
371 * Split a string into substrings on some unicode codepoint.
373 string_list<char> split_on_codepoint(const std::string& s, char32_t cp);
375 * Split a string into substrings on some unicode codepoint.
377 string_list<char32_t> split_on_codepoint(const std::u32string& s, char32_t cp);
379 #endif