Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[vector] Allow to iterate with mutables #7586

Merged
merged 3 commits into from
Oct 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/flatbuffers/array.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ template<typename T, uint16_t length> class Array {
public:
typedef uint16_t size_type;
typedef typename IndirectHelper<IndirectHelperType>::return_type return_type;
typedef VectorIterator<T, return_type> const_iterator;
typedef VectorConstIterator<T, return_type> const_iterator;
typedef VectorReverseIterator<const_iterator> const_reverse_iterator;

// If T is a LE-scalar or a struct (!scalar_tag::value).
Expand Down
12 changes: 11 additions & 1 deletion include/flatbuffers/buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ template<typename T> struct IndirectHelper {
static return_type Read(const uint8_t *p, uoffset_t i) {
return EndianScalar((reinterpret_cast<const T *>(p))[i]);
}
static return_type Read(uint8_t *p, uoffset_t i) {
return Read(const_cast<const uint8_t *>(p), i);
}
};
template<typename T> struct IndirectHelper<Offset<T>> {
typedef const T *return_type;
Expand All @@ -85,13 +88,20 @@ template<typename T> struct IndirectHelper<Offset<T>> {
p += i * sizeof(uoffset_t);
return reinterpret_cast<return_type>(p + ReadScalar<uoffset_t>(p));
}
static mutable_return_type Read(uint8_t *p, uoffset_t i) {
p += i * sizeof(uoffset_t);
return reinterpret_cast<mutable_return_type>(p + ReadScalar<uoffset_t>(p));
}
};
template<typename T> struct IndirectHelper<const T *> {
typedef const T *return_type;
typedef T *mutable_return_type;
static const size_t element_stride = sizeof(T);
static return_type Read(const uint8_t *p, uoffset_t i) {
return reinterpret_cast<const T *>(p + i * sizeof(T));
return reinterpret_cast<return_type>(p + i * sizeof(T));
}
static mutable_return_type Read(uint8_t *p, uoffset_t i) {
return reinterpret_cast<mutable_return_type>(p + i * sizeof(T));
}
};

Expand Down
12 changes: 8 additions & 4 deletions include/flatbuffers/vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,15 @@ struct String;

// An STL compatible iterator implementation for Vector below, effectively
// calling Get() for every element.
template<typename T, typename IT> struct VectorIterator {
template<typename T, typename IT, typename Data = uint8_t *>
struct VectorIterator {
typedef std::random_access_iterator_tag iterator_category;
typedef IT value_type;
typedef ptrdiff_t difference_type;
typedef IT *pointer;
typedef IT &reference;

VectorIterator(const uint8_t *data, uoffset_t i)
VectorIterator(Data data, uoffset_t i)
: data_(data + IndirectHelper<T>::element_stride * i) {}
VectorIterator(const VectorIterator &other) : data_(other.data_) {}
VectorIterator() : data_(nullptr) {}
Expand Down Expand Up @@ -116,9 +117,12 @@ template<typename T, typename IT> struct VectorIterator {
}

private:
const uint8_t *data_;
Data data_;
};

template<typename T, typename IT>
using VectorConstIterator = VectorIterator<T, IT, const uint8_t *>;

template<typename Iterator>
struct VectorReverseIterator : public std::reverse_iterator<Iterator> {
explicit VectorReverseIterator(Iterator iter)
Expand All @@ -145,7 +149,7 @@ template<typename T> class Vector {
public:
typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type>
iterator;
typedef VectorIterator<T, typename IndirectHelper<T>::return_type>
typedef VectorConstIterator<T, typename IndirectHelper<T>::return_type>
const_iterator;
typedef VectorReverseIterator<iterator> reverse_iterator;
typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
Expand Down
10 changes: 10 additions & 0 deletions tests/monster_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,16 @@ void MutateFlatBuffersTest(uint8_t *flatbuf, std::size_t length) {
TEST_EQ(first->hp(), 0);
first->mutate_hp(1000);

// Test for each loop over mutable entries
for (auto item: *tables)
{
TEST_EQ(item->hp(), 1000);
item->mutate_hp(0);
TEST_EQ(item->hp(), 0);
item->mutate_hp(1000);
break; // one iteration is enough, just testing compilation
}

// Mutate via LookupByKey
TEST_NOTNULL(tables->MutableLookupByKey("Barney"));
TEST_EQ(static_cast<Monster *>(nullptr),
Expand Down