utils: fragment_range: add a fragment iterator for FragmentedView

A stylistic change. Iterators are the idiomatic way to iterate in C++.
This commit is contained in:
Michał Chojnowski
2021-01-08 11:39:52 +01:00
parent 2e38647a95
commit 72ecbd6936
7 changed files with 50 additions and 16 deletions

View File

@@ -266,8 +266,8 @@ private:
}
template<typename CharOutputIterator>
static void write_value(managed_bytes_view val, CharOutputIterator& out) {
for (; !val.empty(); val.remove_current()) {
out = std::copy(val.current_fragment().begin(), val.current_fragment().end(), out);
for (bytes_view frag : fragment_range(val)) {
out = std::copy(frag.begin(), frag.end(), out);
}
}
template <typename CharOutputIterator>

View File

@@ -500,8 +500,8 @@ public:
[[gnu::always_inline]]
operator managed_bytes() && {
managed_bytes mb(managed_bytes::initialized_later(), _stream.size());
for (managed_bytes_mutable_view v = mb; !v.empty(); v.remove_current()) {
_stream.read(reinterpret_cast<char*>(v.current_fragment().data()), v.current_fragment().size());
for (bytes_mutable_view frag : fragment_range(managed_bytes_mutable_view(mb))) {
_stream.read(reinterpret_cast<char*>(frag.data()), frag.size());
}
return mb;
}
@@ -533,8 +533,8 @@ struct serializer<bytes> {
template<typename Output>
static void write(Output& out, const managed_bytes& mb) {
safe_serialize_as_uint32(out, uint32_t(mb.size()));
for (managed_bytes_view v = mb; !v.empty(); v.remove_current()) {
out.write(reinterpret_cast<const char*>(v.current_fragment().data()), v.current_fragment().size());
for (bytes_view frag : fragment_range(managed_bytes_view(mb))) {
out.write(reinterpret_cast<const char*>(frag.data()), frag.size());
}
}
template<typename Output>

View File

@@ -306,8 +306,8 @@ inline void write(sstable_version_types v, W& out, bytes_view s) {
template <typename W>
requires Writer<W>
inline void write(sstable_version_types v, W& out, managed_bytes_view s) {
for (; !s.empty(); s.remove_current()) {
out.write(reinterpret_cast<const char*>(s.current_fragment().data()), s.current_fragment().size());
for (bytes_view fragment : fragment_range(s)) {
write(v, out, fragment);
}
}

View File

@@ -1477,8 +1477,8 @@ struct validate_visitor {
}
void operator()(const ascii_type_impl&) {
// ASCII can be validated independently for each fragment
for (View fv = v; fv.size_bytes() > 0; fv.remove_current()) {
if (!utils::ascii::validate(fv.current_fragment())) {
for (bytes_view frag : fragment_range(v)) {
if (!utils::ascii::validate(frag)) {
throw marshal_exception("Validation failed - non-ASCII character in an ASCII string");
}
}

View File

@@ -179,6 +179,41 @@ concept FragmentedMutableView = requires (T view) {
requires std::is_same_v<typename T::fragment_type, bytes_mutable_view>;
};
template<FragmentedView View>
struct fragment_range {
View view;
class fragment_iterator {
using iterator_category = std::input_iterator_tag;
using value_type = typename View::fragment_type;
using difference_type = std::ptrdiff_t;
using pointer = const value_type*;
using reference = const value_type&;
View _view;
value_type _current;
public:
fragment_iterator() : _view(value_type()) {}
fragment_iterator(const View& v) : _view(v) {
_current = _view.current_fragment();
}
fragment_iterator& operator++() {
_view.remove_current();
_current = _view.current_fragment();
return *this;
}
fragment_iterator operator++(int) {
fragment_iterator i(*this);
++(*this);
return i;
}
reference operator*() const { return _current; }
pointer operator->() const { return &_current; }
bool operator==(const fragment_iterator& i) const { return _view.size_bytes() == i._view.size_bytes(); }
};
fragment_range(const View& v) : view(v) {}
fragment_iterator begin() const { return fragment_iterator(view); }
fragment_iterator end() const { return fragment_iterator(); }
};
template<FragmentedView View>
requires (!FragmentRange<View>)
bytes linearized(View v)

View File

@@ -451,8 +451,8 @@ struct appending_hash<managed_bytes_view> {
template<Hasher Hasher>
void operator()(Hasher& h, managed_bytes_view v) const {
feed_hash(h, v.size_bytes());
for (; !v.empty(); v.remove_current()) {
h.update(reinterpret_cast<const char*>(v.current_fragment().data()), v.current_fragment().size());
for (bytes_view frag : fragment_range(v)) {
h.update(reinterpret_cast<const char*>(frag.data()), frag.size());
}
}
};
@@ -481,8 +481,8 @@ inline bool operator==(const managed_bytes_view& a, const managed_bytes_view& b)
}
inline std::ostream& operator<<(std::ostream& os, const managed_bytes_view& v) {
for (managed_bytes_view mbv; !mbv.empty(); mbv.remove_current()) {
os << to_hex(mbv.current_fragment());
for (bytes_view frag : fragment_range(v)) {
os << to_hex(frag);
}
return os;
}

View File

@@ -74,8 +74,7 @@ std::optional<size_t> validate_with_error_position_fragmented(FragmentedView aut
size_t partial_filled = 0;
size_t partial_more_needed = 0;
size_t bytes_validated = 0;
for (; fv.size_bytes(); fv.remove_current()) {
bytes_view frag = fv.current_fragment();
for (bytes_view frag : fragment_range(fv)) {
auto data = reinterpret_cast<const uint8_t*>(frag.data());
auto len = frag.size();
if (partial_more_needed) {