Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
J
json
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
json
Commits
bf06cf6c
Unverified
Commit
bf06cf6c
authored
Aug 14, 2017
by
Théo DELRIEU
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add detail/iterators/iter_impl.hpp
parent
3e65a652
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
615 additions
and
596 deletions
+615
-596
Makefile
Makefile
+2
-1
iter_impl.hpp
src/detail/iterators/iter_impl.hpp
+612
-0
json.hpp
src/json.hpp
+1
-595
No files found.
Makefile
View file @
bf06cf6c
...
@@ -14,7 +14,8 @@ SRCS = ${SRCDIR}/json.hpp \
...
@@ -14,7 +14,8 @@ SRCS = ${SRCDIR}/json.hpp \
${
SRCDIR
}
/detail/parsing/lexer.hpp
\
${
SRCDIR
}
/detail/parsing/lexer.hpp
\
${
SRCDIR
}
/detail/parsing/parser.hpp
\
${
SRCDIR
}
/detail/parsing/parser.hpp
\
${
SRCDIR
}
/detail/iterators/primitive_iterator.hpp
\
${
SRCDIR
}
/detail/iterators/primitive_iterator.hpp
\
${
SRCDIR
}
/detail/iterators/internal_iterator.hpp
${
SRCDIR
}
/detail/iterators/internal_iterator.hpp
\
${
SRCDIR
}
/detail/iterators/iter_impl.hpp
...
...
src/detail/iterators/iter_impl.hpp
0 → 100644
View file @
bf06cf6c
#ifndef NLOHMANN_JSON_DETAIL_ITERATORS_ITER_IMPL_HPP
#define NLOHMANN_JSON_DETAIL_ITERATORS_ITER_IMPL_HPP
#include <iterator>
#include <type_traits>
#include "detail/exceptions.hpp"
#include "detail/macro_scope.hpp"
namespace
nlohmann
{
namespace
detail
{
// forward declare, to be able to friend it later on
template
<
typename
IteratorType
>
class
iteration_proxy
;
/*!
@brief a template for a bidirectional iterator for the @ref basic_json class
This class implements a both iterators (iterator and const_iterator) for the
@ref basic_json class.
@note An iterator is called *initialized* when a pointer to a JSON value has
been set (e.g., by a constructor or a copy assignment). If the iterator is
default-constructed, it is *uninitialized* and most methods are undefined.
**The library uses assertions to detect calls on uninitialized iterators.**
@requirement The class satisfies the following concept requirements:
-
[BidirectionalIterator](http://en.cppreference.com/w/cpp/concept/BidirectionalIterator):
The iterator that can be moved can be moved in both directions (i.e.
incremented and decremented).
@since version 1.0.0, simplified in version 2.0.9, change to bidirectional
iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
*/
template
<
typename
BasicJsonType
>
class
iter_impl
{
/// allow basic_json to access private members
friend
iter_impl
<
typename
std
::
conditional
<
std
::
is_const
<
BasicJsonType
>::
value
,
typename
std
::
remove_const
<
BasicJsonType
>::
type
,
const
BasicJsonType
>::
type
>
;
friend
BasicJsonType
;
friend
iteration_proxy
<
iter_impl
>
;
using
object_t
=
typename
BasicJsonType
::
object_t
;
using
array_t
=
typename
BasicJsonType
::
array_t
;
// make sure BasicJsonType is basic_json or const basic_json
static_assert
(
is_basic_json
<
typename
std
::
remove_const
<
BasicJsonType
>::
type
>::
value
,
"iter_impl only accepts (const) basic_json"
);
public
:
/// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
/// The C++ Standard has never required user-defined iterators to derive from std::iterator.
/// A user-defined iterator should provide publicly accessible typedefs named
/// iterator_category, value_type, difference_type, pointer, and reference.
/// Note that value_type is required to be non-const, even for constant iterators.
using
iterator_category
=
std
::
bidirectional_iterator_tag
;
/// the type of the values when the iterator is dereferenced
using
value_type
=
typename
BasicJsonType
::
value_type
;
/// a type to represent differences between iterators
using
difference_type
=
typename
BasicJsonType
::
difference_type
;
/// defines a pointer to the type iterated over (value_type)
using
pointer
=
typename
std
::
conditional
<
std
::
is_const
<
BasicJsonType
>::
value
,
typename
BasicJsonType
::
const_pointer
,
typename
BasicJsonType
::
pointer
>::
type
;
/// defines a reference to the type iterated over (value_type)
using
reference
=
typename
std
::
conditional
<
std
::
is_const
<
BasicJsonType
>::
value
,
typename
BasicJsonType
::
const_reference
,
typename
BasicJsonType
::
reference
>::
type
;
/// default constructor
iter_impl
()
=
default
;
/*!
@brief constructor for a given JSON instance
@param[in] object pointer to a JSON object for this iterator
@pre object != nullptr
@post The iterator is initialized; i.e. `m_object != nullptr`.
*/
explicit
iter_impl
(
pointer
object
)
noexcept
:
m_object
(
object
)
{
assert
(
m_object
!=
nullptr
);
switch
(
m_object
->
m_type
)
{
case
value_t
:
:
object
:
{
m_it
.
object_iterator
=
typename
object_t
::
iterator
();
break
;
}
case
value_t
:
:
array
:
{
m_it
.
array_iterator
=
typename
array_t
::
iterator
();
break
;
}
default:
{
m_it
.
primitive_iterator
=
primitive_iterator_t
();
break
;
}
}
}
/*!
@note The conventional copy constructor and copy assignment are implicitly
defined. Combined with the following converting constructor and
assignment, they support: (1) copy from iterator to iterator, (2)
copy from const iterator to const iterator, and (3) conversion from
iterator to const iterator. However conversion from const iterator
to iterator is not defined.
*/
/*!
@brief converting constructor
@param[in] other non-const iterator to copy from
@note It is not checked whether @a other is initialized.
*/
iter_impl
(
const
iter_impl
<
typename
std
::
remove_const
<
BasicJsonType
>::
type
>&
other
)
noexcept
:
m_object
(
other
.
m_object
),
m_it
(
other
.
m_it
)
{}
/*!
@brief converting assignment
@param[in,out] other non-const iterator to copy from
@return const/non-const iterator
@note It is not checked whether @a other is initialized.
*/
iter_impl
&
operator
=
(
const
iter_impl
<
typename
std
::
remove_const
<
BasicJsonType
>::
type
>&
other
)
noexcept
{
m_object
=
other
.
m_object
;
m_it
=
other
.
m_it
;
return
*
this
;
}
private
:
/*!
@brief set the iterator to the first value
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
void
set_begin
()
noexcept
{
assert
(
m_object
!=
nullptr
);
switch
(
m_object
->
m_type
)
{
case
value_t
:
:
object
:
{
m_it
.
object_iterator
=
m_object
->
m_value
.
object
->
begin
();
break
;
}
case
value_t
:
:
array
:
{
m_it
.
array_iterator
=
m_object
->
m_value
.
array
->
begin
();
break
;
}
case
value_t
:
:
null
:
{
// set to end so begin()==end() is true: null is empty
m_it
.
primitive_iterator
.
set_end
();
break
;
}
default
:
{
m_it
.
primitive_iterator
.
set_begin
();
break
;
}
}
}
/*!
@brief set the iterator past the last value
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
void
set_end
()
noexcept
{
assert
(
m_object
!=
nullptr
);
switch
(
m_object
->
m_type
)
{
case
value_t
:
:
object
:
{
m_it
.
object_iterator
=
m_object
->
m_value
.
object
->
end
();
break
;
}
case
value_t
:
:
array
:
{
m_it
.
array_iterator
=
m_object
->
m_value
.
array
->
end
();
break
;
}
default
:
{
m_it
.
primitive_iterator
.
set_end
();
break
;
}
}
}
public
:
/*!
@brief return a reference to the value pointed to by the iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
reference
operator
*
()
const
{
assert
(
m_object
!=
nullptr
);
switch
(
m_object
->
m_type
)
{
case
value_t
:
:
object
:
{
assert
(
m_it
.
object_iterator
!=
m_object
->
m_value
.
object
->
end
());
return
m_it
.
object_iterator
->
second
;
}
case
value_t
:
:
array
:
{
assert
(
m_it
.
array_iterator
!=
m_object
->
m_value
.
array
->
end
());
return
*
m_it
.
array_iterator
;
}
case
value_t
:
:
null
:
JSON_THROW
(
invalid_iterator
::
create
(
214
,
"cannot get value"
));
default
:
{
if
(
JSON_LIKELY
(
m_it
.
primitive_iterator
.
is_begin
()))
{
return
*
m_object
;
}
JSON_THROW
(
invalid_iterator
::
create
(
214
,
"cannot get value"
));
}
}
}
/*!
@brief dereference the iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
pointer
operator
->
()
const
{
assert
(
m_object
!=
nullptr
);
switch
(
m_object
->
m_type
)
{
case
value_t
:
:
object
:
{
assert
(
m_it
.
object_iterator
!=
m_object
->
m_value
.
object
->
end
());
return
&
(
m_it
.
object_iterator
->
second
);
}
case
value_t
:
:
array
:
{
assert
(
m_it
.
array_iterator
!=
m_object
->
m_value
.
array
->
end
());
return
&*
m_it
.
array_iterator
;
}
default
:
{
if
(
JSON_LIKELY
(
m_it
.
primitive_iterator
.
is_begin
()))
{
return
m_object
;
}
JSON_THROW
(
invalid_iterator
::
create
(
214
,
"cannot get value"
));
}
}
}
/*!
@brief post-increment (it++)
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
iter_impl
const
operator
++
(
int
)
{
auto
result
=
*
this
;
++
(
*
this
);
return
result
;
}
/*!
@brief pre-increment (++it)
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
iter_impl
&
operator
++
()
{
assert
(
m_object
!=
nullptr
);
switch
(
m_object
->
m_type
)
{
case
value_t
:
:
object
:
{
std
::
advance
(
m_it
.
object_iterator
,
1
);
break
;
}
case
value_t
:
:
array
:
{
std
::
advance
(
m_it
.
array_iterator
,
1
);
break
;
}
default
:
{
++
m_it
.
primitive_iterator
;
break
;
}
}
return
*
this
;
}
/*!
@brief post-decrement (it--)
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
iter_impl
const
operator
--
(
int
)
{
auto
result
=
*
this
;
--
(
*
this
);
return
result
;
}
/*!
@brief pre-decrement (--it)
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
iter_impl
&
operator
--
()
{
assert
(
m_object
!=
nullptr
);
switch
(
m_object
->
m_type
)
{
case
value_t
:
:
object
:
{
std
::
advance
(
m_it
.
object_iterator
,
-
1
);
break
;
}
case
value_t
:
:
array
:
{
std
::
advance
(
m_it
.
array_iterator
,
-
1
);
break
;
}
default
:
{
--
m_it
.
primitive_iterator
;
break
;
}
}
return
*
this
;
}
/*!
@brief comparison: equal
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
bool
operator
==
(
const
iter_impl
&
other
)
const
{
// if objects are not the same, the comparison is undefined
if
(
JSON_UNLIKELY
(
m_object
!=
other
.
m_object
))
{
JSON_THROW
(
invalid_iterator
::
create
(
212
,
"cannot compare iterators of different containers"
));
}
assert
(
m_object
!=
nullptr
);
switch
(
m_object
->
m_type
)
{
case
value_t
:
:
object
:
return
(
m_it
.
object_iterator
==
other
.
m_it
.
object_iterator
);
case
value_t
:
:
array
:
return
(
m_it
.
array_iterator
==
other
.
m_it
.
array_iterator
);
default
:
return
(
m_it
.
primitive_iterator
==
other
.
m_it
.
primitive_iterator
);
}
}
/*!
@brief comparison: not equal
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
bool
operator
!=
(
const
iter_impl
&
other
)
const
{
return
not
operator
==
(
other
);
}
/*!
@brief comparison: smaller
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
bool
operator
<
(
const
iter_impl
&
other
)
const
{
// if objects are not the same, the comparison is undefined
if
(
JSON_UNLIKELY
(
m_object
!=
other
.
m_object
))
{
JSON_THROW
(
invalid_iterator
::
create
(
212
,
"cannot compare iterators of different containers"
));
}
assert
(
m_object
!=
nullptr
);
switch
(
m_object
->
m_type
)
{
case
value_t
:
:
object
:
JSON_THROW
(
invalid_iterator
::
create
(
213
,
"cannot compare order of object iterators"
));
case
value_t
:
:
array
:
return
(
m_it
.
array_iterator
<
other
.
m_it
.
array_iterator
);
default
:
return
(
m_it
.
primitive_iterator
<
other
.
m_it
.
primitive_iterator
);
}
}
/*!
@brief comparison: less than or equal
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
bool
operator
<=
(
const
iter_impl
&
other
)
const
{
return
not
other
.
operator
<
(
*
this
);
}
/*!
@brief comparison: greater than
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
bool
operator
>
(
const
iter_impl
&
other
)
const
{
return
not
operator
<=
(
other
);
}
/*!
@brief comparison: greater than or equal
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
bool
operator
>=
(
const
iter_impl
&
other
)
const
{
return
not
operator
<
(
other
);
}
/*!
@brief add to iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
iter_impl
&
operator
+=
(
difference_type
i
)
{
assert
(
m_object
!=
nullptr
);
switch
(
m_object
->
m_type
)
{
case
value_t
:
:
object
:
JSON_THROW
(
invalid_iterator
::
create
(
209
,
"cannot use offsets with object iterators"
));
case
value_t
:
:
array
:
{
std
::
advance
(
m_it
.
array_iterator
,
i
);
break
;
}
default
:
{
m_it
.
primitive_iterator
+=
i
;
break
;
}
}
return
*
this
;
}
/*!
@brief subtract from iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
iter_impl
&
operator
-=
(
difference_type
i
)
{
return
operator
+=
(
-
i
);
}
/*!
@brief add to iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
iter_impl
operator
+
(
difference_type
i
)
const
{
auto
result
=
*
this
;
result
+=
i
;
return
result
;
}
/*!
@brief addition of distance and iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
friend
iter_impl
operator
+
(
difference_type
i
,
const
iter_impl
&
it
)
{
auto
result
=
it
;
result
+=
i
;
return
result
;
}
/*!
@brief subtract from iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
iter_impl
operator
-
(
difference_type
i
)
const
{
auto
result
=
*
this
;
result
-=
i
;
return
result
;
}
/*!
@brief return difference
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
difference_type
operator
-
(
const
iter_impl
&
other
)
const
{
assert
(
m_object
!=
nullptr
);
switch
(
m_object
->
m_type
)
{
case
value_t
:
:
object
:
JSON_THROW
(
invalid_iterator
::
create
(
209
,
"cannot use offsets with object iterators"
));
case
value_t
:
:
array
:
return
m_it
.
array_iterator
-
other
.
m_it
.
array_iterator
;
default
:
return
m_it
.
primitive_iterator
-
other
.
m_it
.
primitive_iterator
;
}
}
/*!
@brief access to successor
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
reference
operator
[](
difference_type
n
)
const
{
assert
(
m_object
!=
nullptr
);
switch
(
m_object
->
m_type
)
{
case
value_t
:
:
object
:
JSON_THROW
(
invalid_iterator
::
create
(
208
,
"cannot use operator[] for object iterators"
));
case
value_t
:
:
array
:
return
*
std
::
next
(
m_it
.
array_iterator
,
n
);
case
value_t
:
:
null
:
JSON_THROW
(
invalid_iterator
::
create
(
214
,
"cannot get value"
));
default
:
{
if
(
JSON_LIKELY
(
m_it
.
primitive_iterator
.
get_value
()
==
-
n
))
{
return
*
m_object
;
}
JSON_THROW
(
invalid_iterator
::
create
(
214
,
"cannot get value"
));
}
}
}
/*!
@brief return the key of an object iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
typename
object_t
::
key_type
key
()
const
{
assert
(
m_object
!=
nullptr
);
if
(
JSON_LIKELY
(
m_object
->
is_object
()))
{
return
m_it
.
object_iterator
->
first
;
}
JSON_THROW
(
invalid_iterator
::
create
(
207
,
"cannot use key() for non-object iterators"
));
}
/*!
@brief return the value of an iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
reference
value
()
const
{
return
operator
*
();
}
private
:
/// associated JSON instance
pointer
m_object
=
nullptr
;
/// the actual iterator of the associated instance
internal_iterator
<
typename
std
::
remove_const
<
BasicJsonType
>::
type
>
m_it
=
{};
};
}
}
#endif
src/json.hpp
View file @
bf06cf6c
...
@@ -62,6 +62,7 @@ SOFTWARE.
...
@@ -62,6 +62,7 @@ SOFTWARE.
#include "detail/parsing/parser.hpp"
#include "detail/parsing/parser.hpp"
#include "detail/iterators/primitive_iterator.hpp"
#include "detail/iterators/primitive_iterator.hpp"
#include "detail/iterators/internal_iterator.hpp"
#include "detail/iterators/internal_iterator.hpp"
#include "detail/iterators/iter_impl.hpp"
/*!
/*!
@brief namespace for Niels Lohmann
@brief namespace for Niels Lohmann
...
@@ -76,601 +77,6 @@ namespace detail
...
@@ -76,601 +77,6 @@ namespace detail
// iterators //
// iterators //
///////////////
///////////////
template
<
typename
IteratorType
>
class
iteration_proxy
;
/*!
@brief a template for a bidirectional iterator for the @ref basic_json class
This class implements a both iterators (iterator and const_iterator) for the
@ref basic_json class.
@note An iterator is called *initialized* when a pointer to a JSON value has
been set (e.g., by a constructor or a copy assignment). If the iterator is
default-constructed, it is *uninitialized* and most methods are undefined.
**The library uses assertions to detect calls on uninitialized iterators.**
@requirement The class satisfies the following concept requirements:
-
[BidirectionalIterator](http://en.cppreference.com/w/cpp/concept/BidirectionalIterator):
The iterator that can be moved can be moved in both directions (i.e.
incremented and decremented).
@since version 1.0.0, simplified in version 2.0.9, change to bidirectional
iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
*/
template
<
typename
BasicJsonType
>
class
iter_impl
{
/// allow basic_json to access private members
friend
iter_impl
<
typename
std
::
conditional
<
std
::
is_const
<
BasicJsonType
>::
value
,
typename
std
::
remove_const
<
BasicJsonType
>::
type
,
const
BasicJsonType
>::
type
>
;
friend
BasicJsonType
;
friend
iteration_proxy
<
iter_impl
>
;
using
object_t
=
typename
BasicJsonType
::
object_t
;
using
array_t
=
typename
BasicJsonType
::
array_t
;
// make sure BasicJsonType is basic_json or const basic_json
static_assert
(
is_basic_json
<
typename
std
::
remove_const
<
BasicJsonType
>::
type
>::
value
,
"iter_impl only accepts (const) basic_json"
);
public
:
/// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
/// The C++ Standard has never required user-defined iterators to derive from std::iterator.
/// A user-defined iterator should provide publicly accessible typedefs named
/// iterator_category, value_type, difference_type, pointer, and reference.
/// Note that value_type is required to be non-const, even for constant iterators.
using
iterator_category
=
std
::
bidirectional_iterator_tag
;
/// the type of the values when the iterator is dereferenced
using
value_type
=
typename
BasicJsonType
::
value_type
;
/// a type to represent differences between iterators
using
difference_type
=
typename
BasicJsonType
::
difference_type
;
/// defines a pointer to the type iterated over (value_type)
using
pointer
=
typename
std
::
conditional
<
std
::
is_const
<
BasicJsonType
>::
value
,
typename
BasicJsonType
::
const_pointer
,
typename
BasicJsonType
::
pointer
>::
type
;
/// defines a reference to the type iterated over (value_type)
using
reference
=
typename
std
::
conditional
<
std
::
is_const
<
BasicJsonType
>::
value
,
typename
BasicJsonType
::
const_reference
,
typename
BasicJsonType
::
reference
>::
type
;
/// default constructor
iter_impl
()
=
default
;
/*!
@brief constructor for a given JSON instance
@param[in] object pointer to a JSON object for this iterator
@pre object != nullptr
@post The iterator is initialized; i.e. `m_object != nullptr`.
*/
explicit
iter_impl
(
pointer
object
)
noexcept
:
m_object
(
object
)
{
assert
(
m_object
!=
nullptr
);
switch
(
m_object
->
m_type
)
{
case
value_t
:
:
object
:
{
m_it
.
object_iterator
=
typename
object_t
::
iterator
();
break
;
}
case
value_t
:
:
array
:
{
m_it
.
array_iterator
=
typename
array_t
::
iterator
();
break
;
}
default:
{
m_it
.
primitive_iterator
=
primitive_iterator_t
();
break
;
}
}
}
/*!
@note The conventional copy constructor and copy assignment are implicitly
defined. Combined with the following converting constructor and
assignment, they support: (1) copy from iterator to iterator, (2)
copy from const iterator to const iterator, and (3) conversion from
iterator to const iterator. However conversion from const iterator
to iterator is not defined.
*/
/*!
@brief converting constructor
@param[in] other non-const iterator to copy from
@note It is not checked whether @a other is initialized.
*/
iter_impl
(
const
iter_impl
<
typename
std
::
remove_const
<
BasicJsonType
>::
type
>&
other
)
noexcept
:
m_object
(
other
.
m_object
),
m_it
(
other
.
m_it
)
{}
/*!
@brief converting assignment
@param[in,out] other non-const iterator to copy from
@return const/non-const iterator
@note It is not checked whether @a other is initialized.
*/
iter_impl
&
operator
=
(
const
iter_impl
<
typename
std
::
remove_const
<
BasicJsonType
>::
type
>&
other
)
noexcept
{
m_object
=
other
.
m_object
;
m_it
=
other
.
m_it
;
return
*
this
;
}
private
:
/*!
@brief set the iterator to the first value
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
void
set_begin
()
noexcept
{
assert
(
m_object
!=
nullptr
);
switch
(
m_object
->
m_type
)
{
case
value_t
:
:
object
:
{
m_it
.
object_iterator
=
m_object
->
m_value
.
object
->
begin
();
break
;
}
case
value_t
:
:
array
:
{
m_it
.
array_iterator
=
m_object
->
m_value
.
array
->
begin
();
break
;
}
case
value_t
:
:
null
:
{
// set to end so begin()==end() is true: null is empty
m_it
.
primitive_iterator
.
set_end
();
break
;
}
default
:
{
m_it
.
primitive_iterator
.
set_begin
();
break
;
}
}
}
/*!
@brief set the iterator past the last value
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
void
set_end
()
noexcept
{
assert
(
m_object
!=
nullptr
);
switch
(
m_object
->
m_type
)
{
case
value_t
:
:
object
:
{
m_it
.
object_iterator
=
m_object
->
m_value
.
object
->
end
();
break
;
}
case
value_t
:
:
array
:
{
m_it
.
array_iterator
=
m_object
->
m_value
.
array
->
end
();
break
;
}
default
:
{
m_it
.
primitive_iterator
.
set_end
();
break
;
}
}
}
public
:
/*!
@brief return a reference to the value pointed to by the iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
reference
operator
*
()
const
{
assert
(
m_object
!=
nullptr
);
switch
(
m_object
->
m_type
)
{
case
value_t
:
:
object
:
{
assert
(
m_it
.
object_iterator
!=
m_object
->
m_value
.
object
->
end
());
return
m_it
.
object_iterator
->
second
;
}
case
value_t
:
:
array
:
{
assert
(
m_it
.
array_iterator
!=
m_object
->
m_value
.
array
->
end
());
return
*
m_it
.
array_iterator
;
}
case
value_t
:
:
null
:
JSON_THROW
(
invalid_iterator
::
create
(
214
,
"cannot get value"
));
default
:
{
if
(
JSON_LIKELY
(
m_it
.
primitive_iterator
.
is_begin
()))
{
return
*
m_object
;
}
JSON_THROW
(
invalid_iterator
::
create
(
214
,
"cannot get value"
));
}
}
}
/*!
@brief dereference the iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
pointer
operator
->
()
const
{
assert
(
m_object
!=
nullptr
);
switch
(
m_object
->
m_type
)
{
case
value_t
:
:
object
:
{
assert
(
m_it
.
object_iterator
!=
m_object
->
m_value
.
object
->
end
());
return
&
(
m_it
.
object_iterator
->
second
);
}
case
value_t
:
:
array
:
{
assert
(
m_it
.
array_iterator
!=
m_object
->
m_value
.
array
->
end
());
return
&*
m_it
.
array_iterator
;
}
default
:
{
if
(
JSON_LIKELY
(
m_it
.
primitive_iterator
.
is_begin
()))
{
return
m_object
;
}
JSON_THROW
(
invalid_iterator
::
create
(
214
,
"cannot get value"
));
}
}
}
/*!
@brief post-increment (it++)
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
iter_impl
const
operator
++
(
int
)
{
auto
result
=
*
this
;
++
(
*
this
);
return
result
;
}
/*!
@brief pre-increment (++it)
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
iter_impl
&
operator
++
()
{
assert
(
m_object
!=
nullptr
);
switch
(
m_object
->
m_type
)
{
case
value_t
:
:
object
:
{
std
::
advance
(
m_it
.
object_iterator
,
1
);
break
;
}
case
value_t
:
:
array
:
{
std
::
advance
(
m_it
.
array_iterator
,
1
);
break
;
}
default
:
{
++
m_it
.
primitive_iterator
;
break
;
}
}
return
*
this
;
}
/*!
@brief post-decrement (it--)
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
iter_impl
const
operator
--
(
int
)
{
auto
result
=
*
this
;
--
(
*
this
);
return
result
;
}
/*!
@brief pre-decrement (--it)
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
iter_impl
&
operator
--
()
{
assert
(
m_object
!=
nullptr
);
switch
(
m_object
->
m_type
)
{
case
value_t
:
:
object
:
{
std
::
advance
(
m_it
.
object_iterator
,
-
1
);
break
;
}
case
value_t
:
:
array
:
{
std
::
advance
(
m_it
.
array_iterator
,
-
1
);
break
;
}
default
:
{
--
m_it
.
primitive_iterator
;
break
;
}
}
return
*
this
;
}
/*!
@brief comparison: equal
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
bool
operator
==
(
const
iter_impl
&
other
)
const
{
// if objects are not the same, the comparison is undefined
if
(
JSON_UNLIKELY
(
m_object
!=
other
.
m_object
))
{
JSON_THROW
(
invalid_iterator
::
create
(
212
,
"cannot compare iterators of different containers"
));
}
assert
(
m_object
!=
nullptr
);
switch
(
m_object
->
m_type
)
{
case
value_t
:
:
object
:
return
(
m_it
.
object_iterator
==
other
.
m_it
.
object_iterator
);
case
value_t
:
:
array
:
return
(
m_it
.
array_iterator
==
other
.
m_it
.
array_iterator
);
default
:
return
(
m_it
.
primitive_iterator
==
other
.
m_it
.
primitive_iterator
);
}
}
/*!
@brief comparison: not equal
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
bool
operator
!=
(
const
iter_impl
&
other
)
const
{
return
not
operator
==
(
other
);
}
/*!
@brief comparison: smaller
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
bool
operator
<
(
const
iter_impl
&
other
)
const
{
// if objects are not the same, the comparison is undefined
if
(
JSON_UNLIKELY
(
m_object
!=
other
.
m_object
))
{
JSON_THROW
(
invalid_iterator
::
create
(
212
,
"cannot compare iterators of different containers"
));
}
assert
(
m_object
!=
nullptr
);
switch
(
m_object
->
m_type
)
{
case
value_t
:
:
object
:
JSON_THROW
(
invalid_iterator
::
create
(
213
,
"cannot compare order of object iterators"
));
case
value_t
:
:
array
:
return
(
m_it
.
array_iterator
<
other
.
m_it
.
array_iterator
);
default
:
return
(
m_it
.
primitive_iterator
<
other
.
m_it
.
primitive_iterator
);
}
}
/*!
@brief comparison: less than or equal
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
bool
operator
<=
(
const
iter_impl
&
other
)
const
{
return
not
other
.
operator
<
(
*
this
);
}
/*!
@brief comparison: greater than
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
bool
operator
>
(
const
iter_impl
&
other
)
const
{
return
not
operator
<=
(
other
);
}
/*!
@brief comparison: greater than or equal
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
bool
operator
>=
(
const
iter_impl
&
other
)
const
{
return
not
operator
<
(
other
);
}
/*!
@brief add to iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
iter_impl
&
operator
+=
(
difference_type
i
)
{
assert
(
m_object
!=
nullptr
);
switch
(
m_object
->
m_type
)
{
case
value_t
:
:
object
:
JSON_THROW
(
invalid_iterator
::
create
(
209
,
"cannot use offsets with object iterators"
));
case
value_t
:
:
array
:
{
std
::
advance
(
m_it
.
array_iterator
,
i
);
break
;
}
default
:
{
m_it
.
primitive_iterator
+=
i
;
break
;
}
}
return
*
this
;
}
/*!
@brief subtract from iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
iter_impl
&
operator
-=
(
difference_type
i
)
{
return
operator
+=
(
-
i
);
}
/*!
@brief add to iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
iter_impl
operator
+
(
difference_type
i
)
const
{
auto
result
=
*
this
;
result
+=
i
;
return
result
;
}
/*!
@brief addition of distance and iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
friend
iter_impl
operator
+
(
difference_type
i
,
const
iter_impl
&
it
)
{
auto
result
=
it
;
result
+=
i
;
return
result
;
}
/*!
@brief subtract from iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
iter_impl
operator
-
(
difference_type
i
)
const
{
auto
result
=
*
this
;
result
-=
i
;
return
result
;
}
/*!
@brief return difference
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
difference_type
operator
-
(
const
iter_impl
&
other
)
const
{
assert
(
m_object
!=
nullptr
);
switch
(
m_object
->
m_type
)
{
case
value_t
:
:
object
:
JSON_THROW
(
invalid_iterator
::
create
(
209
,
"cannot use offsets with object iterators"
));
case
value_t
:
:
array
:
return
m_it
.
array_iterator
-
other
.
m_it
.
array_iterator
;
default
:
return
m_it
.
primitive_iterator
-
other
.
m_it
.
primitive_iterator
;
}
}
/*!
@brief access to successor
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
reference
operator
[](
difference_type
n
)
const
{
assert
(
m_object
!=
nullptr
);
switch
(
m_object
->
m_type
)
{
case
value_t
:
:
object
:
JSON_THROW
(
invalid_iterator
::
create
(
208
,
"cannot use operator[] for object iterators"
));
case
value_t
:
:
array
:
return
*
std
::
next
(
m_it
.
array_iterator
,
n
);
case
value_t
:
:
null
:
JSON_THROW
(
invalid_iterator
::
create
(
214
,
"cannot get value"
));
default
:
{
if
(
JSON_LIKELY
(
m_it
.
primitive_iterator
.
get_value
()
==
-
n
))
{
return
*
m_object
;
}
JSON_THROW
(
invalid_iterator
::
create
(
214
,
"cannot get value"
));
}
}
}
/*!
@brief return the key of an object iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
typename
object_t
::
key_type
key
()
const
{
assert
(
m_object
!=
nullptr
);
if
(
JSON_LIKELY
(
m_object
->
is_object
()))
{
return
m_it
.
object_iterator
->
first
;
}
JSON_THROW
(
invalid_iterator
::
create
(
207
,
"cannot use key() for non-object iterators"
));
}
/*!
@brief return the value of an iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
reference
value
()
const
{
return
operator
*
();
}
private
:
/// associated JSON instance
pointer
m_object
=
nullptr
;
/// the actual iterator of the associated instance
internal_iterator
<
typename
std
::
remove_const
<
BasicJsonType
>::
type
>
m_it
=
{};
};
/// proxy class for the iterator_wrapper functions
/// proxy class for the iterator_wrapper functions
template
<
typename
IteratorType
>
class
iteration_proxy
template
<
typename
IteratorType
>
class
iteration_proxy
{
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment