From 17a8804cf3c3f99bfc1083730755ca4f4d1abd0a Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Thu, 3 Jul 2014 14:29:57 +0200 Subject: [PATCH] document.h: add GenericMemberIterator Add dedicated class-based member iterator to prepare the switch to a (safe) API change to return MemberEnd() from FindMember(). Pointer-based iterator can be kept by defining RAPIDJSON_NOMEMBERITERATORCLASS. This may be useful for platforms without a working header. --- include/rapidjson/document.h | 150 ++++++++++++++++++++++++++++++++++- 1 file changed, 147 insertions(+), 3 deletions(-) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index ae13c28..3017dfd 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -5,6 +5,11 @@ #include "internal/strfunc.h" #include // placement new +#ifndef RAPIDJSON_NOMEMBERITERATORCLASS +#include "internal/meta.h" +#include // std::iterator, std::random_access_iterator_tag +#endif + #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4127) // conditional expression is constant @@ -21,7 +26,7 @@ namespace rapidjson { template class GenericValue; -//! Name-value pair in an object. +//! Name-value pair in a JSON object value. /*! This class was internal to GenericValue. It used to be a inner struct. But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct. @@ -33,6 +38,145 @@ struct GenericMember { GenericValue value; //!< value of member. }; +#ifndef RAPIDJSON_NOMEMBERITERATORCLASS + +//! (Const) member iterator for a JSON object value +/*! + \tparam Const Is this a const iterator? + \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document) + \tparam Allocator Allocator type for allocating memory of object, array and string. + + This class implements a Random Access Iterator for GenericMember elements + of a GenericValue, see ISO/IEC 14882:2003(E) C++ standard, 24.1 [lib.iterator.requirements]. + + \note This iterator implementation is mainly intended to avoid implicit + conversions from iterator values to \c NULL, + e.g. from GenericValue::FindMember. + + \note Define \c RAPIDJSON_NOMEMBERITERATORCLASS to fall back to a + pointer-based implementation, if your platform doesn't provide + the C++ header. + + \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator + */ +template +class GenericMemberIterator + : public std::iterator >::Type> { + + friend class GenericValue; + template friend class GenericMemberIterator; + + typedef GenericMember PlainType; + typedef typename internal::MaybeAddConst::Type ValueType; + typedef std::iterator BaseType; + +public: + //! Iterator type itself + typedef GenericMemberIterator Type; + //! Const iterator type + typedef GenericMemberIterator ConstType; + //! Non-const iterator type + typedef GenericMemberIterator NonConstType; + + //! Pointer to (const) GenericMember + typedef typename BaseType::pointer Pointer; + //! Reference to (const) GenericMember + typedef typename BaseType::reference Reference; + //! Signed integer type (e.g. \c ptrdiff_t) + typedef typename BaseType::difference_type DifferenceType; + + //! Default constructor (singular value) + /*! Creates an iterator pointing to no element. + \note All operations, except for comparisons, are undefined on such values. + */ + GenericMemberIterator() : ptr_() {} + + //! Iterator conversions to more const + /*! + \param it (Non-const) iterator to copy from + + Allows the creation of an iterator from another GenericMemberIterator + that is "less const". Especially, creating a non-const iterator from + a const iterator are disabled: + \li const -> non-const (not ok) + \li const -> const (ok) + \li non-const -> const (ok) + \li non-const -> non-const (ok) + + \note If the \c Const template parameter is already \c false, this + constructor effectively defines a regular copy-constructor. + Otherwise, the copy constructor is implicitly defined. + */ + GenericMemberIterator(const NonConstType & it) + : ptr_( it.ptr_ ) {} + + //! @name stepping + //@{ + Type& operator++(){ ++ptr_; return *this; } + Type& operator--(){ --ptr_; return *this; } + Type operator++(int){ Type old(*this); ++ptr_; return old; } + Type operator--(int){ Type old(*this); --ptr_; return old; } + //@} + + //! @name increment/decrement + //@{ + Type operator+(DifferenceType n) const { return Type(ptr_+n); } + Type operator-(DifferenceType n) const { return Type(ptr_-n); } + + Type& operator+=(DifferenceType n) { ptr_+=n; return *this; } + Type& operator-=(DifferenceType n) { ptr_-=n; return *this; } + //@} + + //! @name relations + //@{ + bool operator==(Type that) const { return ptr_ == that.ptr_; } + bool operator!=(Type that) const { return ptr_ != that.ptr_; } + bool operator<=(Type that) const { return ptr_ <= that.ptr_; } + bool operator>=(Type that) const { return ptr_ >= that.ptr_; } + bool operator< (Type that) const { return ptr_ < that.ptr_; } + bool operator> (Type that) const { return ptr_ > that.ptr_; } + //@} + + //! @name dereference + //@{ + Reference operator*() const { return *ptr_; } + Pointer operator->() const { return ptr_; } + Reference operator[](DifferenceType n) const { return ptr_[n]; } + //@} + + //! Distance + DifferenceType operator-(Type that) const { return ptr_-that.ptr_; } + +private: + //!< Internal constructor from plain pointer + explicit GenericMemberIterator(Pointer p) : ptr_(p) {} + + Pointer ptr_; //!< raw pointer +}; + +#else // RAPIDJSON_NOMEMBERITERATORCLASS + +// class-based member iterator implementation disabled, use plain pointers + +template +struct GenericMemberIterator; + +//! non-const GenericMemberIterator +template +struct GenericMemberIterator { + //! use plain pointer as iterator type + typedef GenericMember* Type; +}; +//! const GenericMemberIterator +template +struct GenericMemberIterator { + //! use plain const pointer as iterator type + typedef const GenericMember* Type; +}; + +#endif // RAPIDJSON_NOMEMBERITERATORCLASS + /////////////////////////////////////////////////////////////////////////////// // GenericValue @@ -55,8 +199,8 @@ public: typedef Encoding EncodingType; //!< Encoding type from template parameter. typedef Allocator AllocatorType; //!< Allocator type from template parameter. typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. - typedef Member* MemberIterator; //!< Member iterator for iterating in object. - typedef const Member* ConstMemberIterator; //!< Constant member iterator for iterating in object. + typedef typename GenericMemberIterator::Type MemberIterator; //!< Member iterator for iterating in object. + typedef typename GenericMemberIterator::Type ConstMemberIterator; //!< Constant member iterator for iterating in object. typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array. typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array.