1 #ifndef _library__string__hpp__included__
2 #define _library__string__hpp__included__
11 #include <boost/lexical_cast.hpp>
16 * Strip trailing CR if any.
18 std::string
strip_CR(const std::string
& str
);
21 * Strip trailing CR if any.
23 void istrip_CR(std::string
& str
);
26 * Return first character or -1 if empty.
28 int firstchar(const std::string
& str
);
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()); }
48 template<typename T
> class lambda_output_iterator
51 template<typename U
> class helper
54 helper(std::function
<void(const U
& val
)> _fn
)
58 helper
& operator=(const U
& v
)
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
;
74 lambda_output_iterator(std::function
<void(const T
& val
)> _fn
)
81 helper
<T
>& operator*() throw()
88 lambda_output_iterator
<T
>& operator++() throw()
95 lambda_output_iterator
<T
> operator++(int) throw()
106 template<typename T
> class token_iterator
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
); }
130 bool operator==(const token_iterator
<T
>& itr
) const throw() { return equals_op(itr
); }
134 bool operator!=(const token_iterator
<T
>& itr
) const throw() { return !equals_op(itr
); }
138 const std::basic_string
<T
>& operator*() const throw() { return dereference(); }
142 token_iterator
<T
>& operator++() throw(std::bad_alloc
) { return preincrement(); }
146 token_iterator
<T
> operator++(int) throw(std::bad_alloc
) { return postincrement(); }
148 * Do nothing, pull everything.
150 static void pull_fn();
155 template<typename U
> class _foreach
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
)
169 token_iterator
<U
> begin() throw() { return s
; }
173 token_iterator
<U
> end() throw() { return e
; }
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
);
187 const std::basic_string
<T
>& str
;
190 std::basic_string
<T
> tmp
;
191 std::set
<std::basic_string
<T
>> spliton
;
192 bool is_end_iterator
;
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
);
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;
215 const std::string
& operator[](size_t i
) const;
216 std::pair
<size_t, size_t> match(size_t i
) const;
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.
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");
286 if(value
[idx
] == '-' || value
[idx
] == '+')
288 bool sign
= (value
[0] == '-');
289 T bound
= sign
? std::numeric_limits
<T
>::min() : std::numeric_limits
<T
>::max();
291 if(value
.length() > idx
+ 2 && value
[idx
] == '0' && value
[idx
+ 1] == 'x') {
293 for(size_t i
= idx
+ 2; i
< value
.length(); i
++) {
296 if(ch
>= '0' && ch
<= '9')
298 else if(ch
>= 'A' && ch
<= 'F')
300 else if(ch
>= 'a' && ch
<= 'f')
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
);
310 for(size_t i
= idx
; i
< value
.length(); i
++) {
313 if(ch
>= '0' && ch
<= '9')
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
);
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");
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
);
342 throw std::runtime_error("Can't parse value '" + value
+ "': Value out of valid range");
346 template<> inline std::string
parse_value(const std::string
& value
) throw(std::bad_alloc
, std::runtime_error
)
356 string_list(const std::list
<std::basic_string
<T
>>& list
);
358 string_list
strip_one() 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;
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
);