Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
R
rapidjson
Project
Project
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
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
rapidjson
Commits
59309b5d
Commit
59309b5d
authored
Feb 13, 2016
by
Milo Yip
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add GenericArray helper class with range-based for
parent
c6946fd2
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
157 additions
and
22 deletions
+157
-22
document.h
include/rapidjson/document.h
+72
-1
rapidjson.h
include/rapidjson/rapidjson.h
+11
-0
valuetest.cpp
test/unittest/valuetest.cpp
+74
-21
No files found.
include/rapidjson/document.h
View file @
59309b5d
...
...
@@ -483,6 +483,9 @@ struct TypeHelper<ValueType, std::basic_string<typename ValueType::Ch> > {
}
// namespace internal
template
<
typename
ValueType
>
class
GenericArray
;
///////////////////////////////////////////////////////////////////////////////
// GenericValue
...
...
@@ -510,6 +513,7 @@ public:
typedef
GenericValue
*
ValueIterator
;
//!< Value iterator for iterating in array.
typedef
const
GenericValue
*
ConstValueIterator
;
//!< Constant value iterator for iterating in array.
typedef
GenericValue
<
Encoding
,
Allocator
>
ValueType
;
//!< Value type of itself.
typedef
GenericArray
<
ValueType
>
ArrayType
;
//!@name Constructors and destructor.
//@{
...
...
@@ -1556,6 +1560,9 @@ public:
return
pos
;
}
ArrayType
GetArray
()
{
RAPIDJSON_ASSERT
(
IsArray
());
return
ArrayType
(
*
this
);
}
const
ArrayType
GetArray
()
const
{
RAPIDJSON_ASSERT
(
IsArray
());
return
ArrayType
(
*
this
);
}
//@}
//!@name Number
...
...
@@ -1653,9 +1660,12 @@ public:
//@}
//!@name Array
//@{
//! Templated version for checking whether this value is type T.
/*!
\tparam T Either \c bool, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c float, \c std::basic_string<Ch>
\tparam T Either \c bool, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c float, \c
const \c char*, \c
std::basic_string<Ch>
*/
template
<
typename
T
>
bool
Is
()
const
{
return
internal
::
TypeHelper
<
ValueType
,
T
>::
Is
(
*
this
);
}
...
...
@@ -1669,6 +1679,8 @@ public:
template
<
typename
T
>
ValueType
&
Set
(
const
T
&
data
,
AllocatorType
&
allocator
)
{
return
internal
::
TypeHelper
<
ValueType
,
T
>::
Set
(
*
this
,
data
,
allocator
);
}
//@}
//! Generate events of this value to a Handler.
/*! This function adopts the GoF visitor pattern.
Typical usage is to output this JSON value as JSON text via Writer, which is a Handler.
...
...
@@ -2278,6 +2290,65 @@ GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,Sourc
}
}
//! Helper class for accessing Value of array type.
/*!
Instance of this helper class is obtained by \c GenericValue::GetArray().
In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1.
*/
template
<
typename
ValueType
>
class
GenericArray
{
public
:
typedef
typename
ValueType
::
ValueIterator
ValueIterator
;
typedef
typename
ValueType
::
ConstValueIterator
ConstValueIterator
;
typedef
typename
ValueType
::
AllocatorType
AllocatorType
;
typedef
typename
ValueType
::
StringRefType
StringRefType
;
template
<
typename
,
typename
>
friend
class
GenericValue
;
GenericArray
()
:
ptr_
()
{}
GenericArray
(
const
GenericArray
&
rhs
)
:
ptr_
(
rhs
.
ptr_
)
{}
GenericArray
&
operator
=
(
GenericArray
&
rhs
)
{
ptr_
=
rhs
.
ptr_
;
return
*
this
;
}
~
GenericArray
()
{}
SizeType
Size
()
const
{
return
ptr_
->
Size
();
}
SizeType
Capacity
()
const
{
return
ptr_
->
Capacity
();
}
bool
Empty
()
const
{
return
ptr_
->
Empty
();
}
void
Clear
()
{
ptr_
->
Clear
();
}
ValueType
&
operator
[](
SizeType
index
)
{
return
(
*
ptr_
)[
index
];
}
const
ValueType
&
operator
[](
SizeType
index
)
const
{
return
(
*
ptr_
)[
index
];
}
ValueIterator
Begin
()
{
return
ptr_
->
Begin
();
}
ValueIterator
End
()
{
return
ptr_
->
End
();
}
ConstValueIterator
Begin
()
const
{
return
ptr_
->
Begin
();
}
ConstValueIterator
End
()
const
{
return
ptr_
->
End
();
}
GenericArray
&
Reserve
(
SizeType
newCapacity
,
AllocatorType
&
allocator
)
{
ptr_
->
Reserve
(
newCapacity
,
allocator
);
return
*
this
;
}
GenericArray
&
PushBack
(
ValueType
&
value
,
AllocatorType
&
allocator
)
{
ptr_
->
PushBack
(
value
,
allocator
);
return
*
this
;
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericArray
&
PushBack
(
ValueType
&&
value
,
AllocatorType
&
allocator
)
{
ptr_
->
PushBack
(
value
,
allocator
);
return
*
this
;
}
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericArray
&
PushBack
(
StringRefType
value
,
AllocatorType
&
allocator
)
{
ptr_
->
PushBack
(
value
,
allocator
);
return
*
this
;
}
template
<
typename
T
>
RAPIDJSON_DISABLEIF_RETURN
((
internal
::
OrExpr
<
internal
::
IsPointer
<
T
>
,
internal
::
IsGenericValue
<
T
>
>
),
(
GenericArray
&
))
PushBack
(
T
value
,
AllocatorType
&
allocator
)
{
ptr_
->
PushBack
(
value
,
allocator
);
return
*
this
;
}
GenericArray
&
PopBack
()
{
ptr_
->
PopBack
();
return
*
this
;
}
ValueIterator
Erase
(
ConstValueIterator
pos
)
{
return
ptr_
->
Erase
(
pos
);
}
ValueIterator
Erase
(
ConstValueIterator
first
,
ConstValueIterator
last
)
{
return
ptr_
->
Erase
(
first
,
last
);
}
#if RAPIDJSON_HAS_CXX11_RANGE_FOR
ValueIterator
begin
()
{
return
ptr_
->
Begin
();
}
ValueIterator
end
()
{
return
ptr_
->
End
();
}
ConstValueIterator
begin
()
const
{
return
ptr_
->
Begin
();
}
ConstValueIterator
end
()
const
{
return
ptr_
->
End
();
}
#endif
private
:
GenericArray
(
ValueType
&
value
)
:
ptr_
(
&
value
)
{}
GenericArray
(
const
ValueType
&
value
)
:
ptr_
(
const_cast
<
ValueType
*>
(
&
value
))
{}
ValueType
*
ptr_
;
};
typedef
GenericArray
<
Value
>
Array
;
RAPIDJSON_NAMESPACE_END
#ifdef _MSC_VER
...
...
include/rapidjson/rapidjson.h
View file @
59309b5d
...
...
@@ -530,6 +530,17 @@ RAPIDJSON_NAMESPACE_END
#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0
#endif
#ifndef RAPIDJSON_HAS_CXX11_RANGE_FOR
#if defined(__clang)
#define RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for)
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
(
defined
(
_MSC_VER
)
&&
_MSC_VER
>=
1600
)
#define RAPIDJSON_HAS_CXX11_RANGE_FOR 1
#else
#define RAPIDJSON_HAS_CXX11_RANGE_FOR 0
#endif
#endif // RAPIDJSON_HAS_CXX11_RANGE_FOR
//!@endcond
///////////////////////////////////////////////////////////////////////////////
...
...
test/unittest/valuetest.cpp
View file @
59309b5d
...
...
@@ -824,25 +824,9 @@ TEST(Value, SetStringNullException) {
EXPECT_THROW
(
v
.
SetString
(
0
,
0
),
AssertException
);
}
TEST
(
Value
,
Array
)
{
Value
x
(
kArrayType
);
const
Value
&
y
=
x
;
Value
::
AllocatorType
allocator
;
EXPECT_EQ
(
kArrayType
,
x
.
GetType
());
EXPECT_TRUE
(
x
.
IsArray
());
EXPECT_TRUE
(
x
.
Empty
());
EXPECT_EQ
(
0u
,
x
.
Size
());
EXPECT_TRUE
(
y
.
IsArray
());
EXPECT_TRUE
(
y
.
Empty
());
EXPECT_EQ
(
0u
,
y
.
Size
());
EXPECT_FALSE
(
x
.
IsNull
());
EXPECT_FALSE
(
x
.
IsBool
());
EXPECT_FALSE
(
x
.
IsFalse
());
EXPECT_FALSE
(
x
.
IsTrue
());
EXPECT_FALSE
(
x
.
IsString
());
EXPECT_FALSE
(
x
.
IsObject
());
template
<
typename
T
,
typename
Allocator
>
void
TestArray
(
T
&
x
,
Allocator
&
allocator
)
{
const
T
&
y
=
x
;
// PushBack()
Value
v
;
...
...
@@ -889,7 +873,7 @@ TEST(Value, Array) {
#endif
// iterator
Value
::
ValueIterator
itr
=
x
.
Begin
();
typename
T
::
ValueIterator
itr
=
x
.
Begin
();
EXPECT_TRUE
(
itr
!=
x
.
End
());
EXPECT_TRUE
(
itr
->
IsNull
());
++
itr
;
...
...
@@ -908,7 +892,7 @@ TEST(Value, Array) {
EXPECT_STREQ
(
"foo"
,
itr
->
GetString
());
// const iterator
Value
::
ConstValueIterator
citr
=
y
.
Begin
();
typename
T
::
ConstValueIterator
citr
=
y
.
Begin
();
EXPECT_TRUE
(
citr
!=
y
.
End
());
EXPECT_TRUE
(
citr
->
IsNull
());
++
citr
;
...
...
@@ -994,6 +978,29 @@ TEST(Value, Array) {
EXPECT_EQ
(
i
+
removeCount
,
x
[
static_cast
<
SizeType
>
(
i
)][
0
].
GetUint
());
}
}
}
TEST
(
Value
,
Array
)
{
Value
x
(
kArrayType
);
const
Value
&
y
=
x
;
Value
::
AllocatorType
allocator
;
EXPECT_EQ
(
kArrayType
,
x
.
GetType
());
EXPECT_TRUE
(
x
.
IsArray
());
EXPECT_TRUE
(
x
.
Empty
());
EXPECT_EQ
(
0u
,
x
.
Size
());
EXPECT_TRUE
(
y
.
IsArray
());
EXPECT_TRUE
(
y
.
Empty
());
EXPECT_EQ
(
0u
,
y
.
Size
());
EXPECT_FALSE
(
x
.
IsNull
());
EXPECT_FALSE
(
x
.
IsBool
());
EXPECT_FALSE
(
x
.
IsFalse
());
EXPECT_FALSE
(
x
.
IsTrue
());
EXPECT_FALSE
(
x
.
IsString
());
EXPECT_FALSE
(
x
.
IsObject
());
TestArray
(
x
,
allocator
);
// Working in gcc without C++11, but VS2013 cannot compile. To be diagnosed.
// http://en.wikipedia.org/wiki/Erase-remove_idiom
...
...
@@ -1017,6 +1024,52 @@ TEST(Value, Array) {
EXPECT_TRUE
(
z
.
Empty
());
}
TEST
(
Value
,
ArrayHelper
)
{
Value
::
AllocatorType
allocator
;
{
Value
x
(
kArrayType
);
Array
a
=
x
.
GetArray
();
TestArray
(
a
,
allocator
);
}
Value
x
(
kArrayType
);
Array
a
=
x
.
GetArray
();
a
.
PushBack
(
1
,
allocator
);
Array
a2
(
a
);
// copy constructor
EXPECT_EQ
(
1
,
a2
.
Size
());
Array
a3
;
// default constructor
a3
=
a
;
// assignment operator
EXPECT_EQ
(
1
,
a3
.
Size
());
}
#if RAPIDJSON_HAS_CXX11_RANGE_FOR
TEST
(
Value
,
ArrayHelperRangeFor
)
{
Value
::
AllocatorType
allocator
;
Value
x
(
kArrayType
);
for
(
int
i
=
0
;
i
<
10
;
i
++
)
x
.
PushBack
(
i
,
allocator
);
{
int
i
=
0
;
for
(
auto
&
v
:
x
.
GetArray
())
EXPECT_EQ
(
i
++
,
v
.
GetInt
());
EXPECT_EQ
(
i
,
10
);
}
{
int
i
=
0
;
for
(
auto
&
v
:
const_cast
<
const
Value
&>
(
x
).
GetArray
())
EXPECT_EQ
(
i
++
,
v
.
GetInt
());
EXPECT_EQ
(
i
,
10
);
}
// Array a = x.GetArray();
// Array ca = const_cast<const Value&>(x).GetArray();
}
#endif
TEST
(
Value
,
Object
)
{
Value
x
(
kObjectType
);
const
Value
&
y
=
x
;
// const version
...
...
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