31#ifndef KBLIB_STRINGOPS_H
32#define KBLIB_STRINGOPS_H
42#include <initializer_list>
48# include <string_view>
53#if true or KBLIB_USE_CXX17
103 template <
typename T>
118 template <
typename T,
typename = arithmetic_type_t<T>>
145 template <
typename T>
152 using type = std::conditional_t<std::is_convertible_v<T, std::string>,
158 return std::forward<T>(in);
202 struct str_type<char8_t, char8_t> {
203 using type = char8_t;
204 KBLIB_NODISCARD static auto convert(
char8_t in) ->
char8_t {
return in; }
210 template <
typename T>
223template <
typename Str>
225 if constexpr (std::is_array_v<std::remove_reference_t<Str>>) {
227 }
else if constexpr (std::is_pointer_v<std::decay_t<Str>>) {
229 }
else if constexpr (is_character_v<std::decay_t<Str>>) {
231 }
else if constexpr (std::is_integral_v<std::decay_t<Str>>) {
233 }
else if constexpr (std::is_floating_point_v<std::decay_t<Str>>) {
240template <
typename CharT>
257template <
typename string,
typename F,
typename... S>
258constexpr auto append(
string&& out, F&& f, S&&... tail) ->
void {
259 if constexpr (is_character_v<std::decay_t<F>>) {
261 }
else if constexpr (std::is_arithmetic_v<std::decay_t<F>>) {
266 if constexpr (
sizeof...(S) > 0) {
274 template <std::
size_t I,
typename T>
279 template <
class Idxs,
class... Ts>
282 template <std::size_t... Idxs,
typename... Ts>
285 template <
typename string,
typename... S, std::size_t... I>
287 S&&... ins) ->
string {
311template <
typename string = std::string,
typename F,
typename... S>
313 return detail::concat_impl<string>(
314 std::make_index_sequence<1 +
sizeof...(S)>{}, std::forward<F>(f),
315 std::forward<S>(ins)...);
325template <
typename string = std::
string,
typename str>
330 ins.begin(), ins.end(), std::size_t{0},
331 [](std::size_t z,
const str& s) { return z + strsize(s); }));
332 for (
auto&& s : ins) {
352 for (
auto v :
" \t\r\n\f\v") {
360 for (
auto v : L
" \t\r\n\f\v") {
377template <
typename range,
typename string = std::
string>
379 const string& joiner =
"") {
383 begin(in), end(in), std::size_t{},
384 [](std::size_t l,
const auto& x) {
return l +
strsize(x); });
385 auto ret = *begin(in);
404template <
typename Container = std::vector<std::
string>,
typename Predicate,
409 typename Container::value_type::value_type>
::value,
412 bool delim_run =
true;
413 const char* begpos{};
414 auto endpos = begpos;
415 for (
const auto& c : in) {
422 ret.emplace_back(begpos, &c - begpos);
423 }
else if (not spacer(c)) {
430 ret.emplace_back(begpos, endpos + 1);
432 if (not delim_run and begpos != endpos) {
433 ret.emplace_back(begpos, endpos - begpos + 1);
444template <
typename Container = std::vector<std::
string>,
typename String>
456template <
typename Container = std::vector<std::
string>,
typename String>
459 typename Container::value_type::value_type delim) -> Container {
461 bool delim_run =
true;
462 using CharT =
typename Container::value_type::value_type;
463 const CharT* begpos{};
464 auto endpos = begpos;
465 for (
const CharT& c : in) {
472 ret.emplace_back(begpos, &c - begpos);
473 }
else if (c != delim) {
479 if (not delim_run and begpos != endpos) {
480 ret.emplace_back(&*begpos, endpos - begpos + 1);
485template <
typename Container = std::vector<std::
string>,
typename String>
487 char delim =
' ') -> Container {
489 bool delim_run =
true;
494 }
else if (c != delim) {
497 ret.back().push_back(c);
500 if (ret.back().empty()) {
513template <
typename Container = std::vector<std::
string>,
typename String>
515 char delim) -> Container {
517 for (std::size_t pos1{}, pos2{str.find(delim)}; pos1 != str.npos;) {
518 ret.emplace_back(str, pos1, pos2 - pos1);
520 if (pos1 != str.npos) {
534template <
typename Container = std::vector<std::
string>,
typename String,
539 typename Container::value_type::value_type>
::value,
542 for (std::size_t pos1{}, pos2{str.find(delim)}; pos1 != str.npos;) {
543 ret.emplace_back(str, pos1, pos2 - pos1);
546 if (pos1 != str.npos) {
565template <
typename string>
567 std::reverse(val.begin(), val.end());
573 template <
typename CharT>
577 template <
typename CharT,
typename IntT>
604template <
typename string>
607 [](
auto c) { return detail::tolower(c); });
617template <
typename string>
620 [](
auto c) { return detail::toupper(c); });
635template <
typename string>
639 for (std::size_t i = 0; i < count; ++i) {
654 std::size_t count) -> std::string {
655 return std::string(count, val);
658#if KBLIB_USE_STRING_VIEW
667 std::string_view needle) ->
bool {
668 return haystack.size() >= needle.size()
669 and haystack.compare(haystack.size() - needle.size(),
670 std::string_view::npos, needle)
681 char needle) ->
bool {
682 return not haystack.empty() and haystack.back() == needle;
692 std::string_view needle) ->
bool {
693 return haystack.size() >= needle.size()
694 and haystack.compare(0, needle.size(), needle) == 0;
704 char needle) ->
bool {
705 return not haystack.empty() and haystack.front() == needle;
Provides general-purpose algorithms, similar to the <algorithms> header.
GeneratorWrapper< T > value(T &&value)
Generic::PredicateMatcher< T > Predicate(std::function< bool(T const &)> const &predicate, std::string const &description="")
constexpr auto concat_impl(std::index_sequence< I... >, S &&... ins) -> string
typename str_type< T >::type str_type_t
Provides the natural stringlike type for representing a T.
typename arithmetic_type< T >::type arithmetic_type_t
Equivalent to typename arithmetic_type<T>::type.
constexpr auto to_int_type(CharT ch)
constexpr auto to_char_type(IntT ch)
constexpr auto towlower(wchar_t ch)
constexpr auto towupper(wchar_t ch)
constexpr auto size(const C &c) -> decltype(c.size())
constexpr auto exchange(T &obj, U &&new_value) -> T
auto consumer(F f) -> consume_iterator< F >
Creates a consume_iterator of deduced type F.
constexpr auto isAspace(wchar_t c) -> bool
constexpr auto repeat(char val, std::size_t count) -> std::string
Construct a string consisting of count copies of val.
constexpr auto concat(std::initializer_list< str > ins) -> string
Returns a string consisting of the concatenation of all elements of an initializer list.
constexpr auto starts_with(std::string_view haystack, char needle) -> bool
Checks if a given string starts with a particular string.
constexpr auto toupper(string str) -> string
Folds all characters in a string using the default execution character set to uppercase.
constexpr auto tolower(string str) -> string
Folds all characters in a string using the default execution character set to lowercase.
constexpr auto append(string &&out, F &&f, S &&... tail) -> void
Given an object out of resizable stringlike type string, appends all other arguments to it.
constexpr auto kbsplit2(const String &in, char delim=' ') -> Container
constexpr auto isspace(wchar_t c) -> bool
auto try_reserve(C &c, std::size_t s) noexcept(noexcept(c.reserve(s))) -> void
Attempt to reserve capacity in a container. No-op if unsupported.
constexpr bool is_character_v
Equivalent to is_character<C>::value.
constexpr auto range(Value min, Value max, Delta step=0) -> range_t< Value, Delta >
Constructs a range from beginning, end, and step amount. The range is half-open, that is min is in th...
constexpr auto length(const CharT *str) noexcept -> std::size_t
constexpr auto to_string(Int num) -> std::string
typename std::decay< T >::type decay_t
constexpr auto reverse_str(string val) -> string
Reverses all the elements of its input.
constexpr auto count_digits(Number val) -> enable_if_t< std::is_floating_point< Number >::value, int >
Calculates the number of decimal digits needed to represent a number, plus one for negative numbers.
constexpr auto accumulate(InputIt first, InputIt last, T init) -> T
A constexpr version of std::accumulate.
constexpr auto copy(InputIt first, EndIt last, OutputIt out) -> OutputIt
Copies all elements of [first, last) to out. It also allows for a sentinel end iterator.
constexpr auto split_tokens(const String &in, typename Container::value_type::value_type delim) -> Container
Split a string on all instances of a delimiter.
typename return_assert< V, T >::type return_assert_t
constexpr auto ends_with(std::string_view haystack, char needle) -> bool
Checks if a given string ends with a particular string.
constexpr auto split_dsv(const String &str, Predicate delim) -> return_assert_t< is_callable< Predicate, typename Container::value_type::value_type >::value, Container >
Split a string on all instances of delim.
constexpr auto join(const range &in, const string &joiner="")
Concatenates all elements of a range together with an optional joiner.
constexpr auto find_in_if(ForwardIt begin, EndIt end, UnaryPredicate pred) noexcept(noexcept(kblib::invoke(pred, *begin))) -> size_t
Find the offset of the first element for which p returns true. It also allows for a sentinel end iter...
constexpr auto to_unsigned(I x) -> std::make_unsigned_t< I >
Cast integral argument to corresponding unsigned type.
constexpr auto strsize(Str &&str) -> std::size_t
Determines the size in characters of any valid argument to concat or append.
constexpr auto transform(InputIt first, EndIt last, OutputIt d_first, UnaryOperation unary_op) -> OutputIt
transform applies the given function to a range and stores the result in another range,...
Determines if T is a type in Tuple, which must be a std::tuple.
Filter only arithmetic types.
static auto convert(T &&in) -> type
Returns the potentially-converted argument.
std::conditional_t< std::is_convertible_v< T, std::string >, std::string, T > type
Non-arithmetic types are either already stringlike, are convertible to std::string,...
static auto convert(char16_t in) -> char16_t
static auto convert(char32_t in) -> char32_t
static auto convert(char in) -> char
static auto convert(wchar_t in) -> wchar_t
Converts types to strings.
std::string type
Arithmetic types can be converted into strings using the standard library.
static auto convert(T in) -> std::string
Forwards to std::to_string.
Determine if the given type, ignoring const or reference qualifiers, is a character type.
auto operator()(wchar_t c) -> bool
auto operator()(char c) -> bool
Provides macros and basic templates used by the rest of kblib.
#define KBLIB_NODISCARD
This internal macro is used to provide a fallback for [[nodiscard]] in C++14.
Contains some type traits not in the standard library that are useful in the implementation of kblib.