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()
93 lambda_output_iterator
<T
> operator++(int) throw()
103 template<typename T
> class token_iterator
106 typedef std::forward_iterator_tag iterator_category
;
107 typedef std::basic_string
<T
> value_type
;
108 typedef int difference_type
;
109 typedef const std::basic_string
<T
>& reference
;
110 typedef const std::basic_string
<T
>* pointer
;
112 * Create new end-of-sequence iterator.
114 token_iterator() : str(tmp
) { ctor_eos(); }
116 * Create a new start-of-sequence iterator.
118 * Parameter s: The string to iterate. Must remain valid during lifetime of iterator.
119 * Parameter sep: The set of separators.
120 * Parameter whole_sequence: If true, after seeing one separator, throw away separators until none more are found.
122 token_iterator(const std::basic_string
<T
>& s
, std::initializer_list
<const T
*> sep
,
123 bool whole_sequence
= false) throw(std::bad_alloc
) : str(s
) { ctor_itr(sep
, whole_sequence
); }
127 bool operator==(const token_iterator
<T
>& itr
) const throw() { return equals_op(itr
); }
131 bool operator!=(const token_iterator
<T
>& itr
) const throw() { return !equals_op(itr
); }
135 const std::basic_string
<T
>& operator*() const throw() { return dereference(); }
139 token_iterator
<T
>& operator++() throw(std::bad_alloc
) { return preincrement(); }
143 token_iterator
<T
> operator++(int) throw(std::bad_alloc
) { return postincrement(); }
145 * Do nothing, pull everything.
147 static void pull_fn();
150 void ctor_itr(std::initializer_list
<const T
*> sep
, bool whole_sequence
= false) throw(std::bad_alloc
);
151 token_iterator
<T
> postincrement() throw(std::bad_alloc
);
152 token_iterator
<T
>& preincrement() throw(std::bad_alloc
);
153 const std::basic_string
<T
>& dereference() const throw();
154 bool equals_op(const token_iterator
<T
>& itr
) const throw();
155 size_t is_sep(size_t pos
);
157 const std::basic_string
<T
>& str
;
160 std::basic_string
<T
> tmp
;
161 std::set
<std::basic_string
<T
>> spliton
;
162 bool is_end_iterator
;
169 template<typename U
> class _token_iterator_foreach
175 _token_iterator_foreach(const std::basic_string
<U
>& _s
,
176 std::initializer_list
<const U
*> sep
, bool whole_sequence
= false)
177 : s(_s
, sep
, whole_sequence
)
183 token_iterator
<U
> begin() throw() { return s
; }
187 token_iterator
<U
> end() throw() { return e
; }
193 template<typename T
> _token_iterator_foreach
<T
> token_iterator_foreach(const std::basic_string
<T
>& _s
,
194 std::initializer_list
<const T
*> sep
, bool whole_sequence
= false)
196 return _token_iterator_foreach
<T
>(_s
, sep
, whole_sequence
);
204 regex_results(std::vector
<std::string
> res
, std::vector
<std::pair
<size_t, size_t>> mch
);
205 operator bool() const;
206 bool operator!() const;
208 const std::string
& operator[](size_t i
) const;
209 std::pair
<size_t, size_t> match(size_t i
) const;
212 std::vector
<std::string
> results
;
213 std::vector
<std::pair
<size_t, size_t>> matches
;
217 * Regexp a string and return matches.
219 * Parameter regex: The regexp to apply.
220 * Parameter str: The string to apply the regexp to.
221 * Parameter ex: If non-null and string does not match, throw this as std::runtime_error.
222 * Returns: The captures.
224 regex_results
regex(const std::string
& regex
, const std::string
& str
, const char* ex
= NULL
)
225 throw(std::bad_alloc
, std::runtime_error
);
228 * Regexp a string and return match result.
230 * Parameter regex: The regexp to apply.
231 * Parameter str: The string to apply the regexp to.
232 * Returns: True if matches, false if not.
234 bool regex_match(const std::string
& regex
, const std::string
& str
) throw(std::bad_alloc
, std::runtime_error
);
237 * Cast string to bool.
239 * The following is true: 'on', 'true', 'yes', '1', 'enable', 'enabled'.
240 * The following is false: 'off', 'false', 'no', '0', 'disable', 'disabled'.
241 * Parameter str: The string to cast.
242 * Returns: -1 if string is bad, 0 if false, 1 if true.
244 int string_to_bool(const std::string
& cast_to_bool
);
247 * \brief Typeconvert string.
249 template<typename T
> inline T
parse_value(const std::string
& value
) throw(std::bad_alloc
, std::runtime_error
)
251 //Floating-point case.
253 if(std::numeric_limits
<T
>::is_integer
) {
254 if(!std::numeric_limits
<T
>::is_signed
&& value
.length() && value
[0] == '-') {
255 throw std::runtime_error("Unsigned values can't be negative");
258 if(value
[idx
] == '-' || value
[idx
] == '+')
260 bool sign
= (value
[0] == '-');
261 T mult
= sign
? -1 : 1;
262 T bound
= sign
? std::numeric_limits
<T
>::min() : std::numeric_limits
<T
>::max();
264 if(value
.length() > idx
+ 2 && value
[idx
] == '0' && value
[idx
+ 1] == 'x') {
266 for(size_t i
= idx
+ 2; i
< value
.length(); i
++) {
269 if(ch
>= '0' && ch
<= '9')
271 else if(ch
>= 'A' && ch
<= 'F')
273 else if(ch
>= 'a' && ch
<= 'f')
276 throw std::runtime_error("Invalid character in number");
277 if((sign
&& (bound
+ v
) / 16 > val
) || (!sign
&& (bound
- v
) / 16 < val
))
278 throw std::runtime_error("Value exceeds range");
279 val
= 16 * val
+ (sign
? -v
: v
);
283 for(size_t i
= idx
; i
< value
.length(); i
++) {
286 if(ch
>= '0' && ch
<= '9')
289 throw std::runtime_error("Invalid character in number");
290 if((sign
&& (bound
+ v
) / 10 > val
) || (!sign
&& (bound
- v
) / 10 < val
))
291 throw std::runtime_error("Value exceeds range");
292 val
= 10 * val
+ (sign
? -v
: v
);
297 return boost::lexical_cast
<T
>(value
);
298 } catch(std::exception
& e
) {
299 throw std::runtime_error("Can't parse value '" + value
+ "': " + e
.what());
303 template<> inline ss_int24_t
parse_value(const std::string
& value
) throw(std::bad_alloc
, std::runtime_error
)
305 int32_t v
= parse_value
<int32_t>(value
);
306 if(v
< -8388608 || v
> 8388607)
307 throw std::runtime_error("Can't parse value '" + value
+ "': Value out of valid range");
311 template<> inline ss_uint24_t
parse_value(const std::string
& value
) throw(std::bad_alloc
, std::runtime_error
)
313 uint32_t v
= parse_value
<uint32_t>(value
);
315 throw std::runtime_error("Can't parse value '" + value
+ "': Value out of valid range");
319 template<> inline std::string
parse_value(const std::string
& value
) throw(std::bad_alloc
, std::runtime_error
)
329 string_list(const std::list
<std::basic_string
<T
>>& list
);
331 string_list
strip_one() const;
333 const std::basic_string
<T
>& operator[](size_t idx
) const;
334 bool operator<(const string_list
<T
>& x
) const;
335 bool operator==(const string_list
<T
>& x
) const;
336 bool prefix_of(const string_list
<T
>& x
) const;
337 std::basic_string
<T
> debug_name() const;
339 string_list(const std::basic_string
<T
>* array
, size_t arrsize
);
340 std::vector
<std::basic_string
<T
>> v
;
344 * Split a string into substrings on some unicode codepoint.
346 string_list
<char> split_on_codepoint(const std::string
& s
, char32_t cp
);
348 * Split a string into substrings on some unicode codepoint.
350 string_list
<char32_t
> split_on_codepoint(const std::u32string
& s
, char32_t cp
);