Skip to content

Commit

Permalink
iterator_wrapper for const objects (#83)
Browse files Browse the repository at this point in the history
  • Loading branch information
nlohmann committed Dec 23, 2015
1 parent 00f9296 commit 70493a1
Show file tree
Hide file tree
Showing 4 changed files with 431 additions and 56 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ $ make
$ ./json_unit "*"

===============================================================================
All tests passed (3341888 assertions in 28 test cases)
All tests passed (3341947 assertions in 28 test cases)
```

For more information, have a look at the file [.travis.yml](https://github.com/nlohmann/json/blob/master/.travis.yml).
72 changes: 45 additions & 27 deletions src/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6152,43 +6152,35 @@ class basic_json
}
};

/*!
@brief wrapper to access iterator member functions in range-based for

This class allows to access @ref iterator::key() and @ref iterator::value()
during range-based for loops. In these loops, a reference to the JSON
values is returned, so there is no access to the underlying iterator.
*/
class iterator_wrapper
private:
/// proxy class for the iterator_wrapper functions
template<typename IteratorType>
class iteration_proxy
{
private:
/// the container to iterate
typename basic_json::reference container;
/// the type of the iterator to use while iteration
using json_iterator = decltype(std::begin(container));

/// internal iterator wrapper
class iterator_wrapper_internal
/// helper class for iteration
class iteration_proxy_internal
{
private:
/// the iterator
json_iterator anchor;
IteratorType anchor;
/// an index for arrays
size_t array_index = 0;

public:
/// construct wrapper given an iterator
iterator_wrapper_internal(json_iterator i) : anchor(i)
iteration_proxy_internal(IteratorType it)
: anchor(it)
{}

/// dereference operator (needed for range-based for)
iterator_wrapper_internal& operator*()
iteration_proxy_internal& operator*()
{
return *this;
}

/// increment operator (needed for range-based for)
iterator_wrapper_internal& operator++()
iteration_proxy_internal& operator++()
{
++anchor;
++array_index;
Expand All @@ -6197,7 +6189,7 @@ class basic_json
}

/// inequality operator (needed for range-based for)
bool operator!= (const iterator_wrapper_internal& o)
bool operator!= (const iteration_proxy_internal& o)
{
return anchor != o.anchor;
}
Expand Down Expand Up @@ -6228,31 +6220,57 @@ class basic_json
}

/// return value of the iterator
typename json_iterator::reference value() const
typename IteratorType::reference value() const
{
return anchor.value();
}
};

/// the container to iterate
typename IteratorType::reference container;

public:
/// construct iterator wrapper from a container
iterator_wrapper(typename basic_json::reference cont)
/// construct iteration proxy from a container
iteration_proxy(typename IteratorType::reference cont)
: container(cont)
{}

/// return iterator begin (needed for range-based for)
iterator_wrapper_internal begin()
iteration_proxy_internal begin()
{
return iterator_wrapper_internal(container.begin());
return iteration_proxy_internal(container.begin());
}

/// return iterator end (needed for range-based for)
iterator_wrapper_internal end()
iteration_proxy_internal end()
{
return iterator_wrapper_internal(container.end());
return iteration_proxy_internal(container.end());
}
};

public:
/*!
@brief wrapper to access iterator member functions in range-based for
This functuion allows to access @ref iterator::key() and @ref
iterator::value() during range-based for loops. In these loops, a reference
to the JSON values is returned, so there is no access to the underlying
iterator.
*/
static iteration_proxy<iterator> iterator_wrapper(reference cont)
{
return iteration_proxy<iterator>(cont);
}

/*!
@copydoc iterator_wrapper(reference)
*/
static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
{
return iteration_proxy<const_iterator>(cont);
}


private:
//////////////////////
// lexer and parser //
Expand Down
72 changes: 45 additions & 27 deletions src/json.hpp.re2c
Original file line number Diff line number Diff line change
Expand Up @@ -6152,43 +6152,35 @@ class basic_json
}
};

/*!
@brief wrapper to access iterator member functions in range-based for

This class allows to access @ref iterator::key() and @ref iterator::value()
during range-based for loops. In these loops, a reference to the JSON
values is returned, so there is no access to the underlying iterator.
*/
class iterator_wrapper
private:
/// proxy class for the iterator_wrapper functions
template<typename IteratorType>
class iteration_proxy
{
private:
/// the container to iterate
typename basic_json::reference container;
/// the type of the iterator to use while iteration
using json_iterator = decltype(std::begin(container));

/// internal iterator wrapper
class iterator_wrapper_internal
/// helper class for iteration
class iteration_proxy_internal
{
private:
/// the iterator
json_iterator anchor;
IteratorType anchor;
/// an index for arrays
size_t array_index = 0;

public:
/// construct wrapper given an iterator
iterator_wrapper_internal(json_iterator i) : anchor(i)
iteration_proxy_internal(IteratorType it)
: anchor(it)
{}

/// dereference operator (needed for range-based for)
iterator_wrapper_internal& operator*()
iteration_proxy_internal& operator*()
{
return *this;
}

/// increment operator (needed for range-based for)
iterator_wrapper_internal& operator++()
iteration_proxy_internal& operator++()
{
++anchor;
++array_index;
Expand All @@ -6197,7 +6189,7 @@ class basic_json
}

/// inequality operator (needed for range-based for)
bool operator!= (const iterator_wrapper_internal& o)
bool operator!= (const iteration_proxy_internal& o)
{
return anchor != o.anchor;
}
Expand Down Expand Up @@ -6228,31 +6220,57 @@ class basic_json
}

/// return value of the iterator
typename json_iterator::reference value() const
typename IteratorType::reference value() const
{
return anchor.value();
}
};

/// the container to iterate
typename IteratorType::reference container;

public:
/// construct iterator wrapper from a container
iterator_wrapper(typename basic_json::reference cont)
/// construct iteration proxy from a container
iteration_proxy(typename IteratorType::reference cont)
: container(cont)
{}

/// return iterator begin (needed for range-based for)
iterator_wrapper_internal begin()
iteration_proxy_internal begin()
{
return iterator_wrapper_internal(container.begin());
return iteration_proxy_internal(container.begin());
}

/// return iterator end (needed for range-based for)
iterator_wrapper_internal end()
iteration_proxy_internal end()
{
return iterator_wrapper_internal(container.end());
return iteration_proxy_internal(container.end());
}
};

public:
/*!
@brief wrapper to access iterator member functions in range-based for

This functuion allows to access @ref iterator::key() and @ref
iterator::value() during range-based for loops. In these loops, a reference
to the JSON values is returned, so there is no access to the underlying
iterator.
*/
static iteration_proxy<iterator> iterator_wrapper(reference cont)
{
return iteration_proxy<iterator>(cont);
}

/*!
@copydoc iterator_wrapper(reference)
*/
static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
{
return iteration_proxy<const_iterator>(cont);
}


private:
//////////////////////
// lexer and parser //
Expand Down
Loading

0 comments on commit 70493a1

Please sign in to comment.