Commit 17a8804c authored by Philipp A. Hartmann's avatar Philipp A. Hartmann

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 <iterator> header.
parent 05179e28
......@@ -5,6 +5,11 @@
#include "internal/strfunc.h"
#include <new> // placement new
#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
#include "internal/meta.h"
#include <iterator> // 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 <typename Encoding, typename Allocator>
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<Encoding, Allocator> 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++ <iterator> header.
\see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator
*/
template <bool Const, typename Encoding, typename Allocator>
class GenericMemberIterator
: public std::iterator<std::random_access_iterator_tag
, typename internal::MaybeAddConst<Const,GenericMember<Encoding,Allocator> >::Type> {
friend class GenericValue<Encoding,Allocator>;
template <bool, typename, typename> friend class GenericMemberIterator;
typedef GenericMember<Encoding,Allocator> PlainType;
typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
typedef std::iterator<std::random_access_iterator_tag,ValueType> BaseType;
public:
//! Iterator type itself
typedef GenericMemberIterator Type;
//! Const iterator type
typedef GenericMemberIterator<true,Encoding,Allocator> ConstType;
//! Non-const iterator type
typedef GenericMemberIterator<false,Encoding,Allocator> 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 <bool Const, typename Encoding, typename Allocator>
struct GenericMemberIterator;
//! non-const GenericMemberIterator
template <typename Encoding, typename Allocator>
struct GenericMemberIterator<false,Encoding,Allocator> {
//! use plain pointer as iterator type
typedef GenericMember<Encoding,Allocator>* Type;
};
//! const GenericMemberIterator
template <typename Encoding, typename Allocator>
struct GenericMemberIterator<true,Encoding,Allocator> {
//! use plain const pointer as iterator type
typedef const GenericMember<Encoding,Allocator>* 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<false,Encoding,Allocator>::Type MemberIterator; //!< Member iterator for iterating in object.
typedef typename GenericMemberIterator<true,Encoding,Allocator>::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.
......
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