28 inline static size_t adjust(
const std::string &s,
size_t width) {
29 for (
unsigned char c : s) {
32 }
else if (c >= 0xF8) {
34 }
else if (c >= 0xF0) {
36 }
else if (c >= 0xE0) {
38 }
else if (c == 0xCC || c == 0xCD) {
41 }
else if (c >= 0xC0) {
48 std::string
fill_left(
const std::string &s,
size_t width,
char fill) {
49 width =
adjust(s, width - s.size());
51 return std::string(width, fill) + s;
56 std::string
fill_right(
const std::string &s,
size_t width,
char fill) {
57 width =
adjust(s, width - s.size());
59 return s + std::string(width, fill);
64 std::string
fill_both(
const std::string &s,
size_t width,
char fill) {
65 width =
adjust(s, width - s.size());
67 const int l = width / 2;
68 const int r = width - l;
69 return std::string(l, fill) + s + std::string(r, fill);
76 std::string
trim(
const std::string &s) {
77 const auto begin = s.find_first_not_of(
" \t\n\r");
78 if (begin == std::string::npos) {
81 const auto end = s.find_last_not_of(
" \t\n\r");
82 return s.substr(begin, end - begin + 1);
86 using str = std::string;
87 str::size_type
n =
p.length();
88 for (str::size_type i = s.find(
p); i != str::npos; i = s.find(
p)) {
108 template <
typename Out>
109 void split(
const std::string &s,
char delim, Out result);
111 template <
typename Out>
112 void split(
const std::string &s,
char delim, Out result) {
113 std::stringstream ss;
116 while (std::getline(ss, item, delim)) {
121 std::vector<std::string>
split(
const std::string &s,
char delim) {
122 std::vector<std::string> elems;
123 split(s, delim, std::back_inserter(elems));
127 template <
typename Container>
128 static std::string
join_impl(
const Container &container,
129 std::string_view delim) {
133 using value_type = std::decay_t<decltype(*begin(container))>;
137 std::is_convertible_v<value_type, std::string_view>,
138 "join() requires string-like objects convertible to std::string_view!");
139 auto it = begin(container);
140 const auto last = end(container);
144 std::size_t total_size = 0;
145 std::size_t count = 0;
146 for (
const auto &s : container) {
147 total_size += std::string_view{s}.size();
150 total_size += delim.size() * (count - 1);
151 std::string result{};
152 result.reserve(total_size);
153 result.append(std::string_view{*it});
155 for (; it != last; ++it) {
156 result.append(delim);
157 result.append(std::string_view{*it});
162 std::string
join(
const std::vector<std::string> &v, std::string_view delim) {
166 std::string
join(
const std::vector<std::string_view> &v,
167 std::string_view delim) {
171 std::string
join(
const std::set<std::string> &s, std::string_view delim) {
175 std::string
quote(
const std::string &s) {
return "\"" + s +
"\""; }
std::string fill_right(const std::string &s, size_t width, char fill=' ')
Fill string with characters to the right until the given width is reached.
static size_t adjust(const std::string &s, size_t width)
Adjust filling width by taking the size of unicode characters into account.
std::string fill_both(const std::string &s, size_t width, char fill=' ')
Fill string with characters at both sides until the given width is reached.
std::string fill_left(const std::string &s, size_t width, char fill=' ')
Fill string with characters to the left until the given width is reached.
std::vector< std::string > split(const std::string &s, char delim)
Split string by delimiter.
std::string quote(const std::string &s)
Add quotes around string.
std::string trim(const std::string &s)
Strip leading and trailing whitespaces.
static std::string join_impl(const Container &container, std::string_view delim)
std::string join(const std::vector< std::string > &v, std::string_view delim)
Join strings using delimiter.
void isoclean(std::string &s)
Remove ⁺, ⁻, ⁰ from string.
void remove_substr(std::string &s, const std::string &p)
Remove all instances of a substring p in a string s.