From 2811a3eac80397a1508a6a4da2342cbb722c0fa6 Mon Sep 17 00:00:00 2001 From: Bas Zalmstra Date: Mon, 30 Jun 2014 16:56:34 +0200 Subject: [PATCH] Added an iterator to Vector so you can use range based for loops on them. Change-Id: I6310edd554fba494a76e47b03d3c2bc07b90795d --- include/flatbuffers/flatbuffers.h | 77 ++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index d2ab04c80..82df48850 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -159,12 +159,14 @@ template size_t AlignOf() { // (avoiding the need for a trailing return decltype) template struct IndirectHelper { typedef T return_type; + static const size_t element_stride = sizeof(T); static return_type Read(const uint8_t *p, uoffset_t i) { return EndianScalar((reinterpret_cast(p))[i]); } }; template struct IndirectHelper> { typedef const T *return_type; + static const size_t element_stride = sizeof(uoffset_t); static return_type Read(const uint8_t *p, uoffset_t i) { p += i * sizeof(uoffset_t); return EndianScalar(reinterpret_cast( @@ -173,15 +175,80 @@ template struct IndirectHelper> { }; template struct IndirectHelper { typedef const T &return_type; + static const size_t element_stride = sizeof(T); static return_type Read(const uint8_t *p, uoffset_t i) { return *reinterpret_cast(p + i * sizeof(T)); } }; +// An STL compatible iterator implementation for Vector below, effectively +// calling Get() for every element. +template +struct VectorIterator : public + std::iterator < std::input_iterator_tag, + typename std::conditional < bConst, + const typename IndirectHelper::return_type, + typename IndirectHelper::return_type > ::type, uoffset_t > { + + typedef std::iterator::return_type, + typename IndirectHelper::return_type>::type, uoffset_t> super_type; + +public: + VectorIterator(const uint8_t *data, uoffset_t i) : + data_(data + IndirectHelper::element_stride * i) {}; + VectorIterator(const VectorIterator &other) : data_(other.data_) {} + VectorIterator(VectorIterator &&other) : data_(std::move(other.data_)) {} + + VectorIterator &operator=(const VectorIterator &other) { + data_ = other.data_; + return *this; + } + + VectorIterator &operator=(VectorIterator &&other) { + data_ = other.data_; + return *this; + } + + bool operator==(const VectorIterator& other) const { + return data_ == other.data_; + } + + bool operator!=(const VectorIterator& other) const { + return data_ != other.data_; + } + + typename super_type::value_type operator *() const { + return IndirectHelper::Read(data_, 0); + } + + typename super_type::pointer operator->() const { + return &IndirectHelper::Read(data_, 0); + } + + VectorIterator &operator++() { + data_ += IndirectHelper::element_stride; + return *this; + } + + VectorIterator operator++(int) { + VectorIterator temp(data_); + data_ += IndirectHelper::element_stride; + return temp; + } + +private: + const uint8_t *data_; +}; + // This is used as a helper type for accessing vectors. // Vector::data() assumes the vector elements start after the length field. template class Vector { - public: +public: + typedef VectorIterator iterator; + typedef VectorIterator const_iterator; + uoffset_t Length() const { return EndianScalar(length_); } typedef typename IndirectHelper::return_type return_type; @@ -195,7 +262,13 @@ template class Vector { return reinterpret_cast(Data() + o); } - protected: + iterator begin() { return iterator(Data(), 0); } + const_iterator begin() const { return const_iterator(Data(), 0); } + + iterator end() { return iterator(Data(), length_); } + const_iterator end() const { return const_iterator(Data(), length_); } + +protected: // This class is only used to access pre-existing data. Don't ever // try to construct these manually. Vector();