1 #ifndef _library__string__hpp__included__
2 #define _library__string__hpp__included__
10 #include <boost/lexical_cast.hpp>
15 * Strip trailing CR if any.
17 std::string
strip_CR(const std::string
& str
);
20 * Strip trailing CR if any.
22 void istrip_CR(std::string
& str
);
25 * Return first character or -1 if empty.
27 int firstchar(const std::string
& str
);
36 std::string
str() { return x
.str(); }
37 std::u32string
str32() { return utf8::to32(x
.str()); }
38 template<typename T
> stringfmt
& operator<<(const T
& y
) { x
<< y
; return *this; }
39 void throwex() { throw std::runtime_error(x
.str()); }
47 template<typename T
> class lambda_output_iterator
50 template<typename U
> class helper
53 helper(std::function
<void(const U
& val
)> _fn
)
57 helper
& operator=(const U
& v
)
63 std::function
<void(const U
& val
)> fn
;
65 typedef std::output_iterator_tag iterator_category
;
66 typedef helper
<T
> value_type
;
67 typedef int difference_type
;
68 typedef helper
<T
>& reference
;
69 typedef helper
<T
>* pointer
;
73 lambda_output_iterator(std::function
<void(const T
& val
)> _fn
)
80 helper
<T
>& operator*() throw()
87 lambda_output_iterator
<T
>& operator++() throw()
94 lambda_output_iterator
<T
> operator++(int) throw()
105 template<typename T
> class token_iterator
108 typedef std::forward_iterator_tag iterator_category
;
109 typedef std::basic_string
<T
> value_type
;
110 typedef int difference_type
;
111 typedef const std::basic_string
<T
>& reference
;
112 typedef const std::basic_string
<T
>* pointer
;
114 * Create new end-of-sequence iterator.
116 token_iterator() : str(tmp
) { ctor_eos(); }
118 * Create a new start-of-sequence iterator.
120 * Parameter s: The string to iterate. Must remain valid during lifetime of iterator.
121 * Parameter sep: The set of separators.
122 * Parameter whole_sequence: If true, after seeing one separator, throw away separators until none more are found.
124 token_iterator(const std::basic_string
<T
>& s
, std::initializer_list
<const T
*> sep
,
125 bool whole_sequence
= false) throw(std::bad_alloc
) : str(s
) { ctor_itr(sep
, whole_sequence
); }
129 bool operator==(const token_iterator
<T
>& itr
) const throw() { return equals_op(itr
); }
133 bool operator!=(const token_iterator
<T
>& itr
) const throw() { return !equals_op(itr
); }
137 const std::basic_string
<T
>& operator*() const throw() { return dereference(); }
141 token_iterator
<T
>& operator++() throw(std::bad_alloc
) { return preincrement(); }
145 token_iterator
<T
> operator++(int) throw(std::bad_alloc
) { return postincrement(); }
147 * Do nothing, pull everything.
149 static void pull_fn();
154 template<typename U
> class _foreach
160 _foreach(const std::basic_string
<U
>& _s
,
161 std::initializer_list
<const U
*> sep
, bool whole_sequence
= false)
162 : s(_s
, sep
, whole_sequence
)
168 token_iterator
<U
> begin() throw() { return s
; }
172 token_iterator
<U
> end() throw() { return e
; }
179 void ctor_itr(std::initializer_list
<const T
*> sep
, bool whole_sequence
= false) throw(std::bad_alloc
);
180 token_iterator
<T
> postincrement() throw(std::bad_alloc
);
181 token_iterator
<T
>& preincrement() throw(std::bad_alloc
);
182 const std::basic_string
<T
>& dereference() const throw();
183 bool equals_op(const token_iterator
<T
>& itr
) const throw();
184 size_t is_sep(size_t pos
);
186 const std::basic_string
<T
>& str
;
189 std::basic_string
<T
> tmp
;
190 std::set
<std::basic_string
<T
>> spliton
;
191 bool is_end_iterator
;
195 * Return an container referencing tokens of string.
197 static _foreach
<T
> foreach(const std::basic_string
<T
>& _s
,
198 std::initializer_list
<const T
*> sep
, bool whole_sequence
= false)
200 return _foreach
<T
>(_s
, sep
, whole_sequence
);
210 regex_results(std::vector
<std::string
> res
, std::vector
<std::pair
<size_t, size_t>> mch
);
211 operator bool() const;
212 bool operator!() const;
214 const std::string
& operator[](size_t i
) const;
215 std::pair
<size_t, size_t> match(size_t i
) const;
218 std::vector
<std::string
> results
;
219 std::vector
<std::pair
<size_t, size_t>> matches
;
223 * Regexp a string and return matches.
225 * Parameter regex: The regexp to apply.
226 * Parameter str: The string to apply the regexp to.
227 * Parameter ex: If non-null and string does not match, throw this as std::runtime_error.
228 * Returns: The captures.
230 regex_results
regex(const std::string
& regex
, const std::string
& str
, const char* ex
= NULL
)
231 throw(std::bad_alloc
, std::runtime_error
);
234 * Regexp a string and return match result.
236 * Parameter regex: The regexp to apply.
237 * Parameter str: The string to apply the regexp to.
238 * Returns: True if matches, false if not.
240 bool regex_match(const std::string
& regex
, const std::string
& str
) throw(std::bad_alloc
, std::runtime_error
);
243 * Cast string to bool.
245 * The following is true: 'on', 'true', 'yes', '1', 'enable', 'enabled'.
246 * The following is false: 'off', 'false', 'no', '0', 'disable', 'disabled'.
247 * Parameter str: The string to cast.
248 * Returns: -1 if string is bad, 0 if false, 1 if true.
250 int string_to_bool(const std::string
& cast_to_bool
);
253 * \brief Typeconvert string.
255 template<typename T
> inline T
parse_value(const std::string
& value
) throw(std::bad_alloc
, std::runtime_error
)
257 //Floating-point case.
259 if(std::numeric_limits
<T
>::is_integer
) {
260 if(!std::numeric_limits
<T
>::is_signed
&& value
.length() && value
[0] == '-') {
261 throw std::runtime_error("Unsigned values can't be negative");
264 if(value
[idx
] == '-' || value
[idx
] == '+')
266 bool sign
= (value
[0] == '-');
267 T bound
= sign
? std::numeric_limits
<T
>::min() : std::numeric_limits
<T
>::max();
269 if(value
.length() > idx
+ 2 && value
[idx
] == '0' && value
[idx
+ 1] == 'x') {
271 for(size_t i
= idx
+ 2; i
< value
.length(); i
++) {
274 if(ch
>= '0' && ch
<= '9')
276 else if(ch
>= 'A' && ch
<= 'F')
278 else if(ch
>= 'a' && ch
<= 'f')
281 throw std::runtime_error("Invalid character in number");
282 if((sign
&& (bound
+ v
) / 16 > val
) || (!sign
&& (bound
- v
) / 16 < val
))
283 throw std::runtime_error("Value exceeds range");
284 val
= 16 * val
+ (sign
? -v
: v
);
288 for(size_t i
= idx
; i
< value
.length(); i
++) {
291 if(ch
>= '0' && ch
<= '9')
294 throw std::runtime_error("Invalid character in number");
295 if((sign
&& (bound
+ v
) / 10 > val
) || (!sign
&& (bound
- v
) / 10 < val
))
296 throw std::runtime_error("Value exceeds range");
297 val
= 10 * val
+ (sign
? -v
: v
);
302 return boost::lexical_cast
<T
>(value
);
303 } catch(std::exception
& e
) {
304 throw std::runtime_error("Can't parse value '" + value
+ "': " + e
.what());
308 template<> inline ss_int24_t
parse_value(const std::string
& value
) throw(std::bad_alloc
, std::runtime_error
)
310 int32_t v
= parse_value
<int32_t>(value
);
311 if(v
< -8388608 || v
> 8388607)
312 throw std::runtime_error("Can't parse value '" + value
+ "': Value out of valid range");
316 template<> inline ss_uint24_t
parse_value(const std::string
& value
) throw(std::bad_alloc
, std::runtime_error
)
318 uint32_t v
= parse_value
<uint32_t>(value
);
320 throw std::runtime_error("Can't parse value '" + value
+ "': Value out of valid range");
324 template<> inline std::string
parse_value(const std::string
& value
) throw(std::bad_alloc
, std::runtime_error
)
334 string_list(const std::list
<std::basic_string
<T
>>& list
);
336 string_list
strip_one() const;
338 const std::basic_string
<T
>& operator[](size_t idx
) const;
339 bool operator<(const string_list
<T
>& x
) const;
340 bool operator==(const string_list
<T
>& x
) const;
341 bool prefix_of(const string_list
<T
>& x
) const;
342 std::basic_string
<T
> debug_name() const;
344 string_list(const std::basic_string
<T
>* array
, size_t arrsize
);
345 std::vector
<std::basic_string
<T
>> v
;
349 * Split a string into substrings on some unicode codepoint.
351 string_list
<char> split_on_codepoint(const std::string
& s
, char32_t cp
);
353 * Split a string into substrings on some unicode codepoint.
355 string_list
<char32_t
> split_on_codepoint(const std::u32string
& s
, char32_t cp
);