lokinet/llarp/util/str.hpp
Jason Rhinelander 9950adf472 Remove unneeded split(str, char) method
This function had a bug in stable (fixed in dev) when `last` returns
npos, but the function also appears to basically be duplicating what the
next split version can do, so this just removes it and uses the single
more generic split(strview, strview) method.
2021-08-11 00:26:52 -03:00

149 lines
4.9 KiB
C++

#pragma once
#include <string_view>
#include <sstream>
#include <vector>
#include <chrono>
#include <iterator>
#include <charconv>
namespace llarp
{
bool
IsFalseValue(std::string_view str);
struct CaselessLessThan
{
bool
operator()(std::string_view lhs, std::string_view rhs) const;
};
bool
IsTrueValue(std::string_view str);
/// Trim leading and trailing (ascii) whitespace from the given string;
/// returns a std::string_view of the trimmed part of the string.
[[nodiscard]] std::string_view
TrimWhitespace(std::string_view str);
template <typename... T>
std::string
stringify(T&&... stuff)
{
std::ostringstream o;
(o << ... << std::forward<T>(stuff));
return o.str();
}
using namespace std::literals;
/// Returns true if the first string is equal to the second string, compared case-insensitively.
inline bool
string_iequal(std::string_view s1, std::string_view s2)
{
return std::equal(s1.begin(), s1.end(), s2.begin(), s2.end(), [](char a, char b) {
return std::tolower(static_cast<unsigned char>(a))
== std::tolower(static_cast<unsigned char>(b));
});
}
/// Returns true if the first string matches any of the given strings case-insensitively.
/// Arguments must be string literals, std::string, or std::string_views
template <typename S1, typename... S>
bool
string_iequal_any(const S1& s1, const S&... s)
{
return (... || string_iequal(s1, s));
}
/// Returns true if the first argument begins with the second argument
inline bool
starts_with(std::string_view str, std::string_view prefix)
{
return str.substr(0, prefix.size()) == prefix;
}
/// Returns true if the first argument ends with the second argument
inline bool
ends_with(std::string_view str, std::string_view suffix)
{
return str.size() >= suffix.size() && str.substr(str.size() - suffix.size()) == suffix;
}
/// Splits a string on some delimiter string and returns a vector of string_view's pointing into
/// the pieces of the original string. The pieces are valid only as long as the original string
/// remains valid. Leading and trailing empty substrings are not removed. If delim is empty you
/// get back a vector of string_views each viewing one character. If `trim` is true then leading
/// and trailing empty values will be suppressed.
///
/// auto v = split("ab--c----de", "--"); // v is {"ab", "c", "", "de"}
/// auto v = split("abc", ""); // v is {"a", "b", "c"}
/// auto v = split("abc", "c"); // v is {"ab", ""}
/// auto v = split("abc", "c", true); // v is {"ab"}
/// auto v = split("-a--b--", "-"); // v is {"", "a", "", "b", "", ""}
/// auto v = split("-a--b--", "-", true); // v is {"a", "", "b"}
///
std::vector<std::string_view>
split(std::string_view str, std::string_view delim, bool trim = false);
/// Splits a string on any 1 or more of the given delimiter characters and returns a vector of
/// string_view's pointing into the pieces of the original string. If delims is empty this works
/// the same as split(). `trim` works like split (suppresses leading and trailing empty string
/// pieces).
///
/// auto v = split_any("abcdedf", "dcx"); // v is {"ab", "e", "f"}
std::vector<std::string_view>
split_any(std::string_view str, std::string_view delims, bool trim = false);
/// Joins [begin, end) with a delimiter and returns the resulting string. Elements can be
/// anything that can be sent to an ostream via `<<`.
template <typename It>
std::string
join(std::string_view delimiter, It begin, It end)
{
std::ostringstream o;
if (begin != end)
o << *begin++;
while (begin != end)
o << delimiter << *begin++;
return o.str();
}
/// Wrapper around the above that takes a container and passes c.begin(), c.end() to the above.
template <typename Container>
std::string
join(std::string_view delimiter, const Container& c)
{
return join(delimiter, c.begin(), c.end());
}
/// Simple version of whitespace trimming: mutates the given string view to remove leading
/// space, \t, \r, \n. (More exotic and locale-dependent whitespace is not removed).
void
trim(std::string_view& s);
/// Parses an integer of some sort from a string, requiring that the entire string be consumed
/// during parsing. Return false if parsing failed, sets `value` and returns true if the entire
/// string was consumed.
template <typename T>
bool
parse_int(const std::string_view str, T& value, int base = 10)
{
T tmp;
auto* strend = str.data() + str.size();
auto [p, ec] = std::from_chars(str.data(), strend, tmp, base);
if (ec != std::errc() || p != strend)
return false;
value = tmp;
return true;
}
std::string
lowercase_ascii_string(std::string src);
/// Converts a duration into a human friendlier string.
std::string
friendly_duration(std::chrono::nanoseconds dur);
} // namespace llarp