...
This commit is contained in:
@@ -1,12 +1,16 @@
|
||||
#include <list>
|
||||
#include <print>
|
||||
|
||||
// #include "../utils/snplib_string.h"
|
||||
// #include "../include/snipplib/snplib_string.h"
|
||||
#include <snipplib/utils/snplib_keyvalue.h>
|
||||
#include <snipplib/utils/snplib_string.h>
|
||||
|
||||
using namespace snplib;
|
||||
int main()
|
||||
{
|
||||
std::string si = " dewf wek e lwekjflkj ";
|
||||
std::println("s = '{}'", si);
|
||||
|
||||
auto s = snplib_trim_spaces(si);
|
||||
|
||||
@@ -24,6 +28,15 @@ int main()
|
||||
|
||||
std::println("sv(TrimType::TRIM_BOTH) = '{}'", sv);
|
||||
|
||||
const char cstr[] = " dwelkj 3827 dwjh 2398 ";
|
||||
std::println("C-ish string: '{}'", cstr);
|
||||
std::println("C-ish(TrimType::TRIM_BOTH) = '{}'", snplib_trim_spaces_as_view(cstr));
|
||||
|
||||
std::list ll{' ', ' ', '2', ' ', 'e', '4', 's', ' ', ' '};
|
||||
std::println("std::list: {}", ll);
|
||||
std::println("std::ranges::subrange(TrimType::TRIM_BOTH) = '{}'", snplib_trim_spaces_as_view(ll));
|
||||
// std::println("std::ranges::subrange(TrimType::TRIM_BOTH) = '{}'",
|
||||
// std::views::all(snplib_trim_spaces_as_view(ll)));
|
||||
|
||||
si = "123; we; d34534; ";
|
||||
|
||||
@@ -32,16 +45,45 @@ int main()
|
||||
|
||||
std::println("\n\nstr = '{}'", si);
|
||||
|
||||
std::println("all elems: ");
|
||||
std::print("all elems: ");
|
||||
for (auto& el : rv) {
|
||||
std::println("el = '{}'", el);
|
||||
std::print("'{}' ", el);
|
||||
}
|
||||
std::println("");
|
||||
|
||||
rv = snplib_split_char_range<decltype(rv)>(si, "; ", 1, 2);
|
||||
std::println("2 elems starting from 1: ");
|
||||
std::print("2 elems starting from 1: ");
|
||||
for (auto& el : rv) {
|
||||
std::println("el = '{}'", el);
|
||||
std::print("'{}' ", el);
|
||||
}
|
||||
std::println("");
|
||||
|
||||
|
||||
si = " ATTR AAA 1.1 23 45 09 ";
|
||||
std::vector v{std::from_range, si};
|
||||
ll = {std::from_range, si};
|
||||
|
||||
snplib_keyvalue_t kv{v};
|
||||
|
||||
std::println("\n\nKV = {}", v);
|
||||
std::println("key = '{}'", kv.key());
|
||||
std::println("value = '{}'", kv.value());
|
||||
std::println("valueSeq = '{}'", kv.valueSeq());
|
||||
std::println("valueJoinSeq = '{}'", kv.valueJoinSeq<std::string_view>(3, 3));
|
||||
std::println("valueJoinSeq = '{}'", kv.valueJoinSeq<std::string_view>(3, 30));
|
||||
kv.setKeyValue("VAL", std::make_tuple(1, std::string{"RRR"}, 10.24));
|
||||
std::println("\n\nKV = {}", v);
|
||||
|
||||
snplib_keyvalue_t kvl{ll};
|
||||
|
||||
std::println("\n\nKV = {}", ll);
|
||||
std::println("key = '{}'", kvl.key());
|
||||
std::println("key = '{}'", kvl.key<std::string>());
|
||||
std::println("value = '{}'", kvl.value());
|
||||
std::println("valueSeq = '{}'", kvl.valueSeq());
|
||||
std::println("valueSeq = '{}'", kvl.valueSeq<std::list<std::string>>());
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -127,7 +127,7 @@ template <typename T>
|
||||
concept snplib_error_c = std::constructible_from<T> && requires(T&& t) {
|
||||
static_cast<bool>(std::forward<T>(t));
|
||||
|
||||
{ !std::forward<T>(t) } -> std::convertible_to<bool>;
|
||||
// { !std::forward<T>(t) } -> std::convertible_to<bool>;
|
||||
};
|
||||
|
||||
// utility function to deduce error-type
|
||||
|
||||
@@ -214,6 +214,16 @@ struct snplib_deserializer_error_category_t : public std::error_category {
|
||||
};
|
||||
|
||||
|
||||
inline std::error_code make_error_code(snplib_serializer_error_e ec)
|
||||
{
|
||||
return std::error_code(static_cast<int>(ec), snplib_serializer_error_category_t::get());
|
||||
}
|
||||
|
||||
inline std::error_code make_error_code(snplib_deserializer_error_e ec)
|
||||
{
|
||||
return std::error_code(static_cast<int>(ec), snplib_deserializer_error_category_t::get());
|
||||
}
|
||||
|
||||
|
||||
/* BASE SERIALIZER CLASS (FOR IMPLEMENTATIONS BELOW) */
|
||||
|
||||
@@ -370,7 +380,7 @@ struct snplib_serializer_t : snplib_serializer_base_t {
|
||||
return snplib_serializer_base_t::serializeRange<value_t>(sr, value, output, params);
|
||||
}
|
||||
} else if constexpr (snplib_tuple_like_c<VT>) {
|
||||
return [&output, ¶ms]<size_t I = 0>(this auto& self, VT& tp) -> error_t {
|
||||
return [&output, ¶ms]<size_t I = 0>(this auto&& self, VT const& tp) -> error_t {
|
||||
if constexpr (I < (std::tuple_size_v<VT> - 1)) {
|
||||
auto err = snplib_serializer_t<std::tuple_element_t<I, VT>>{}(output, std::get<I>(tp), params);
|
||||
if (err) {
|
||||
@@ -379,8 +389,9 @@ struct snplib_serializer_t : snplib_serializer_base_t {
|
||||
|
||||
snplib_serializer_base_t::addElemDelimiter(output, params);
|
||||
|
||||
return self.template operator()<I + 1>(tp);
|
||||
} else if constexpr (I < (std::tuple_size_v<VT> - 1)) { // the last element
|
||||
return std::forward<decltype(self)>(self).template operator()<I + 1>(tp);
|
||||
// } else if constexpr (I < (std::tuple_size_v<VT> - 1)) { // the last element
|
||||
} else { // the last element
|
||||
auto err = snplib_serializer_t<std::tuple_element_t<I, VT>>{}(output, std::get<I>(tp), params);
|
||||
if (err) {
|
||||
return snplib_deduced_error(err, snplib_serializer_error_e::ERROR_UNDERLYING_SERIALIZER);
|
||||
|
||||
@@ -11,11 +11,12 @@ concept snplib_serializable_c =
|
||||
requires { []<typename VT>(std::type_identity<VT>) {}(std::type_identity<std::remove_cvref_t<T>>{}); };
|
||||
|
||||
template <snplib_char_range_c ByteSeqT>
|
||||
requires(std::ranges::viewable_range<ByteSeqT> && !std::ranges::borrowed_range<ByteSeqT>)
|
||||
class snplib_keyvalue_t
|
||||
{
|
||||
public:
|
||||
static constexpr bool mutableContent = snplib_output_char_range_c<ByteSeqT>;
|
||||
static constexpr bool stringViewContent =
|
||||
static constexpr bool contiguousContent =
|
||||
std::ranges::viewable_range<ByteSeqT> && std::ranges::contiguous_range<ByteSeqT>;
|
||||
|
||||
typedef std::error_code error_t;
|
||||
@@ -28,79 +29,100 @@ public:
|
||||
std::string_view valseq_delim{DEFAULT_VALSEQ_DELIM_SEQ};
|
||||
};
|
||||
|
||||
constexpr snplib_keyvalue_t(ByteSeqT&& bytes, config_t cfg = config_t{}) {}
|
||||
constexpr snplib_keyvalue_t(ByteSeqT& bytes, config_t cfg = config_t{}) : _byteSeq(bytes), _config(cfg)
|
||||
{
|
||||
fromByteSequence(bytes, cfg);
|
||||
}
|
||||
|
||||
virtual ~snplib_keyvalue_t() = default;
|
||||
|
||||
template <snplib_char_range_c R>
|
||||
requires mutableContent
|
||||
error_t fromByteSequence(R&& bytes)
|
||||
error_t fromByteSequence(ByteSeqT& bytes, config_t cfg = config_t{})
|
||||
{
|
||||
_byteSeq = bytes;
|
||||
_config = cfg;
|
||||
|
||||
// key and value
|
||||
|
||||
if constexpr (stringViewContent) {
|
||||
auto bs = snplib_trim_spaces_as_view(bytes, TrimType::TRIM_LEFT);
|
||||
auto found = std::ranges::search(bs, _config.keyval_delim);
|
||||
auto bs = snplib_trim_spaces_as_view(bytes, TrimType::TRIM_LEFT);
|
||||
auto found = std::ranges::search(bs, _config.keyval_delim);
|
||||
|
||||
if (found.empty()) { // no value
|
||||
_key = snplib_trim_spaces_as_view(bs, TrimType::TRIM_RIGHT);
|
||||
if (found.empty()) { // no value
|
||||
_key = snplib_trim_spaces_as_view(bs, TrimType::TRIM_RIGHT);
|
||||
|
||||
_value = std::string_view();
|
||||
} else {
|
||||
_key = snplib_trim_spaces_as_view(std::string_view(bs.begin(), found.begin()), TrimType::TRIM_RIGHT);
|
||||
_value = decltype(_value)();
|
||||
} else {
|
||||
_key = snplib_trim_spaces_as_view(decltype(_key)(bs.begin(), found.begin()), TrimType::TRIM_RIGHT);
|
||||
|
||||
// do not delete space at the end of value-string!
|
||||
_value = std::string_view(found.end(), bs.end());
|
||||
}
|
||||
|
||||
} else if constexpr (std::ranges::viewable_range<R>) {
|
||||
auto bs = bytes | std::views::drop_while(snplib_is_space);
|
||||
auto found = std::ranges::search(bs, _config.keyval_delim);
|
||||
|
||||
_value.clear();
|
||||
|
||||
if (found.empty()) { // no value
|
||||
_key = snplib_trim_spaces(bs, TrimType::TRIM_RIGHT);
|
||||
} else {
|
||||
_key.clear();
|
||||
auto N = std::ranges::distance(bs.begin(), found.begin());
|
||||
std::ranges::copy(std::views::all(bs) | std::views::take(N) | std::views::reverse |
|
||||
std::views::drop_while(snplib_is_space),
|
||||
std::back_inserter(_key));
|
||||
|
||||
std::ranges::copy(found.end(), bs.end(), std::back_inserter(_value));
|
||||
}
|
||||
} else { // always coping
|
||||
auto bs = snplib_trim_spaces(bytes, TrimType::TRIM_LEFT);
|
||||
auto found = std::ranges::search(bs, _config.keyval_delim);
|
||||
|
||||
_value.clear();
|
||||
|
||||
if (found.empty()) { // no value
|
||||
_key = snplib_trim_spaces(bs, TrimType::TRIM_RIGHT);
|
||||
} else {
|
||||
_key.clear;
|
||||
auto N = std::ranges::distance(bs.begin(), found.begin());
|
||||
// std::ranges::copy_n(bs.begin(), N, std::back_inserter(_key));
|
||||
|
||||
size_t i = 0;
|
||||
for (auto it = bs.begin(); it != found.begin(); ++it, ++i) {
|
||||
if (i < N) {
|
||||
if (!snplib_is_space(*it)) {
|
||||
std::back_inserter(_key) = *it;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::ranges::copy(found.end(), bs.end(), std::back_inserter(_value));
|
||||
// do not delete space at the end of value-string!
|
||||
_value = decltype(_value)(found.end(), bs.end());
|
||||
}
|
||||
|
||||
|
||||
// if constexpr (contiguousContent) {
|
||||
// auto bs = snplib_trim_spaces_as_view(bytes, TrimType::TRIM_LEFT);
|
||||
// auto found = std::ranges::search(bs, _config.keyval_delim);
|
||||
|
||||
// if (found.empty()) { // no value
|
||||
// _key = snplib_trim_spaces_as_view(bs, TrimType::TRIM_RIGHT);
|
||||
|
||||
// _value = std::string_view();
|
||||
// } else {
|
||||
// _key = snplib_trim_spaces_as_view(std::string_view(bs.begin(), found.begin()), TrimType::TRIM_RIGHT);
|
||||
|
||||
// // do not delete space at the end of value-string!
|
||||
// _value = std::string_view(found.end(), bs.end());
|
||||
// }
|
||||
|
||||
// } else if constexpr (std::ranges::viewable_range<R>) {
|
||||
// auto bs = bytes | std::views::drop_while(snplib_is_space);
|
||||
// auto found = std::ranges::search(bs, _config.keyval_delim);
|
||||
|
||||
// _value.clear();
|
||||
|
||||
// if (found.empty()) { // no value
|
||||
// _key = snplib_trim_spaces(bs, TrimType::TRIM_RIGHT);
|
||||
// } else {
|
||||
// _key.clear();
|
||||
// auto N = std::ranges::distance(bs.begin(), found.begin());
|
||||
// std::ranges::copy(std::views::all(bs) | std::views::take(N) | std::views::reverse |
|
||||
// std::views::drop_while(snplib_is_space),
|
||||
// std::back_inserter(_key));
|
||||
|
||||
// std::ranges::copy(found.end(), bs.end(), std::back_inserter(_value));
|
||||
// }
|
||||
// } else { // always coping
|
||||
// auto bs = snplib_trim_spaces(bytes, TrimType::TRIM_LEFT);
|
||||
// auto found = std::ranges::search(bs, _config.keyval_delim);
|
||||
|
||||
// _value.clear();
|
||||
|
||||
// if (found.empty()) { // no value
|
||||
// _key = snplib_trim_spaces(bs, TrimType::TRIM_RIGHT);
|
||||
// } else {
|
||||
// _key.clear;
|
||||
// auto N = std::ranges::distance(bs.begin(), found.begin());
|
||||
// // std::ranges::copy_n(bs.begin(), N, std::back_inserter(_key));
|
||||
|
||||
// size_t i = 0;
|
||||
// for (auto it = bs.begin(); it != found.begin(); ++it, ++i) {
|
||||
// if (i < N) {
|
||||
// if (!snplib_is_space(*it)) {
|
||||
// std::back_inserter(_key) = *it;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// std::ranges::copy(found.end(), bs.end(), std::back_inserter(_value));
|
||||
// }
|
||||
|
||||
// split value to elements
|
||||
|
||||
if (_value.size()) {
|
||||
if (!_value.empty()) {
|
||||
_valueSeq = snplib_split_char_range<decltype(_valueSeq)>(_value, _config.valseq_delim);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
template <snplib_char_range_c R>
|
||||
@@ -109,9 +131,9 @@ public:
|
||||
return snplib_transform_char_range<R>(_key);
|
||||
}
|
||||
|
||||
constexpr std::string_view key() const
|
||||
constexpr auto key() const
|
||||
{
|
||||
return key<std::string_view>();
|
||||
return _key;
|
||||
}
|
||||
|
||||
template <snplib_char_range_c R>
|
||||
@@ -120,9 +142,9 @@ public:
|
||||
return snplib_transform_char_range<R>(_value);
|
||||
}
|
||||
|
||||
constexpr std::string_view value() const
|
||||
constexpr auto value() const
|
||||
{
|
||||
return value<std ::string_view>();
|
||||
return _value;
|
||||
}
|
||||
|
||||
|
||||
@@ -147,9 +169,11 @@ public:
|
||||
std::ranges::for_each(elems, [&res](auto const& e) {
|
||||
if constexpr (std::constructible_from<el_t, std::string_view::const_iterator,
|
||||
std::string_view::const_iterator>) {
|
||||
std::back_inserter(el_t{e.cbegin(), e.cend()}, std::back_inserter(res));
|
||||
// std::back_inserter(el_t{e.cbegin(), e.cend()}, std::back_inserter(res));
|
||||
std::back_inserter(res) = el_t{e.cbegin(), e.cend()};
|
||||
} else if constexpr (std::constructible_from<el_t, std::string_view>) {
|
||||
std::back_inserter(el_t{e}, std::back_inserter(res));
|
||||
// std::back_inserter(el_t{e}, std::back_inserter(res));
|
||||
std::back_inserter(res) = el_t{e};
|
||||
} else {
|
||||
static_assert(false, "Incompatible types: cannot create output element!");
|
||||
}
|
||||
@@ -159,9 +183,11 @@ public:
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<std::string_view> valueSeq(size_t start = 0, size_t N = std::numeric_limits<size_t>::max()) const
|
||||
auto valueSeq(size_t start = 0, size_t N = std::numeric_limits<size_t>::max()) const
|
||||
// std::vector<std::string_view> valueSeq(size_t start = 0, size_t N = std::numeric_limits<size_t>::max()) const
|
||||
{
|
||||
return valueSeq<std::vector<std::string_view>>(start, N);
|
||||
// return valueSeq<std::vector<std::string_view>>(start, N);
|
||||
return _valueSeq;
|
||||
}
|
||||
|
||||
|
||||
@@ -172,7 +198,7 @@ public:
|
||||
return OR();
|
||||
}
|
||||
|
||||
auto last_idx = start + N;
|
||||
auto last_idx = start + N - 1;
|
||||
if (last_idx >= _valueSeq.size()) {
|
||||
last_idx = _valueSeq.size() - 1;
|
||||
}
|
||||
@@ -197,24 +223,30 @@ public:
|
||||
requires mutableContent
|
||||
error_t setKey(KeyT&& key, SParT const& sparams = snplib_serialization_params_t{})
|
||||
{
|
||||
auto err = snplib_serializer_t<std::remove_cvref_t<KeyT>>(_key, std::forward<KeyT>(key), sparams);
|
||||
_byteSeq.clear();
|
||||
auto err = snplib_serializer_t<std::remove_cvref_t<KeyT>>{}(_byteSeq, std::forward<KeyT>(key), sparams);
|
||||
if (err) {
|
||||
return snplib_deduced_error(err, std::errc::invalid_argument);
|
||||
// return snplib_deduced_error(err, std::errc::invalid_argument);
|
||||
// return snplib_deduced_error(err, std::make_error_code(std::errc::invalid_argument));
|
||||
return std::make_error_code(std::errc::invalid_argument);
|
||||
}
|
||||
|
||||
return {};
|
||||
// return std::make_error_code(std::errc{});
|
||||
}
|
||||
|
||||
template <snplib_serializable_c ValueT, snplib_serialization_params_c SParT = snplib_serialization_params_t>
|
||||
requires mutableContent
|
||||
error_t setValue(ValueT&& value, SParT const& sparams = snplib_serialization_params_t{})
|
||||
{
|
||||
auto err = snplib_serializer_t<std::remove_cvref_t<ValueT>>(_key, std::forward<ValueT>(value), sparams);
|
||||
auto err = snplib_serializer_t<std::remove_cvref_t<ValueT>>{}(_byteSeq, std::forward<ValueT>(value), sparams);
|
||||
if (err) {
|
||||
return snplib_deduced_error(err, std::errc::invalid_argument);
|
||||
// return snplib_deduced_error(err, std::make_error_code(std::errc::invalid_argument));
|
||||
return std::make_error_code(std::errc::invalid_argument);
|
||||
}
|
||||
|
||||
return {};
|
||||
// return std::make_error_code(std::errc{});
|
||||
}
|
||||
|
||||
|
||||
@@ -229,22 +261,25 @@ public:
|
||||
return err;
|
||||
}
|
||||
|
||||
return setValue(std::forward<KeyT>(value), sparams);
|
||||
return setValue(std::forward<ValueT>(value), sparams);
|
||||
}
|
||||
|
||||
protected:
|
||||
std::
|
||||
conditional_t<mutableContent, std::string, std::conditional_t<stringViewContent, std::string_view, std::string>>
|
||||
_key;
|
||||
std::
|
||||
conditional_t<mutableContent, std::string, std::conditional_t<stringViewContent, std::string_view, std::string>>
|
||||
_value;
|
||||
std::vector<std::string_view> _valueSeq;
|
||||
// std::conditional_t<mutableContent,
|
||||
// std::vector<std::string>,
|
||||
// std::conditional_t<stringViewContent, std::vector<std::string_view>,
|
||||
// std::vector<std::string>>>
|
||||
// _valueSeq;
|
||||
ByteSeqT& _byteSeq;
|
||||
|
||||
// std::
|
||||
// conditional_t<mutableContent, std::string, std::conditional_t<contiguousContent, std::string_view,
|
||||
// std::string>>
|
||||
// _key;
|
||||
// std::
|
||||
// conditional_t<mutableContent, std::string, std::conditional_t<contiguousContent, std::string_view,
|
||||
// std::string>>
|
||||
// _value;
|
||||
std::conditional_t<contiguousContent, std::string_view, std::ranges::subrange<typename ByteSeqT::iterator>> _key;
|
||||
std::conditional_t<contiguousContent, std::string_view, std::ranges::subrange<typename ByteSeqT::iterator>> _value;
|
||||
// std::conditional_t<contiguousContent, std::string_view, std::views::all_t<ByteSeqT>> _key;
|
||||
// std::conditional_t<contiguousContent, std::string_view, std::views::all_t<ByteSeqT>> _value;
|
||||
std::vector<decltype(_value)> _valueSeq;
|
||||
|
||||
config_t _config;
|
||||
};
|
||||
|
||||
@@ -15,7 +15,7 @@ constexpr static bool snplib_is_space(char in) noexcept
|
||||
};
|
||||
|
||||
|
||||
enum class TrimType { TRIM_LEFT, TRIM_RIGHT, TRIM_BOTH };
|
||||
enum class TrimType { TRIM_LEFT = 0b1, TRIM_RIGHT = 0b10, TRIM_BOTH = 0b11 };
|
||||
|
||||
template <snplib_output_char_range_c OR, snplib_input_char_range_c R, typename IsSpaceFuncT = decltype(snplib_is_space)>
|
||||
constexpr static OR snplib_trim_spaces(R&& r,
|
||||
@@ -45,38 +45,72 @@ constexpr static std::string snplib_trim_spaces(R&& r,
|
||||
return snplib_trim_spaces<std::string>(std::forward<R>(r), type, std::forward<IsSpaceFuncT>(is_space_func));
|
||||
}
|
||||
|
||||
template <snplib_input_char_range_c R, typename IsSpaceFuncT = decltype(snplib_is_space)>
|
||||
constexpr static std::string_view snplib_trim_spaces_as_view(R&& r,
|
||||
TrimType type = TrimType::TRIM_BOTH,
|
||||
IsSpaceFuncT&& is_space_func = snplib_is_space)
|
||||
requires std::ranges::contiguous_range<R>
|
||||
// template <snplib_input_char_range_c R, typename IsSpaceFuncT = decltype(snplib_is_space)>
|
||||
// constexpr static std::string_view snplib_trim_spaces_as_view(R&& r,
|
||||
// TrimType type = TrimType::TRIM_BOTH,
|
||||
// IsSpaceFuncT&& is_space_func = snplib_is_space)
|
||||
// requires std::ranges::contiguous_range<R>
|
||||
// {
|
||||
// auto end = std::forward<R>(r).end();
|
||||
|
||||
// auto f1 = std::forward<R>(r).begin();
|
||||
|
||||
// if (type != TrimType::TRIM_RIGHT) {
|
||||
// // look for the first non-space symbol
|
||||
// f1 = std::ranges::find_if_not(std::forward<R>(r), std::forward<IsSpaceFuncT>(is_space_func));
|
||||
// if (f1 == end) { // all are spaces!
|
||||
// return std::string_view();
|
||||
// }
|
||||
// }
|
||||
|
||||
// auto f2 = end;
|
||||
|
||||
// if (type != TrimType::TRIM_LEFT) {
|
||||
// auto f3 = f1;
|
||||
|
||||
// do {
|
||||
// f2 = std::ranges::find_if(++f3, end, std::forward<IsSpaceFuncT>(is_space_func));
|
||||
// if (f2 == end)
|
||||
// break;
|
||||
// f3 = std::ranges::find_if_not(f2 + 1, end, std::forward<IsSpaceFuncT>(is_space_func));
|
||||
// } while (f3 != end);
|
||||
// }
|
||||
|
||||
// return std::string_view(f1, f2);
|
||||
// }
|
||||
|
||||
|
||||
template <std::ranges::viewable_range R, typename IsSpaceFuncT = decltype(snplib_is_space)>
|
||||
requires(snplib_char_range_c<R> && std::ranges::borrowed_range<R>)
|
||||
constexpr static auto snplib_trim_spaces_as_view(R&& r,
|
||||
TrimType type = TrimType::TRIM_BOTH,
|
||||
IsSpaceFuncT&& is_space_func = snplib_is_space)
|
||||
{
|
||||
auto end = std::forward<R>(r).end();
|
||||
if constexpr (std::is_pointer_v<std::decay_t<R>>) { // char*, const char*, char[] ('\0' terminates C-ish string)
|
||||
return snplib_trim_spaces_as_view(std::string_view(std::forward<R>(r)), type,
|
||||
std::forward<IsSpaceFuncT>(is_space_func));
|
||||
} else {
|
||||
auto it_left = r.begin();
|
||||
auto it_right = r.end();
|
||||
|
||||
auto f1 = std::forward<R>(r).begin();
|
||||
if (std::to_underlying(type) & std::to_underlying(TrimType::TRIM_LEFT)) {
|
||||
it_left = std::ranges::find_if_not(std::forward<R>(r), std::forward<IsSpaceFuncT>(is_space_func));
|
||||
}
|
||||
|
||||
if (type != TrimType::TRIM_RIGHT) {
|
||||
// look for the first non-space symbol
|
||||
f1 = std::ranges::find_if_not(std::forward<R>(r), std::forward<IsSpaceFuncT>(is_space_func));
|
||||
if (f1 == end) { // all are spaces!
|
||||
return std::string_view();
|
||||
if (std::to_underlying(type) & std::to_underlying(TrimType::TRIM_RIGHT)) {
|
||||
auto found = std::ranges::find_last_if_not(std::forward<R>(r), std::forward<IsSpaceFuncT>(is_space_func));
|
||||
if (!found.empty()) {
|
||||
it_right = std::next(found.begin());
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (std::ranges::contiguous_range<std::decay_t<R>>) {
|
||||
return std::string_view{it_left, it_right};
|
||||
} else {
|
||||
return std::ranges::subrange{it_left, it_right};
|
||||
// return std::views::all_t<std::decay_t<R>>(std::ranges::subrange{it_left, it_right});
|
||||
}
|
||||
}
|
||||
|
||||
auto f2 = end;
|
||||
|
||||
if (type != TrimType::TRIM_LEFT) {
|
||||
auto f3 = f1;
|
||||
|
||||
do {
|
||||
f2 = std::ranges::find_if(++f3, end, std::forward<IsSpaceFuncT>(is_space_func));
|
||||
if (f2 == end)
|
||||
break;
|
||||
f3 = std::ranges::find_if_not(f2 + 1, end, std::forward<IsSpaceFuncT>(is_space_func));
|
||||
} while (f3 != end);
|
||||
}
|
||||
|
||||
return std::string_view(f1, f2);
|
||||
}
|
||||
|
||||
|
||||
@@ -113,13 +147,21 @@ static constexpr OR snplib_transform_char_range(IR&& r, CTorTs&&... or_ctor_args
|
||||
{
|
||||
using val_t = std::remove_cvref_t<IR>;
|
||||
|
||||
static constexpr bool ret_view = snplib_char_view_c<OR> && std::ranges::viewable_range<val_t>;
|
||||
|
||||
if constexpr (std::same_as<OR, val_t>) { // just a copy
|
||||
return r;
|
||||
} else if constexpr (snplib_char_view_c<OR> && std::ranges::viewable_range<val_t>) {
|
||||
} else if constexpr (ret_view &&
|
||||
(std::constructible_from<OR, std::ranges::iterator_t<val_t>, std::ranges::iterator_t<val_t>> ||
|
||||
std::constructible_from<OR, std::ranges::iterator_t<val_t>,
|
||||
std::ranges::sentinel_t<val_t>>)) {
|
||||
return OR{r.begin(), r.end()};
|
||||
} else if (snplib_output_char_range_c<OR>) {
|
||||
} else if constexpr (std::constructible_from<OR, val_t>) {
|
||||
return OR(std::forward<IR>(r));
|
||||
} else if constexpr (snplib_output_char_range_c<OR>) {
|
||||
OR res(std::forward<CTorTs>(or_ctor_args)...);
|
||||
std::ranges::copy(std::forward<IR>(r), std::back_inserter(res));
|
||||
return res;
|
||||
} else {
|
||||
static_assert(false, "Incompatible types!");
|
||||
}
|
||||
@@ -154,8 +196,10 @@ static constexpr OR snplib_split_char_range(IR&& input,
|
||||
|
||||
using el_t = std::ranges::range_value_t<OR>;
|
||||
using it_t = std::ranges::iterator_t<IR>;
|
||||
static_assert(std::constructible_from<el_t, it_t, it_t>,
|
||||
static_assert(std::constructible_from<el_t, decltype(input.begin()), decltype(input.end())>,
|
||||
"Incompatible input and output types: cannot create element!");
|
||||
// static_assert(std::constructible_from<el_t, it_t, it_t>,
|
||||
// "Incompatible input and output types: cannot create element!");
|
||||
|
||||
auto it = input.begin();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user