41std::string
ltrim(
const std::string &s);
49std::string
rtrim(
const std::string &s);
57std::string
trim(
const std::string &s);
87std::string
get_env(
const std::string &name);
136template <
typename T,
typename S>
139 if (T *
const converted =
dynamic_cast<T *
>(p.get())) {
140 std::move(p).release();
141 return std::unique_ptr<T>{converted};
154 const std::string &separator,
const std::string &input);
169std::vector<std::string>
split(
170 std::string str, std::string_view delimiter,
bool skip_empty =
true);
182template <
typename T,
typename F>
void erase_if(std::vector<T> &v, F &&f)
184 v.erase(std::remove_if(v.begin(), v.end(), std::forward<F>(f)), v.end());
195 const std::vector<std::string> &toks, std::string_view delimiter);
205template <
typename... Args>
206std::string
join(std::string_view delimiter, Args... args)
208 std::vector<std::string> coll{args...};
211 return s.find_first_not_of(
" \t") == std::string::npos;
214 return fmt::format(
"{}", fmt::join(coll, delimiter));
225std::string
abbreviate(
const std::string &s,
unsigned int max_length);
238 const std::string &input, std::tuple<std::string, size_t, size_t> &result);
247bool replace_all(std::string &input,
const std::string &pattern,
248 const std::string &replace_with);
257template <
typename T>
void append(std::vector<T> &l,
const std::vector<T> &r)
259 l.insert(l.end(), r.begin(), r.end());
270template <
typename T>
bool starts_with(
const T &col,
const T &prefix)
272 if (prefix.size() > col.size())
275 return std::search(col.begin(), col.end(), prefix.begin(), prefix.end()) ==
279template <>
bool starts_with(
const std::string &s,
const std::string &prefix);
281template <
typename T>
bool ends_with(
const T &value,
const T &suffix);
283template <>
bool ends_with(
const std::string &value,
const std::string &suffix);
286bool ends_with(
const std::vector<T> &col,
const std::vector<T> &suffix)
288 if (suffix.size() > col.size())
291 return std::vector<std::string>(suffix.rbegin(), suffix.rend()) ==
292 std::vector<std::string>(col.rbegin(), col.rbegin() + suffix.size());
308 col = std::vector<T>(col.begin() + prefix.size(), col.end());
320template <
typename T,
typename E>
323 if constexpr (std::is_pointer_v<E>) {
324 return std::find_if(container.begin(), container.end(),
325 [&element](
const auto &e) { return *e == *element; }) !=
328 else if constexpr (std::is_same_v<std::remove_cv_t<T>, std::string>) {
329 return container.find(element) != std::string::npos;
332 return std::find(container.begin(), container.end(), element) !=
337template <
typename T,
typename F>
void for_each(
const T &collection, F &&func)
339 std::for_each(std::begin(collection), std::end(collection),
340 std::forward<
decltype(func)>(func));
343template <
typename R,
typename T,
typename F>
344std::vector<R>
map(
const std::vector<T> &in, F &&f)
348 in.cbegin(), in.cend(), std::back_inserter(out), std::forward<F>(f));
352template <
typename T,
typename F,
typename FElse>
355 if (pointer !=
nullptr) {
356 std::forward<F>(func)(pointer);
359 std::forward<FElse>(func_else)();
363template <
typename T,
typename F>
void if_not_null(
const T *pointer, F &&func)
365 if_not_null(pointer, std::forward<F>(func), []() {});
368template <
typename F,
typename FElse>
369void _if(
const bool condition, F &&func, FElse &&func_else)
372 std::forward<F>(func)();
375 std::forward<FElse>(func_else)();
379template <
typename F>
void _if(
const bool condition, F &&func)
381 _if(condition, std::forward<F>(func), []() {});
386 std::sort(coll.begin(), coll.end());
387 coll.erase(std::unique(coll.begin(), coll.end()), coll.end());
407std::string
path_to_url(
const std::filesystem::path &p);
420 const std::filesystem::path &root = std::filesystem::current_path());
431 const std::filesystem::path &parent,
const std::filesystem::path &child);
437 const std::map<std::string, std::string> &m,
const std::string &prefix);