57 static std::vector<mask> v(classic_table(), classic_table() + table_size);
68 static std::vector<mask> v(classic_table(), classic_table() + table_size);
85 static std::vector<mask> v(classic_table(), classic_table() + table_size);
96 std::ostringstream oss;
101 template <
typename T>
105 std::istringstream iss{ aValueAsString };
111 template <
typename T>
112 inline string to_string(T
const& aValue)
117 template <
typename T>
123 template <
typename FwdIter1,
typename FwdIter2,
typename ResultContainer>
124 inline FwdIter1
tokens(FwdIter1 aFirst, FwdIter1 aLast, FwdIter2 aDelimeterFirst, FwdIter2 aDelimiterLast, ResultContainer& aTokens, std::size_t aMaxTokens = 0,
bool aSkipEmptyTokens =
true,
bool aDelimeterIsSubsequence =
false)
128 typedef typename ResultContainer::value_type value_type;
129 if (aDelimeterFirst == aDelimiterLast)
131 aTokens.push_back(value_type{ aFirst, aLast });
135 FwdIter1 e = aDelimeterIsSubsequence ? std::search(b, aLast, aDelimeterFirst, aDelimiterLast) : std::find_first_of(b, aLast, aDelimeterFirst, aDelimiterLast);
137 std::optional<FwdIter1> last;
138 while(e != aLast && (aMaxTokens == 0 ||
tokens < aMaxTokens))
140 if (b == e && !aSkipEmptyTokens)
142 aTokens.push_back(value_type{ b, b });
148 aTokens.push_back(value_type{ b, e });
154 e = aDelimeterIsSubsequence ? std::search(b, aLast, aDelimeterFirst, aDelimiterLast) : std::find_first_of(b, aLast, aDelimeterFirst, aDelimiterLast);
156 if (b != e && (aMaxTokens == 0 ||
tokens < aMaxTokens))
158 aTokens.push_back(value_type{ b, e });
161 else if (b == e && last && last.value() != e && !aSkipEmptyTokens)
162 aTokens.push_back(value_type{ e, e });
166 template <
typename FwdIter,
typename CharT,
typename Traits,
typename Alloc,
typename ResultContainer>
167 inline void tokens(FwdIter aFirst, FwdIter aLast,
const std::basic_string<CharT, Traits, Alloc>& aDelimeter, ResultContainer& aTokens, std::size_t aMaxTokens = 0,
bool aSkipEmptyTokens =
true,
bool aDelimeterIsSubsequence =
false)
169 tokens(aFirst, aLast, aDelimeter.begin(), aDelimeter.end(), aTokens, aMaxTokens, aSkipEmptyTokens, aDelimeterIsSubsequence);
172 template <
typename CharT,
typename Traits,
typename Alloc,
typename ResultContainer>
173 inline void tokens(
const std::basic_string<CharT, Traits, Alloc>& aLine,
const std::basic_string<CharT, Traits, Alloc>& aDelimeter, ResultContainer& aTokens, std::size_t aMaxTokens = 0,
bool aSkipEmptyTokens =
true,
bool aDelimeterIsSubsequence =
false)
175 tokens(aLine.begin(), aLine.end(), aDelimeter.begin(), aDelimeter.end(), aTokens, aMaxTokens, aSkipEmptyTokens, aDelimeterIsSubsequence);
178 template <
typename FwdIter,
typename CharT,
typename Traits,
typename Alloc>
179 inline std::vector<std::basic_string<CharT, Traits, Alloc>>
tokens(FwdIter aFirst, FwdIter aLast,
const std::basic_string<CharT, Traits, Alloc>& aDelimeter, std::size_t aMaxTokens = 0,
bool aSkipEmptyTokens =
true,
bool aDelimeterIsSubsequence =
false)
181 std::vector<std::basic_string<CharT, Traits, Alloc>> results;
182 tokens(aFirst, aLast, aDelimeter.begin(), aDelimeter.end(), results, aMaxTokens, aSkipEmptyTokens, aDelimeterIsSubsequence);
186 template <
typename CharT,
typename Traits,
typename Alloc>
187 inline std::vector<std::basic_string<CharT, Traits, Alloc>>
tokens(
const std::basic_string<CharT, Traits, Alloc>& aLine,
const std::basic_string<CharT, Traits, Alloc>& aDelimeter, std::size_t aMaxTokens = 0,
bool aSkipEmptyTokens =
true,
bool aDelimeterIsSubsequence =
false)
189 std::vector<std::basic_string<CharT, Traits, Alloc>> results;
190 tokens(aLine.begin(), aLine.end(), aDelimeter.begin(), aDelimeter.end(), results, aMaxTokens, aSkipEmptyTokens, aDelimeterIsSubsequence);
194 inline std::string to_string(
const std::pair<char const*, char const*>& aIterPair)
196 return std::string(aIterPair.first, aIterPair.second);
199 template <
typename CharT,
typename Traits,
typename Alloc>
200 inline std::basic_string<CharT, Traits, Alloc>
to_lower(
const std::basic_string<CharT, Traits, Alloc>& aString)
202 static boost::locale::generator gen;
203 static std::locale loc = gen(
"en_US.UTF-8");
204 return boost::locale::to_lower(aString, loc);
207 template <
typename CharT>
210 return to_lower(std::basic_string<CharT>(1, aCharacter))[0];
213 template <
typename CharT,
typename Traits,
typename Alloc>
214 inline std::basic_string<CharT, Traits, Alloc>
to_upper(
const std::basic_string<CharT, Traits, Alloc>& aString)
216 static boost::locale::generator gen;
217 static std::locale loc = gen(
"en_US.UTF-8");
218 return boost::locale::to_upper(aString, loc);
221 template <
typename CharT>
224 return to_upper(std::basic_string<CharT>(1, aCharacter))[0];
227 struct NEOLIB_EXPORT
string_span : std::pair<std::size_t, std::size_t>
229 typedef std::pair<std::size_t, std::size_t>
span;
232 string_span(std::size_t aFirst, std::size_t aSecond,
type aType = 0) :
span(aFirst, aSecond), iType(aType) {}
238 template <
typename CharT,
typename Traits,
typename Alloc>
239 inline bool replace_string(std::basic_string<CharT, Traits, Alloc>& aString,
const std::basic_string<CharT, Traits, Alloc>& aSearch,
const std::basic_string<CharT, Traits, Alloc>& aReplace,
string_spans* aSpans,
const string_span::type* aNewSpanType)
243 typedef std::basic_string<CharT, Traits, Alloc>
string;
245 bool replaced =
false;
246 while ((pos = aString.find(aSearch, pos)) != string::npos)
248 aString.replace(pos, aSearch.size(), aReplace);
251 if (aNewSpanType && aSpans->empty())
255 for (string_spans::iterator i = aSpans->begin(); i != aSpans->end(); ++i)
257 if (i->first != i->second)
261 if (aSearch.size() > aReplace.size())
262 i->first -= aSearch.size() - aReplace.size();
264 i->first += aReplace.size() - aSearch.size();
266 if (i->second >= pos)
268 if (aSearch.size() > aReplace.size())
269 i->second -= aSearch.size() - aReplace.size();
271 i->second += aReplace.size() - aSearch.size();
277 pos += aReplace.size();
283 template <
typename CharT,
typename Traits,
typename Alloc>
284 inline bool replace_string(std::basic_string<CharT, Traits, Alloc>& aString,
const std::basic_string<CharT, Traits, Alloc>& aSearch,
const std::basic_string<CharT, Traits, Alloc>& aReplace)
289 template <
typename CharT,
typename Traits,
typename Alloc>
290 inline bool replace_string(std::basic_string<CharT, Traits, Alloc>& aString,
const std::basic_string<CharT, Traits, Alloc>& aSearch,
const std::basic_string<CharT, Traits, Alloc>& aReplace,
string_spans* aSpans)
295 template <
typename CharT,
typename Traits,
typename Alloc>
296 inline bool replace_string(std::basic_string<CharT, Traits, Alloc>& aString,
const std::basic_string<CharT, Traits, Alloc>& aSearch,
const std::basic_string<CharT, Traits, Alloc>& aReplace,
string_spans* aSpans,
string_span::type aNewSpanType)
298 return replace_string(aString, aSearch, aReplace, aSpans, &aNewSpanType);
301 template <
typename CharT,
typename Traits,
typename Alloc>
302 inline std::string&
remove_leading(std::basic_string<CharT, Traits, Alloc>& aString,
const std::basic_string<CharT, Traits, Alloc>& aLeading)
304 typename std::basic_string<CharT, Traits, Alloc>::size_type pos = aString.find_first_not_of(aLeading);
305 if (pos != std::basic_string<CharT, Traits, Alloc>::npos)
306 aString.erase(aString.begin(), aString.begin() + pos);
312 template <
typename CharT,
typename Traits,
typename Alloc>
313 inline std::string&
remove_trailing(std::basic_string<CharT, Traits, Alloc>& aString,
const std::basic_string<CharT, Traits, Alloc>& aTrailing)
315 typename std::basic_string<CharT, Traits, Alloc>::size_type pos = aString.find_last_not_of(aTrailing);
316 if (pos != std::basic_string<CharT, Traits, Alloc>::npos)
317 aString.erase(aString.begin() + pos + 1, aString.end());
323 template <
typename CharT,
typename Traits,
typename Alloc>
324 inline std::string&
remove_leading_and_trailing(std::basic_string<CharT, Traits, Alloc>& aString,
const std::basic_string<CharT, Traits, Alloc>& aLeadingTrailing)
331 template <
typename CharT>
334 return strchr(aSequence, aCharacter) != NULL;
337 template <
typename CharT,
typename Traits,
typename Alloc>
338 inline typename std::basic_string<CharT, Traits, Alloc>::size_type
reverse_find_last_of(
const std::basic_string<CharT, Traits, Alloc>& aString,
const std::basic_string<CharT, Traits, Alloc>& aSequence,
typename std::basic_string<CharT, Traits, Alloc>::size_type aPosition)
341 return std::basic_string<CharT, Traits, Alloc>::npos;
342 typename std::basic_string<CharT, Traits, Alloc>::size_type last = std::basic_string<CharT, Traits, Alloc>::npos;
358 template <
typename CharT,
typename Traits,
typename Alloc>
359 inline typename std::basic_string<CharT, Traits, Alloc>::size_type
reverse_find_first_of(
const std::basic_string<CharT, Traits, Alloc>& aString,
const std::basic_string<CharT, Traits, Alloc>& aSequence,
typename std::basic_string<CharT, Traits, Alloc>::size_type aPosition)
362 return std::basic_string<CharT, Traits, Alloc>::npos;
363 if (aPosition == std::basic_string<CharT, Traits, Alloc>::npos)
364 aPosition = aString.size() - 1;
369 else if (aPosition == 0)
370 return std::basic_string<CharT, Traits, Alloc>::npos;
373 return std::basic_string<CharT, Traits, Alloc>::npos;
378 std::string ret = aString;
379 std::string::size_type escapePos;
380 while((escapePos = ret.find(
"\\r")) != std::string::npos)
381 ret.replace(escapePos, 2,
"\r");
382 while((escapePos = ret.find(
"\\n")) != std::string::npos)
383 ret.replace(escapePos, 2,
"\n");
384 while((escapePos = ret.find(
"\\t")) != std::string::npos)
385 ret.replace(escapePos, 2,
"\t");
391 std::string ret = aString;
392 for (std::string::size_type pos = 0; pos != ret.length(); ++pos)
393 if (ret[pos] ==
'%' && pos + 2 < ret.length())
394 ret.replace(pos, 3, 1,
static_cast<char>(
string_to_int32(ret.substr(pos + 1, 2), 16)));
400 template<
typename CharT>
404 template<
typename CharT>
409 template <
typename Traits>
415 if (c2 == wildcard_match_any_character<char_type>())
418 return Traits::eq(c1, c2);
423 template <
typename CharT,
typename Traits,
typename FwdIter>
424 inline bool do_wildcard_match(FwdIter aTextBegin, FwdIter aTextEnd, FwdIter aPatternBegin, FwdIter aPatternEnd)
426 typedef std::pair<FwdIter, FwdIter> substring_t;
427 typedef std::vector<substring_t> substrings_t;
428 substrings_t substrings;
429 CharT any_string = detail::wildcard_match_any_string<CharT>();
430 neolib::tokens(aPatternBegin, aPatternEnd, &any_string, &any_string+1, substrings);
432 FwdIter previousMatch = aTextBegin;
433 for (
typename substrings_t::const_iterator i = substrings.begin(); i != substrings.end();)
435 substring_t theSubstring = *i++;
437 if (nextMatch == aTextEnd)
439 if (theSubstring.first == aPatternBegin && nextMatch != aTextBegin)
441 if (theSubstring.second == aPatternEnd && !std::equal(aTextEnd - (theSubstring.second - theSubstring.first), aTextEnd, theSubstring.first,
detail::wildcard_compare<Traits>()))
443 if (theSubstring.second == aPatternEnd && aTextEnd - nextMatch != theSubstring.second - theSubstring.first)
445 previousMatch = nextMatch + (theSubstring.second - theSubstring.first);
450 template <
typename CharT,
typename FwdIter>
451 inline bool wildcard_match(FwdIter aTextBegin, FwdIter aTextEnd, FwdIter aPatternBegin, FwdIter aPatternEnd)
453 return do_wildcard_match<CharT, std::char_traits<CharT>, FwdIter>(aTextBegin, aTextEnd, aPatternBegin, aPatternEnd);
456 template <
typename CharT,
typename Traits,
typename Alloc>
457 inline bool wildcard_match(
const std::basic_string<CharT, Traits, Alloc>& aText,
const std::basic_string<CharT, Traits, Alloc>& aPattern)
459 return do_wildcard_match<CharT, Traits, std::basic_string<CharT, Traits, Alloc>::const_iterator>(aText.begin(), aText.end(), aPattern.begin(), aPattern.end());
465 typedef std::function<void(
char const*,
char const*)> action_t;
468 std::map<char, state> match;
469 std::list<action_t> actions;
471 typedef std::tuple<const action_t*, char const*, char const*> result_t;
472 typedef std::set<result_t> results_t;
477 void search(std::string
const& aText,
bool aRemoveSubmatches =
true)
const;
479 void search(state
const& aState,
char const* aStart,
char const* aNext,
char const* aEnd,
bool aSearchingWildcard, results_t& aResults)
const;
482 std::map<std::string, action_t> iPatterns;
501 arg_list::const_iterator
find_arg(std::size_t aArgIndex)
const
503 return std::find_if(
args.begin(),
args.end(), [&](
auto const& a) { return a.arg == aArgIndex; });
509 std::string_view
arg_span(std::size_t aArgIndex)
const
511 auto existing =
find_arg(aArgIndex);
512 if (existing !=
args.end())
514 throw std::format_error(
"neolib::format_result");
518 return std::find_if(
args.begin(),
args.end(), [&](
auto const& a) { return aPos >= a.begin && aPos < a.end; });
520 arg_list::const_iterator
arg_after(std::ptrdiff_t aPos)
const
523 if (existing ==
args.end())
525 existing = std::find_if(
args.rbegin(),
args.rend(), [&](
auto const& a) { return aPos >= a.end; }).base();
526 if (existing !=
args.begin())
529 if (existing !=
args.end())
535 template <
typename... Args>
539 auto next = aFormat.begin();
540 while (next != aFormat.end())
542 auto nextArg = std::find(next, aFormat.end(),
'{');
543 if (nextArg == aFormat.end())
545 result.
text.append(next, nextArg);
548 else if (
std::next(nextArg) == aFormat.end())
549 throw std::format_error(
"neolib::format");
557 result.
text.append(next, nextArg);
558 auto nextArgEnd = std::find(nextArg, aFormat.end(),
'}');
559 if (nextArgEnd == aFormat.end())
560 throw std::format_error(
"neolib::format");
566 auto argIdTerminators = {
':',
'}' };
567 auto argIdEnd = std::find_first_of(nextArg, nextArgEnd, argIdTerminators.begin(), argIdTerminators.end());
568 std::optional<std::size_t> argId;
569 if (argIdEnd - nextArg >= 2)
570 argId =
static_cast<std::size_t
>(std::stoi(std::string{
std::next(nextArg), argIdEnd }));
572 result.
args.emplace_back(argId.value(), result.
text.size());
573 result.
text.append(std::vformat(std::string_view{ nextArg, nextArgEnd }, std::make_format_args(std::forward<Args>(aArgs)...)));
575 result.
args.back().end = result.
text.size();
std::string to_std_string() const
void search(std::string const &aText, bool aRemoveSubmatches=true) const
void add_pattern(std::string const &aPattern, action_t aAction)
void push_back(const value_type &aValue) final
CharT wildcard_match_any_character()
char16_t wildcard_match_any_string< char16_t >()
char16_t wildcard_match_any_character< char16_t >()
CharT wildcard_match_any_string()
int32_t string_to_int32(const std::basic_string_view< CharT, Traits > &aStringView)
std::string to_std_string(T const &aValue)
std::string & remove_leading(std::basic_string< CharT, Traits, Alloc > &aString, const std::basic_string< CharT, Traits, Alloc > &aLeading)
std::string parse_escapes(const std::string &aString)
FwdIter1 tokens(FwdIter1 aFirst, FwdIter1 aLast, FwdIter2 aDelimeterFirst, FwdIter2 aDelimiterLast, ResultContainer &aTokens, std::size_t aMaxTokens=0, bool aSkipEmptyTokens=true, bool aDelimeterIsSubsequence=false)
std::basic_string< CharT, Traits, Alloc >::size_type reverse_find_first_of(const std::basic_string< CharT, Traits, Alloc > &aString, const std::basic_string< CharT, Traits, Alloc > &aSequence, typename std::basic_string< CharT, Traits, Alloc >::size_type aPosition)
bool wildcard_match(FwdIter aTextBegin, FwdIter aTextEnd, FwdIter aPatternBegin, FwdIter aPatternEnd)
bool replace_string(std::basic_string< CharT, Traits, Alloc > &aString, const std::basic_string< CharT, Traits, Alloc > &aSearch, const std::basic_string< CharT, Traits, Alloc > &aReplace, string_spans *aSpans, const string_span::type *aNewSpanType)
std::string & remove_trailing(std::basic_string< CharT, Traits, Alloc > &aString, const std::basic_string< CharT, Traits, Alloc > &aTrailing)
std::vector< string_span > string_spans
std::basic_string< CharT, Traits, Alloc >::size_type reverse_find_last_of(const std::basic_string< CharT, Traits, Alloc > &aString, const std::basic_string< CharT, Traits, Alloc > &aSequence, typename std::basic_string< CharT, Traits, Alloc >::size_type aPosition)
T from_std_string(std::string const &aValueAsString)
T from_string(i_string const &aValueAsString)
format_result format(std::string_view const &aFormat, Args &&... aArgs)
std::basic_string< CharT, Traits, Alloc > to_lower(const std::basic_string< CharT, Traits, Alloc > &aString)
std::basic_string< CharT, Traits, Alloc > to_upper(const std::basic_string< CharT, Traits, Alloc > &aString)
std::string parse_url_escapes(const std::string &aString)
bool contains_character(const CharT *aSequence, CharT aCharacter)
bool do_wildcard_match(FwdIter aTextBegin, FwdIter aTextEnd, FwdIter aPatternBegin, FwdIter aPatternEnd)
std::string & remove_leading_and_trailing(std::basic_string< CharT, Traits, Alloc > &aString, const std::basic_string< CharT, Traits, Alloc > &aLeadingTrailing)
it_type next(it_type it, const typename iterator_traits< it_type >::difference_type distance=1)
iterator_traits< it_type >::difference_type distance(const it_type first, const it_type last)
void advance(it_type &it, const distance_type distance)
comma_and_brackets_as_whitespace(std::size_t refs=0)
static const mask * make_table()
comma_as_whitespace(std::size_t refs=0)
static const mask * make_table()
comma_only_whitespace(std::size_t refs=0)
static const mask * make_table()
Traits::char_type char_type
bool operator()(char_type c1, char_type c2) const
std::pair< std::size_t, std::size_t > span
string_span(const span &aSpan, type aType=0)
string_span(std::size_t aFirst, std::size_t aSecond, type aType=0)
string_span & operator=(const span &aSpan)