49# ifndef AH_STRING_UTILS_H
50# define AH_STRING_UTILS_H
59# include <string_view>
60# include <type_traits>
83 for (
size_t i = 0; i < v.size(); ++i)
101 std::ostringstream s;
102 for (
auto it = v.
get_it(); it.has_curr(); it.next_ne())
105 if (
not it.is_last())
120 s.erase(s.begin(), std::find_if(s.begin(), s.end(),
121 [](
const unsigned char ch)
123 return not std::isspace(ch);
136 s.erase(std::find_if(s.rbegin(), s.rend(),
137 [](
const unsigned char ch)
139 return not std::isspace(ch);
152 template <
class...
Args>
155 std::ostringstream s;
166 inline std::string
trim(
const std::string & s)
192 inline bool contains(
const std::string_view & str,
const std::string_view &
substr)
194 return str.find(
substr) != std::string::npos;
203 inline std::string
to_string(
const double d,
const size_t precision)
205 std::ostringstream s;
206 s.precision(precision);
207 s << std::fixed << d;
218 inline std::string
to_str(
const double d)
220 return to_string(d, std::numeric_limits<double>::max_digits10);
231 for (
const char *ptr = str; *ptr; ++ptr)
232 ret.push_back(
static_cast<char>(std::tolower(
static_cast<unsigned char>(*ptr))));
244 for (
const char *ptr = str; *ptr; ++ptr)
245 ret.push_back(
static_cast<char>(std::toupper(
static_cast<unsigned char>(*ptr))));
254 inline std::string
tolower(
const std::string & str)
264 inline std::string
toupper(
const std::string & str)
277 c =
static_cast<char>(std::tolower(
static_cast<unsigned char>(c)));
289 c =
static_cast<char>(std::toupper(
static_cast<unsigned char>(c)));
306 ret.reserve(str.size() + 1);
307 for (
const char c: str)
315 ret.push_back(
static_cast<char>(std::tolower(
static_cast<unsigned char>(c))));
333 const size_t n = str.
size();
336 for (
const auto c: str)
337 if (
not std::isspace(
static_cast<unsigned char>(c)))
350 const size_t n = str.
size();
353 for (
const auto c: str)
354 if (
symbols.find(c) == std::string::npos)
372 inline std::ostream &
join(
const C & c,
const std::string &
sep, std::ostream &
out)
378 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
380 auto & curr = it.get_curr();
396 inline std::string
join(
const C & c,
const std::string &
sep =
" ")
398 std::ostringstream s;
414 const char *begin = str.c_str();
433 const char *begin = str.c_str();
452 const char *begin = str.c_str();
471 if (str.empty()
or str[0] ==
'-')
474 const char *begin = str.c_str();
477 const auto val = std::strtoull(begin, &
endptr, 10);
496 const auto val = std::strtol(s.c_str(), &
endptr, 10);
516 const auto val = std::strtod(s.c_str(), &
endptr);
519 (
errno != 0 && val == 0) ||
534 if (str.size() <
prefix.size())
548 str = str.substr(
prefix.size());
557 inline std::string
to_lower(
const std::string & str)
560 for (
const char c: str)
561 ret.push_back(
static_cast<char>(std::tolower(
static_cast<unsigned char>(c))));
570 inline std::string
to_upper(
const std::string & str)
573 for (
const char c: str)
574 ret.push_back(
static_cast<char>(std::toupper(
static_cast<unsigned char>(c))));
583 inline std::string
to_name(
const std::string & str)
589 ret.push_back(
static_cast<char>(std::toupper(
static_cast<unsigned char>(str[0]))));
591 for (
size_t i = 1; i < str.size(); ++i)
592 ret.push_back(str[i]);
607 if (str ==
nullptr or *str ==
'\0')
609 const char *ptr = str;
610 std::string curr(1, *ptr);
612 if (std::isupper(
static_cast<unsigned char>(*ptr)))
615 curr = std::string(1, *ptr);
618 curr.push_back(*ptr);
656 inline std::vector<std::string> &
659 std::stringstream
ss(s);
662 elems.push_back(item);
673 inline std::vector<std::string>
split(
const std::string & s,
const char delim)
675 std::vector<std::string>
elems;
707 std::string data = s;
708 const char *d =
delim.data();
709 const auto str = data.data();
725 const std::string &
delim)
747 return tokens.
foldl<std::string>(
"", [](
const std::string &
acu,
const std::string &
token)
760 const std::string &
delim)
772 inline std::pair<std::string, std::string>
split_pos(
const std::string & str,
const size_t pos)
775 <<
"split_pos(" << str <<
", " << pos <<
"): position " << pos
776 <<
" is larger than std::string size " << str.size();
779 const char *ptr = str.data();
780 const char *
end1 = ptr + pos;
784 s1.push_back(*ptr++);
788 s2.push_back(*ptr++);
808 <<
"split_n(" << str <<
", " << n <<
"): number of parts " << n
809 <<
" is larger than std::string size " << str.
size();
811 const size_t sz = str.size() / n;
813 const char *ptr = str.data();
817 for (
size_t i = 0; i < n; ++i)
824 for (
size_t k = 0;
k < sz
and *ptr; ++
k)
842 template <
typename T>
849 const size_t sz =
l.
size();
855 for (
auto it =
zip_it(m,
sizes); it.has_curr(); it.next_ne())
857 auto t = it.get_curr();
859 const size_t sz =
get<1>(t);
860 const long n =
max_sz - sz;
861 for (
auto i = 0; i < n; ++i)
882 const std::string
blanks(p.first > p.second.size() ?
883 p.first - p.second.size() :
885 return blanks + p.second +
" ";
900 for (
auto it = mat.get_it(); it.has_curr(); it.next_ne())
902 const auto &
row = it.get_curr();
903 auto line =
zip(lens,
row).
906 const std::string
blanks(p.first > p.second.size() ?
907 p.first - p.second.size() :
909 return blanks + p.second +
" ";
940 return std::max(p.first, p.second.size());
963 const std::string & s = it.get_curr();
984 std::ostringstream s;
1004 std::istringstream
in(
text);
1027 std::ostringstream s;
1028 for (
auto it =
lines.
get_it(); it.has_curr(); it.next_ne())
1030 const auto & line = it.get_curr();
1047 if (
size_t pos = line.find_first_of(
' '); pos != std::string::npos)
1050 pos = line.find_first_not_of(
' ', pos);
1051 if (pos == std::string::npos)
1053 line.insert(pos,
" ");
1054 pos = line.find_first_of(
' ', pos + 1);
1055 if (pos == std::string::npos)
1056 pos = line.find_first_of(
' ');
1075 std::ostringstream s;
1077 for (
const std::string &
word: words)
1078 if (line.size() +
word.
size() + 1 > width)
1113 std::ostringstream s;
1133 std::ostringstream s;
1135 for (
const std::string &
word: words)
1141 s <<
margin << line <<
'\n';
1171 std::ostringstream s;
1185 std::ostringstream s;
1186 const std::string
fill(n,
' ');
1188 for (
auto it =
lines.
get_it(); it.has_curr(); it.next_ne())
1190 const auto & line = it.get_curr();
1207 template <
typename T>
1208 requires requires(std::ostream &
out,
const T & v)
1221 std::ostringstream s;
1236 template <
class T,
class...
Args>
1246 template <
class First,
class...
Rest>
1247 requires (
not requires(
const std::remove_reference_t<First> & c)
1271 requires requires(
const C & c)
1289 auto & last = c.get_last();
1290 std::ostringstream s;
1291 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
1293 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.
Simple dynamic array with automatic resizing and functional operations.
Dynamic singly linked list with functional programming support.
T & append(const T &item)
Append a new item by copy.
T & get_last() const
Return the last item of the list.
void empty() noexcept
empty the list
constexpr bool is_empty() const noexcept
Return true if list is empty.
size_t size() const noexcept
Count the number of elements of the list.
void mutable_for_each(Operation &operation)
__T foldl(const __T &init, Op &op) const
Fold the elements of the container to a specific result.
void for_each(Operation &operation)
Traverse all the container and performs an operation on each element.
Aleph::DynList< __T > maps(Operation &op) const
Map the elements of the container.
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
Singly linked list implementations with head-tail access.
Main namespace for Aleph-w library functions.
std::string tolower(const char *str)
Convert a C std::string to lower-case.
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 & 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.
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.
std::string concat(const Args &... args)
Concatenate multiple streamable arguments into a single std::string.
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.
ZipIterator< Cs... > zip_it(const Cs &... cs)
Alias for get_zip_it.
std::string & mutable_toupper(std::string &str)
Convert a std::string to upper-case in-place.
DynList< T > maps(const C &c, Op op)
Classic map operation.
std::string only_alpha(const std::string &str)
Extract alphanumeric ASCII characters and normalize letters to lower-case.
Dynamic array container with automatic resizing.