mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-26 08:12:40 +00:00
[vector] Allow to iterate with mutables (#7586)
Co-authored-by: ArnaudD-FR <arnaud.desmier@gmail.com> Co-authored-by: Derek Bailey <derekbailey@google.com>
This commit is contained in:
@@ -35,7 +35,7 @@ template<typename T, uint16_t length> class Array {
|
|||||||
public:
|
public:
|
||||||
typedef uint16_t size_type;
|
typedef uint16_t size_type;
|
||||||
typedef typename IndirectHelper<IndirectHelperType>::return_type return_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;
|
typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
|
||||||
|
|
||||||
// If T is a LE-scalar or a struct (!scalar_tag::value).
|
// If T is a LE-scalar or a struct (!scalar_tag::value).
|
||||||
|
|||||||
@@ -76,6 +76,9 @@ template<typename T> struct IndirectHelper {
|
|||||||
static return_type Read(const uint8_t *p, uoffset_t i) {
|
static return_type Read(const uint8_t *p, uoffset_t i) {
|
||||||
return EndianScalar((reinterpret_cast<const T *>(p))[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>> {
|
template<typename T> struct IndirectHelper<Offset<T>> {
|
||||||
typedef const T *return_type;
|
typedef const T *return_type;
|
||||||
@@ -85,13 +88,20 @@ template<typename T> struct IndirectHelper<Offset<T>> {
|
|||||||
p += i * sizeof(uoffset_t);
|
p += i * sizeof(uoffset_t);
|
||||||
return reinterpret_cast<return_type>(p + ReadScalar<uoffset_t>(p));
|
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 *> {
|
template<typename T> struct IndirectHelper<const T *> {
|
||||||
typedef const T *return_type;
|
typedef const T *return_type;
|
||||||
typedef T *mutable_return_type;
|
typedef T *mutable_return_type;
|
||||||
static const size_t element_stride = sizeof(T);
|
static const size_t element_stride = sizeof(T);
|
||||||
static return_type Read(const uint8_t *p, uoffset_t i) {
|
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));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -27,14 +27,15 @@ struct String;
|
|||||||
|
|
||||||
// An STL compatible iterator implementation for Vector below, effectively
|
// An STL compatible iterator implementation for Vector below, effectively
|
||||||
// calling Get() for every element.
|
// 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 std::random_access_iterator_tag iterator_category;
|
||||||
typedef IT value_type;
|
typedef IT value_type;
|
||||||
typedef ptrdiff_t difference_type;
|
typedef ptrdiff_t difference_type;
|
||||||
typedef IT *pointer;
|
typedef IT *pointer;
|
||||||
typedef IT &reference;
|
typedef IT &reference;
|
||||||
|
|
||||||
VectorIterator(const uint8_t *data, uoffset_t i)
|
VectorIterator(Data 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() : data_(nullptr) {}
|
||||||
@@ -116,9 +117,12 @@ template<typename T, typename IT> struct VectorIterator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const uint8_t *data_;
|
Data data_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T, typename IT>
|
||||||
|
using VectorConstIterator = VectorIterator<T, IT, const uint8_t *>;
|
||||||
|
|
||||||
template<typename Iterator>
|
template<typename Iterator>
|
||||||
struct VectorReverseIterator : public std::reverse_iterator<Iterator> {
|
struct VectorReverseIterator : public std::reverse_iterator<Iterator> {
|
||||||
explicit VectorReverseIterator(Iterator iter)
|
explicit VectorReverseIterator(Iterator iter)
|
||||||
@@ -145,7 +149,7 @@ template<typename T> class Vector {
|
|||||||
public:
|
public:
|
||||||
typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type>
|
typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type>
|
||||||
iterator;
|
iterator;
|
||||||
typedef VectorIterator<T, typename IndirectHelper<T>::return_type>
|
typedef VectorConstIterator<T, typename IndirectHelper<T>::return_type>
|
||||||
const_iterator;
|
const_iterator;
|
||||||
typedef VectorReverseIterator<iterator> reverse_iterator;
|
typedef VectorReverseIterator<iterator> reverse_iterator;
|
||||||
typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
|
typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
|
||||||
|
|||||||
@@ -439,6 +439,16 @@ void MutateFlatBuffersTest(uint8_t *flatbuf, std::size_t length) {
|
|||||||
TEST_EQ(first->hp(), 0);
|
TEST_EQ(first->hp(), 0);
|
||||||
first->mutate_hp(1000);
|
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
|
// Mutate via LookupByKey
|
||||||
TEST_NOTNULL(tables->MutableLookupByKey("Barney"));
|
TEST_NOTNULL(tables->MutableLookupByKey("Barney"));
|
||||||
TEST_EQ(static_cast<Monster *>(nullptr),
|
TEST_EQ(static_cast<Monster *>(nullptr),
|
||||||
|
|||||||
Reference in New Issue
Block a user