Commit c2f40c37 authored by Henry Lee's avatar Henry Lee Committed by Wouter van Oortmerssen

[C++]Support reverse iterator in Vector (#5128)

* Add `const` keyword to the `operator-(const uoffset_t &)` function in
`VectorIterator`

* Support reverse iterator in Vector

Introduced a new VectorReverseIterator type. We cannot directly use
`std::reverse_iterator<VectorIterator>` because the signature of
`operator*` and `operator->` in the VectorIterator class are not
standard signatures.

Also added `rbegin()`, `rend()`, `cbegin()`, `cend()`, `crbegin()`
and `crend()` in the Vector class.
parent 63d51afd
...@@ -116,6 +116,7 @@ template<typename T, typename IT> struct VectorIterator { ...@@ -116,6 +116,7 @@ template<typename T, typename IT> struct VectorIterator {
VectorIterator(const uint8_t *data, uoffset_t i) VectorIterator(const uint8_t *data, uoffset_t i)
: data_(data + IndirectHelper<T>::element_stride * i) {} : data_(data + IndirectHelper<T>::element_stride * i) {}
VectorIterator(const VectorIterator &other) : data_(other.data_) {} VectorIterator(const VectorIterator &other) : data_(other.data_) {}
VectorIterator() : data_(nullptr) {}
VectorIterator &operator=(const VectorIterator &other) { VectorIterator &operator=(const VectorIterator &other) {
data_ = other.data_; data_ = other.data_;
...@@ -183,7 +184,7 @@ template<typename T, typename IT> struct VectorIterator { ...@@ -183,7 +184,7 @@ template<typename T, typename IT> struct VectorIterator {
return temp; return temp;
} }
VectorIterator operator-(const uoffset_t &offset) { VectorIterator operator-(const uoffset_t &offset) const {
return VectorIterator(data_ - offset * IndirectHelper<T>::element_stride, return VectorIterator(data_ - offset * IndirectHelper<T>::element_stride,
0); 0);
} }
...@@ -197,6 +198,19 @@ template<typename T, typename IT> struct VectorIterator { ...@@ -197,6 +198,19 @@ template<typename T, typename IT> struct VectorIterator {
const uint8_t *data_; const uint8_t *data_;
}; };
template<typename Iterator> struct VectorReverseIterator :
public std::reverse_iterator<Iterator> {
explicit VectorReverseIterator(Iterator iter) : iter_(iter) {}
typename Iterator::value_type operator*() const { return *(iter_ - 1); }
typename Iterator::value_type operator->() const { return *(iter_ - 1); }
private:
Iterator iter_;
};
struct String; struct String;
// This is used as a helper type for accessing vectors. // This is used as a helper type for accessing vectors.
...@@ -207,6 +221,8 @@ template<typename T> class Vector { ...@@ -207,6 +221,8 @@ template<typename T> class Vector {
iterator; iterator;
typedef VectorIterator<T, typename IndirectHelper<T>::return_type> typedef VectorIterator<T, typename IndirectHelper<T>::return_type>
const_iterator; const_iterator;
typedef VectorReverseIterator<iterator> reverse_iterator;
typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
uoffset_t size() const { return EndianScalar(length_); } uoffset_t size() const { return EndianScalar(length_); }
...@@ -253,6 +269,20 @@ template<typename T> class Vector { ...@@ -253,6 +269,20 @@ template<typename T> class Vector {
iterator end() { return iterator(Data(), size()); } iterator end() { return iterator(Data(), size()); }
const_iterator end() const { return const_iterator(Data(), size()); } const_iterator end() const { return const_iterator(Data(), size()); }
reverse_iterator rbegin() { return reverse_iterator(end()); }
const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(end()); }
const_reverse_iterator rend() const { return const_reverse_iterator(end()); }
const_iterator cbegin() const { return begin(); }
const_iterator cend() const { return end(); }
const_reverse_iterator crbegin() const { return rbegin(); }
const_reverse_iterator crend() const { return rend(); }
// Change elements if you have a non-const pointer to this object. // Change elements if you have a non-const pointer to this object.
// Scalars only. See reflection.h, and the documentation. // Scalars only. See reflection.h, and the documentation.
void Mutate(uoffset_t i, const T &val) { void Mutate(uoffset_t i, const T &val) {
......
...@@ -255,6 +255,24 @@ void AccessFlatBufferTest(const uint8_t *flatbuf, size_t length, ...@@ -255,6 +255,24 @@ void AccessFlatBufferTest(const uint8_t *flatbuf, size_t length,
TEST_EQ(*it, inv_data[indx]); TEST_EQ(*it, inv_data[indx]);
} }
for (auto it = inventory->cbegin(); it != inventory->cend(); ++it) {
auto indx = it - inventory->cbegin();
TEST_EQ(*it, inv_vec.at(indx)); // Use bounds-check.
TEST_EQ(*it, inv_data[indx]);
}
for (auto it = inventory->rbegin(); it != inventory->rend(); ++it) {
auto indx = inventory->rend() - it;
TEST_EQ(*it, inv_vec.at(indx)); // Use bounds-check.
TEST_EQ(*it, inv_data[indx]);
}
for (auto it = inventory->crbegin(); it != inventory->crend(); ++it) {
auto indx = inventory->crend() - it;
TEST_EQ(*it, inv_vec.at(indx)); // Use bounds-check.
TEST_EQ(*it, inv_data[indx]);
}
TEST_EQ(monster->color(), Color_Blue); TEST_EQ(monster->color(), Color_Blue);
// Example of accessing a union: // Example of accessing a union:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment