48#ifndef AH_STRING_UTILS_H
49#define AH_STRING_UTILS_H
75#define strtok_r strtok_s
89 for (
size_t i = 0; i < v.size(); ++i)
107 std::ostringstream s;
108 for (
auto it = v.
get_it(); it.has_curr(); it.next_ne())
111 if (
not it.is_last())
126 auto it = std::find_if(s.begin(), s.end(), [](
const unsigned char ch)
128 return not std::isspace(ch);
130 s.erase(s.begin(), it);
142 auto it = std::find_if(s.rbegin(), s.rend(), [](
const unsigned char ch)
144 return not std::isspace(ch);
146 s.erase(it.base(), s.end());
149namespace concat_detail {
152 std::is_convertible_v<T, std::string_view>
or std::is_same_v<std::decay_t<T>,
char>;
182 if constexpr (std::is_convertible_v<T, std::string_view>)
183 return std::string(std::string_view(v));
184 else if constexpr (std::is_same_v<std::decay_t<T>,
char>)
185 return std::string(1, v);
186 else if constexpr (std::is_arithmetic_v<std::decay_t<T>>)
187 return std::to_string(v);
190 std::ostringstream s;
212template <
class...
Args>
215 if constexpr (
sizeof...(Args) == 0)
217 else if constexpr ((concat_detail::is_string_like<Args>
and ...))
228 for (
const auto &p :
pieces)
231 result.reserve(
total);
232 for (
const auto &p :
pieces)
244inline std::string
trim(
const std::string &s)
270inline bool contains(
const std::string_view &str,
const std::string_view &substr)
272 return str.find(substr) != std::string::npos;
281inline std::string
to_string(
const double d,
const size_t precision)
283 std::ostringstream s;
284 s.precision(precision);
285 s << std::fixed << d;
298 return to_string(d, std::numeric_limits<double>::max_digits10);
309 for (
const char *ptr = str; *ptr; ++ptr)
310 ret.push_back(
static_cast<char>(std::tolower(
static_cast<unsigned char>(*ptr))));
322 for (
const char *ptr = str; *ptr; ++ptr)
323 ret.push_back(
static_cast<char>(std::toupper(
static_cast<unsigned char>(*ptr))));
332inline std::string
tolower(
const std::string &str)
342inline std::string
toupper(
const std::string &str)
355 c =
static_cast<char>(std::tolower(
static_cast<unsigned char>(c)));
367 c =
static_cast<char>(std::toupper(
static_cast<unsigned char>(c)));
384 ret.reserve(str.size() + 1);
388 for (
const char c : str)
389 if ((c >=
'0' and c <=
'9')
or (c >=
'a' and c <=
'z'))
391 else if (c >=
'A' and c <=
'Z')
392 ret.push_back(
static_cast<char>(std::tolower(
static_cast<unsigned char>(c))));
406 const size_t n = str.size();
409 for (
const auto c : str)
410 if (
not std::isspace(
static_cast<unsigned char>(c)))
423 const size_t n = str.size();
426 for (
const auto c : str)
427 if (
symbols.find(c) == std::string::npos)
445inline std::ostream &
join(
const C &c,
const std::string &
sep, std::ostream &
out)
450 auto &last = c.get_last();
451 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
453 auto &curr = it.get_curr();
469inline std::string
join(
const C &c,
const std::string &
sep =
" ")
471 std::ostringstream s;
487 const char *begin = str.c_str();
490 const auto val = std::strtod(begin, &
endptr);
506 const char *begin = str.c_str();
509 const auto val = std::strtof(begin, &
endptr);
525 const char *begin = str.c_str();
544 if (str.empty()
or str[0] ==
'-')
547 const char *begin = str.c_str();
550 const auto val = std::strtoull(begin, &
endptr, 10);
568 const auto val = std::strtol(s.c_str(), &
endptr, 10);
586 const auto val = std::strtod(s.c_str(), &
endptr);
603 if (str.size() <
prefix.size())
617 str = str.substr(
prefix.size());
629 for (
const char c : str)
630 ret.push_back(
static_cast<char>(std::tolower(
static_cast<unsigned char>(c))));
642 for (
const char c : str)
643 ret.push_back(
static_cast<char>(std::toupper(
static_cast<unsigned char>(c))));
652inline std::string
to_name(
const std::string &str)
658 ret.push_back(
static_cast<char>(std::toupper(
static_cast<unsigned char>(str[0]))));
660 for (
size_t i = 1; i < str.size(); ++i)
661 ret.push_back(str[i]);
676 if (str ==
nullptr or *str ==
'\0')
678 const char *ptr = str;
679 std::string curr(1, *ptr);
681 if (std::isupper(
static_cast<unsigned char>(*ptr)))
684 curr = std::string(1, *ptr);
687 curr.push_back(*ptr);
689 if (
not curr.empty())
725inline std::vector<std::string> &
split(
const std::string &s,
727 std::vector<std::string> &
elems)
729 std::stringstream
ss(s);
732 elems.push_back(item);
743inline std::vector<std::string>
split(
const std::string &s,
const char delim)
745 std::vector<std::string>
elems;
777 std::string data = s;
778 const char *d =
delim.data();
779 const auto str = data.data();
781 for (
char *token =
strtok_r(str, d, p); token; token =
strtok_r(
nullptr, d, p))
815 return tokens.
foldl<std::string>(
"", [](
const std::string &
acu,
const std::string &token)
839inline std::pair<std::string, std::string>
split_pos(
const std::string &str,
const size_t pos)
841 ah_range_error_if(pos > str.size()) <<
"split_pos(" << str <<
", " << pos <<
"): position " << pos
842 <<
" is larger than std::string size " << str.size();
844 const char *ptr = str.data();
845 const char *
end1 = ptr + pos;
849 s1.push_back(*ptr++);
853 s2.push_back(*ptr++);
872 ah_range_error_if(n > str.size()) <<
"split_n(" << str <<
", " << n <<
"): number of parts " << n
873 <<
" is larger than std::string size " << str.
size();
875 const size_t sz = str.size() / n;
877 const char *ptr = str.data();
881 for (
size_t i = 0; i < n; ++i)
888 for (
size_t k = 0;
k < sz
and *ptr; ++
k)
912 const size_t sz =
l.
size();
918 for (
auto it =
zip_it(
m, sizes); it.has_curr(); it.next_ne())
920 auto t = it.get_curr();
922 const size_t sz =
get<1>(t);
923 const long n =
max_sz - sz;
924 for (
auto i = 0; i < n; ++i)
926 ret.append(std::move(
l));
944 const std::string
blanks(p.first > p.second.size() ? p.first - p.second.size() : 0,
' ');
945 return blanks + p.second +
" ";
961 for (
auto it = mat.get_it(); it.has_curr(); it.next_ne())
963 const auto &
row = it.get_curr();
966 const std::string
blanks(p.first > p.second.size() ? p.first - p.second.size() : 0,
' ');
967 return blanks + p.second +
" ";
993 return zip(
acu,
l).maps<
size_t>([](
const auto &p)
995 return std::max(p.first, p.second.size());
1015 for (
auto it =
curr_row.get_it(); it.has_curr(); it.next_ne())
1017 const std::string &s = it.get_curr();
1021 row.append(s +
",");
1038 std::ostringstream s;
1039 mat.for_each([&s](
const auto &
row)
1041 row.for_each([&s](
const std::string &str)
1058 std::istringstream
in(text);
1081 std::ostringstream s;
1082 for (
auto it =
lines.get_it(); it.has_curr(); it.next_ne())
1084 const auto &line = it.get_curr();
1086 if (line !=
lines.get_last())
1101 if (
size_t pos = line.find_first_of(
' '); pos != std::string::npos)
1104 pos = line.find_first_not_of(
' ', pos);
1105 if (pos == std::string::npos)
1107 line.insert(pos,
" ");
1108 pos = line.find_first_of(
' ', pos + 1);
1109 if (pos == std::string::npos)
1110 pos = line.find_first_of(
' ');
1129 std::ostringstream s;
1131 for (
const std::string &
word : words)
1132 if (line.size() +
word.size() + 1 > width)
1135 if (
not line.empty())
1144 if (
not line.empty())
1167 std::ostringstream s;
1168 s <<
lines.remove_first() <<
'\n';
1187 std::ostringstream s;
1189 for (
const std::string &
word : words)
1193 if (
not line.empty())
1195 s <<
margin << line <<
'\n';
1202 if (
not line.empty())
1225 std::ostringstream s;
1226 s <<
lines.remove_first() <<
'\n';
1239 std::ostringstream s;
1240 const std::string
fill(n,
' ');
1242 for (
auto it =
lines.get_it(); it.has_curr(); it.next_ne())
1244 const auto &line = it.get_curr();
1246 if (line !=
lines.get_last())
1261template <
typename T>
1262 requires requires(std::ostream &
out,
const T &v) {
out << v; }
1272 std::ostringstream s;
1273 if (
not str.empty())
1276 str.append(s.str());
1287template <
class T,
class...
Args>
1297template <
class First,
class...
Rest>
1298 requires(
not requires(
const std::remove_reference_t<First> &c) {
1321 requires requires(
const C &c) {
1338 auto &last = c.get_last();
1339 std::ostringstream s;
1340 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
1342 auto &curr = it.get_curr();
#define ah_runtime_error_if(C)
Throws std::runtime_error if condition holds.
#define ah_range_error_if(C)
Throws std::range_error if condition holds.
Zip iterators and functional operations for multiple containers.
size_t size_t int32_t * out
Simple dynamic array with automatic resizing and functional operations.
Doubly-linked list (defined in tpl_dynList.H).
T & append(const T &item)
T & get_last() const
Return the last item of the list.
size_t size() const noexcept
Count the number of elements of the list.
__T foldl(const __T &init, Op &op) const
Fold the elements of the container to a specific result.
void mutable_for_each(Operation &operation)
Apply a mutable operation to each element of the container.
Aleph::DynList< __T > maps(Operation &op) const
Map the elements of the container.
void for_each(Operation &operation)
Traverse all the container and performs an operation on each element.
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Singly linked list implementations with head-tail access.
size_t piece_size(std::string_view s) noexcept
std::string stringify(const T &v)
Convert any single value to std::string.
constexpr bool is_string_like
void append_to(std::string &out, std::string_view s)
Main namespace for Aleph-w library functions.
std::string tolower(const char *str)
Convert a C std::string to lower-case.
ZipIterator< Cs... > zip_it(const Cs &...cs)
Alias for get_zip_it.
bool is_prefix(const std::string &str, const std::string &prefix)
Check whether prefix is a prefix of str.
std::string remove_symbols(const std::string &str, const std::string &symbols)
Remove any character appearing in symbols.
std::string to_upper(const std::string &str)
Convert a std::string to upper-case (byte-wise).
DynList< std::string > split_text_into_lines(const std::string &text)
Split a text into lines by "\n".
std::string justify_line_except_first(const std::string &text, const size_t width, const size_t left_margin=0)
Justify all lines except the first one.
DynList< std::string > split_text_into_words(const std::string &text)
Split a text into whitespace-separated words.
Array< std::string > split_to_array(const std::string &s, const std::string &delim)
Split a std::string into an Aleph::Array<std::string>.
std::pair< std::string, std::string > split_pos(const std::string &str, const size_t pos)
Split a std::string at a fixed position.
long safe_atol(const std::string &s)
Convert a std::string to long and throw on parse errors.
void ltrim(std::string &s)
Remove leading whitespace from a std::string in-place.
std::string remove_prefix(std::string &str, const std::string &prefix)
Remove prefix from str if present.
std::string concat(const Args &...args)
Concatenate multiple arguments into a single std::string.
std::string & trim_in_place(std::string &s)
Trim a std::string in-place (leading + trailing whitespace removed).
std::string align_text_to_left(const std::string &text, const size_t page_width, const size_t left_margin=0)
Align text to the left by wrapping lines at page_width.
DynList< std::pair< typename Container1::Item_Type, typename Container2::Item_Type > > zip(const Container1 &a, const Container2 &b)
Zip two containers into a list of pairs.
void fill(Itor beg, const Itor &end, const T &value)
Fill a range with a value.
Container< std::string > split_string(const std::string &s, const std::string &delim)
Split a std::string by a set of delimiter characters.
and
Check uniqueness with explicit hash + equality functors.
std::decay_t< typename HeadC::Item_Type > T
bool contains(const std::string_view &str, const std::string_view &substr)
Check if substr appears inside str.
std::string justify_line(std::string line, const size_t page_width)
Justify a single line by inserting extra spaces.
std::string to_Pascalcase(const std::string &str)
Convert an identifier-like std::string to PascalCase.
DynList< DynList< std::string > > format_string_csv(const DynList< DynList< std::string > > &mat)
Produce a CSV-like matrix (commas added to all but last element in each row).
static void prefix(Node *root, DynList< Node * > &acc)
bool is_long(const std::string &str)
Check whether a std::string fully parses as a long.
DynList< std::string > split_n(const std::string &str, const size_t n)
Split a std::string into n parts.
std::string to_name(const std::string &str)
Uppercase the first character of str and return the resulting copy.
bool is_float(const std::string &str)
Check whether a std::string fully parses as a finite float.
bool is_size_t(const std::string &str)
Check whether a std::string fully parses as a non-negative size_t.
std::string trim(const std::string &s)
Return a trimmed copy of a std::string (leading + trailing whitespace removed).
DynList< std::string > split_camel_case(const char *const str)
Split a camelCase / PascalCase std::string into tokens.
void build_pars_list(std::string &unused)
Base case for build_pars_list(std::string&, ...).
std::string remove_spaces(const std::string &str)
Remove all whitespace characters from a std::string.
std::string to_string(const time_t t, const std::string &format)
Format a time_t value into a string using format.
std::string to_str(const double d)
Convert double to a std::string with maximum round-trip precision.
std::string justify_text(const std::string &text, const size_t width, const size_t left_margin=0)
Justify a text to a target width.
bool is_double(const std::string &str)
Check whether a std::string fully parses as a finite double.
DynList< std::string > split_to_list(const std::string &s, const std::string &delim)
Split a std::string into an Aleph::DynList<std::string>.
std::string shift_lines_to_left(const std::string &str, const size_t n)
Indent every line in a multi-line std::string by n spaces.
DynList< DynList< T > > complete_rows(DynList< DynList< T > > &m)
Pad all rows of a matrix to the maximum row length.
std::string align_text_to_left_except_first(const std::string &text, const size_t width, const size_t left_margin=0)
Align all lines except the first one.
std::string toupper(const char *str)
Convert a C std::string to upper-case.
std::ostream & join(const C &c, const std::string &sep, std::ostream &out)
Join elements of an Aleph-style container into a stream.
void rtrim(std::string &s)
Remove trailing whitespace from a std::string in-place.
std::vector< std::string > & split(const std::string &s, const char delim, std::vector< std::string > &elems)
Split a std::string by a single delimiter character.
DynList< DynList< std::string > > format_string(const DynList< size_t > &lens, const DynList< DynList< std::string > > &mat)
double safe_atof(const std::string &s)
Convert a std::string to double and throw on parse errors.
std::string to_lower(const std::string &str)
Convert a std::string to lower-case (byte-wise).
void fill_string(std::string &str, char sym)
Fill all the content of std::string with a defined char.
std::string & mutable_tolower(std::string &str)
Convert a std::string to lower-case in-place.
std::string & mutable_toupper(std::string &str)
Convert a std::string to upper-case in-place.
std::string only_alpha(const std::string &str)
Extract alphanumeric ASCII characters and normalize letters to lower-case.
FooMap m(5, fst_unit_pair_hash, snd_unit_pair_hash)
Dynamic array container with automatic resizing.