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
70493a10
Commit
70493a10
authored
Dec 23, 2015
by
Niels
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
iterator_wrapper for const objects (#83)
parent
00f9296d
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
431 additions
and
56 deletions
+431
-56
README.md
README.md
+1
-1
json.hpp
src/json.hpp
+45
-27
json.hpp.re2c
src/json.hpp.re2c
+45
-27
unit.cpp
test/unit.cpp
+340
-1
No files found.
README.md
View file @
70493a10
...
...
@@ -398,7 +398,7 @@ $ make
$
./json_unit
"*"
===============================================================================
All tests passed
(
3341
888
assertions
in
28
test
cases
)
All tests passed
(
3341
947
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
)
.
src/json.hpp
View file @
70493a10
...
...
@@ -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)
iterat
or_wrapper
_internal
&
operator
*
()
iterat
ion_proxy
_internal
&
operator
*
()
{
return
*
this
;
}
/// increment operator (needed for range-based for)
iterat
or_wrapper
_internal
&
operator
++
()
iterat
ion_proxy
_internal
&
operator
++
()
{
++
anchor
;
++
array_index
;
...
...
@@ -6197,7 +6189,7 @@ class basic_json
}
/// inequality operator (needed for range-based for)
bool
operator
!=
(
const
iterat
or_wrapper
_internal
&
o
)
bool
operator
!=
(
const
iterat
ion_proxy
_internal
&
o
)
{
return
anchor
!=
o
.
anchor
;
}
...
...
@@ -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 iterat
or wrapper
from a container
iterat
or_wrapper
(
typename
basic_json
::
reference
cont
)
/// construct iterat
ion proxy
from a container
iterat
ion_proxy
(
typename
IteratorType
::
reference
cont
)
:
container
(
cont
)
{}
/// return iterator begin (needed for range-based for)
iterat
or_wrapper
_internal
begin
()
iterat
ion_proxy
_internal
begin
()
{
return
iterat
or_wrapper
_internal
(
container
.
begin
());
return
iterat
ion_proxy
_internal
(
container
.
begin
());
}
/// return iterator end (needed for range-based for)
iterat
or_wrapper
_internal
end
()
iterat
ion_proxy
_internal
end
()
{
return
iterat
or_wrapper
_internal
(
container
.
end
());
return
iterat
ion_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 //
...
...
src/json.hpp.re2c
View file @
70493a10
...
...
@@ -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)
iterat
or_wrapper
_internal& operator*()
iterat
ion_proxy
_internal& operator*()
{
return *this;
}
/// increment operator (needed for range-based for)
iterat
or_wrapper
_internal& operator++()
iterat
ion_proxy
_internal& operator++()
{
++anchor;
++array_index;
...
...
@@ -6197,7 +6189,7 @@ class basic_json
}
/// inequality operator (needed for range-based for)
bool operator!= (const iterat
or_wrapper
_internal& o)
bool operator!= (const iterat
ion_proxy
_internal& o)
{
return anchor != o.anchor;
}
...
...
@@ -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 iterat
or wrapper
from a container
iterat
or_wrapper(typename basic_json
::reference cont)
/// construct iterat
ion proxy
from a container
iterat
ion_proxy(typename IteratorType
::reference cont)
: container(cont)
{}
/// return iterator begin (needed for range-based for)
iterat
or_wrapper
_internal begin()
iterat
ion_proxy
_internal begin()
{
return iterat
or_wrapper
_internal(container.begin());
return iterat
ion_proxy
_internal(container.begin());
}
/// return iterator end (needed for range-based for)
iterat
or_wrapper
_internal end()
iterat
ion_proxy
_internal end()
{
return iterat
or_wrapper
_internal(container.end());
return iterat
ion_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 //
...
...
test/unit.cpp
View file @
70493a10
...
...
@@ -9653,6 +9653,141 @@ TEST_CASE("iterator_wrapper")
}
}
SECTION
(
"const object"
)
{
SECTION
(
"value"
)
{
const
json
j
=
{{
"A"
,
1
},
{
"B"
,
2
}};
int
counter
=
1
;
for
(
auto
i
:
json
::
iterator_wrapper
(
j
))
{
switch
(
counter
++
)
{
case
1
:
{
CHECK
(
i
.
key
()
==
"A"
);
CHECK
(
i
.
value
()
==
json
(
1
));
break
;
}
case
2
:
{
CHECK
(
i
.
key
()
==
"B"
);
CHECK
(
i
.
value
()
==
json
(
2
));
break
;
}
default
:
{
break
;
}
}
}
CHECK
(
counter
==
3
);
}
SECTION
(
"reference"
)
{
const
json
j
=
{{
"A"
,
1
},
{
"B"
,
2
}};
int
counter
=
1
;
for
(
auto
&
i
:
json
::
iterator_wrapper
(
j
))
{
switch
(
counter
++
)
{
case
1
:
{
CHECK
(
i
.
key
()
==
"A"
);
CHECK
(
i
.
value
()
==
json
(
1
));
break
;
}
case
2
:
{
CHECK
(
i
.
key
()
==
"B"
);
CHECK
(
i
.
value
()
==
json
(
2
));
break
;
}
default
:
{
break
;
}
}
}
CHECK
(
counter
==
3
);
}
SECTION
(
"const value"
)
{
const
json
j
=
{{
"A"
,
1
},
{
"B"
,
2
}};
int
counter
=
1
;
for
(
const
auto
i
:
json
::
iterator_wrapper
(
j
))
{
switch
(
counter
++
)
{
case
1
:
{
CHECK
(
i
.
key
()
==
"A"
);
CHECK
(
i
.
value
()
==
json
(
1
));
break
;
}
case
2
:
{
CHECK
(
i
.
key
()
==
"B"
);
CHECK
(
i
.
value
()
==
json
(
2
));
break
;
}
default
:
{
break
;
}
}
}
CHECK
(
counter
==
3
);
}
SECTION
(
"const reference"
)
{
const
json
j
=
{{
"A"
,
1
},
{
"B"
,
2
}};
int
counter
=
1
;
for
(
const
auto
&
i
:
json
::
iterator_wrapper
(
j
))
{
switch
(
counter
++
)
{
case
1
:
{
CHECK
(
i
.
key
()
==
"A"
);
CHECK
(
i
.
value
()
==
json
(
1
));
break
;
}
case
2
:
{
CHECK
(
i
.
key
()
==
"B"
);
CHECK
(
i
.
value
()
==
json
(
2
));
break
;
}
default
:
{
break
;
}
}
}
CHECK
(
counter
==
3
);
}
}
SECTION
(
"array"
)
{
SECTION
(
"value"
)
...
...
@@ -9799,6 +9934,141 @@ TEST_CASE("iterator_wrapper")
}
}
SECTION
(
"const array"
)
{
SECTION
(
"value"
)
{
const
json
j
=
{
"A"
,
"B"
};
int
counter
=
1
;
for
(
auto
i
:
json
::
iterator_wrapper
(
j
))
{
switch
(
counter
++
)
{
case
1
:
{
CHECK
(
i
.
key
()
==
"0"
);
CHECK
(
i
.
value
()
==
"A"
);
break
;
}
case
2
:
{
CHECK
(
i
.
key
()
==
"1"
);
CHECK
(
i
.
value
()
==
"B"
);
break
;
}
default
:
{
break
;
}
}
}
CHECK
(
counter
==
3
);
}
SECTION
(
"reference"
)
{
const
json
j
=
{
"A"
,
"B"
};
int
counter
=
1
;
for
(
auto
&
i
:
json
::
iterator_wrapper
(
j
))
{
switch
(
counter
++
)
{
case
1
:
{
CHECK
(
i
.
key
()
==
"0"
);
CHECK
(
i
.
value
()
==
"A"
);
break
;
}
case
2
:
{
CHECK
(
i
.
key
()
==
"1"
);
CHECK
(
i
.
value
()
==
"B"
);
break
;
}
default
:
{
break
;
}
}
}
CHECK
(
counter
==
3
);
}
SECTION
(
"const value"
)
{
const
json
j
=
{
"A"
,
"B"
};
int
counter
=
1
;
for
(
const
auto
i
:
json
::
iterator_wrapper
(
j
))
{
switch
(
counter
++
)
{
case
1
:
{
CHECK
(
i
.
key
()
==
"0"
);
CHECK
(
i
.
value
()
==
"A"
);
break
;
}
case
2
:
{
CHECK
(
i
.
key
()
==
"1"
);
CHECK
(
i
.
value
()
==
"B"
);
break
;
}
default
:
{
break
;
}
}
}
CHECK
(
counter
==
3
);
}
SECTION
(
"const reference"
)
{
const
json
j
=
{
"A"
,
"B"
};
int
counter
=
1
;
for
(
const
auto
&
i
:
json
::
iterator_wrapper
(
j
))
{
switch
(
counter
++
)
{
case
1
:
{
CHECK
(
i
.
key
()
==
"0"
);
CHECK
(
i
.
value
()
==
"A"
);
break
;
}
case
2
:
{
CHECK
(
i
.
key
()
==
"1"
);
CHECK
(
i
.
value
()
==
"B"
);
break
;
}
default
:
{
break
;
}
}
}
CHECK
(
counter
==
3
);
}
}
SECTION
(
"primitive"
)
{
SECTION
(
"value"
)
...
...
@@ -9826,9 +10096,15 @@ TEST_CASE("iterator_wrapper")
++
counter
;
CHECK
(
i
.
key
()
==
""
);
CHECK
(
i
.
value
()
==
json
(
1
));
// change value
i
.
value
()
=
json
(
2
);
}
CHECK
(
counter
==
2
);
// check if value has changed
CHECK
(
j
==
json
(
2
));
}
SECTION
(
"const value"
)
...
...
@@ -9846,7 +10122,7 @@ TEST_CASE("iterator_wrapper")
CHECK
(
counter
==
2
);
}
SECTION
(
"reference"
)
SECTION
(
"
const
reference"
)
{
json
j
=
1
;
int
counter
=
1
;
...
...
@@ -9861,6 +10137,69 @@ TEST_CASE("iterator_wrapper")
CHECK
(
counter
==
2
);
}
}
SECTION
(
"const primitive"
)
{
SECTION
(
"value"
)
{
const
json
j
=
1
;
int
counter
=
1
;
for
(
auto
i
:
json
::
iterator_wrapper
(
j
))
{
++
counter
;
CHECK
(
i
.
key
()
==
""
);
CHECK
(
i
.
value
()
==
json
(
1
));
}
CHECK
(
counter
==
2
);
}
SECTION
(
"reference"
)
{
const
json
j
=
1
;
int
counter
=
1
;
for
(
auto
&
i
:
json
::
iterator_wrapper
(
j
))
{
++
counter
;
CHECK
(
i
.
key
()
==
""
);
CHECK
(
i
.
value
()
==
json
(
1
));
}
CHECK
(
counter
==
2
);
}
SECTION
(
"const value"
)
{
const
json
j
=
1
;
int
counter
=
1
;
for
(
const
auto
i
:
json
::
iterator_wrapper
(
j
))
{
++
counter
;
CHECK
(
i
.
key
()
==
""
);
CHECK
(
i
.
value
()
==
json
(
1
));
}
CHECK
(
counter
==
2
);
}
SECTION
(
"const reference"
)
{
const
json
j
=
1
;
int
counter
=
1
;
for
(
const
auto
&
i
:
json
::
iterator_wrapper
(
j
))
{
++
counter
;
CHECK
(
i
.
key
()
==
""
);
CHECK
(
i
.
value
()
==
json
(
1
));
}
CHECK
(
counter
==
2
);
}
}
}
TEST_CASE
(
"compliance tests from json.org"
)
...
...
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