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
4029ddb1
Commit
4029ddb1
authored
Feb 19, 2016
by
Milo Yip
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #542 from miloyip/issue316_templatedaccessors
Templated accessors and range-based for
parents
cdc2330c
9f6736c2
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
620 additions
and
41 deletions
+620
-41
document.h
include/rapidjson/document.h
+321
-5
rapidjson.h
include/rapidjson/rapidjson.h
+11
-0
valuetest.cpp
test/unittest/valuetest.cpp
+288
-36
No files found.
include/rapidjson/document.h
View file @
4029ddb1
...
...
@@ -393,6 +393,127 @@ template <typename T> struct IsGenericValue : IsGenericValueImpl<T>::Type {};
}
// namespace internal
///////////////////////////////////////////////////////////////////////////////
// TypeHelper
namespace
internal
{
template
<
typename
ValueType
,
typename
T
>
struct
TypeHelper
{};
template
<
typename
ValueType
>
struct
TypeHelper
<
ValueType
,
bool
>
{
static
bool
Is
(
const
ValueType
&
v
)
{
return
v
.
IsBool
();
}
static
bool
Get
(
const
ValueType
&
v
)
{
return
v
.
GetBool
();
}
static
ValueType
&
Set
(
ValueType
&
v
,
bool
data
)
{
return
v
.
SetBool
(
data
);
}
static
ValueType
&
Set
(
ValueType
&
v
,
bool
data
,
typename
ValueType
::
AllocatorType
&
)
{
return
v
.
SetBool
(
data
);
}
};
template
<
typename
ValueType
>
struct
TypeHelper
<
ValueType
,
int
>
{
static
bool
Is
(
const
ValueType
&
v
)
{
return
v
.
IsInt
();
}
static
int
Get
(
const
ValueType
&
v
)
{
return
v
.
GetInt
();
}
static
ValueType
&
Set
(
ValueType
&
v
,
int
data
)
{
return
v
.
SetInt
(
data
);
}
static
ValueType
&
Set
(
ValueType
&
v
,
int
data
,
typename
ValueType
::
AllocatorType
&
)
{
return
v
.
SetInt
(
data
);
}
};
template
<
typename
ValueType
>
struct
TypeHelper
<
ValueType
,
unsigned
>
{
static
bool
Is
(
const
ValueType
&
v
)
{
return
v
.
IsUint
();
}
static
unsigned
Get
(
const
ValueType
&
v
)
{
return
v
.
GetUint
();
}
static
ValueType
&
Set
(
ValueType
&
v
,
unsigned
data
)
{
return
v
.
SetUint
(
data
);
}
static
ValueType
&
Set
(
ValueType
&
v
,
unsigned
data
,
typename
ValueType
::
AllocatorType
&
)
{
return
v
.
SetUint
(
data
);
}
};
template
<
typename
ValueType
>
struct
TypeHelper
<
ValueType
,
int64_t
>
{
static
bool
Is
(
const
ValueType
&
v
)
{
return
v
.
IsInt64
();
}
static
int64_t
Get
(
const
ValueType
&
v
)
{
return
v
.
GetInt64
();
}
static
ValueType
&
Set
(
ValueType
&
v
,
int64_t
data
)
{
return
v
.
SetInt64
(
data
);
}
static
ValueType
&
Set
(
ValueType
&
v
,
int64_t
data
,
typename
ValueType
::
AllocatorType
&
)
{
return
v
.
SetInt64
(
data
);
}
};
template
<
typename
ValueType
>
struct
TypeHelper
<
ValueType
,
uint64_t
>
{
static
bool
Is
(
const
ValueType
&
v
)
{
return
v
.
IsUint64
();
}
static
uint64_t
Get
(
const
ValueType
&
v
)
{
return
v
.
GetUint64
();
}
static
ValueType
&
Set
(
ValueType
&
v
,
uint64_t
data
)
{
return
v
.
SetUint64
(
data
);
}
static
ValueType
&
Set
(
ValueType
&
v
,
uint64_t
data
,
typename
ValueType
::
AllocatorType
&
)
{
return
v
.
SetUint64
(
data
);
}
};
template
<
typename
ValueType
>
struct
TypeHelper
<
ValueType
,
double
>
{
static
bool
Is
(
const
ValueType
&
v
)
{
return
v
.
IsDouble
();
}
static
double
Get
(
const
ValueType
&
v
)
{
return
v
.
GetDouble
();
}
static
ValueType
&
Set
(
ValueType
&
v
,
double
data
)
{
return
v
.
SetDouble
(
data
);
}
static
ValueType
&
Set
(
ValueType
&
v
,
double
data
,
typename
ValueType
::
AllocatorType
&
)
{
return
v
.
SetDouble
(
data
);
}
};
template
<
typename
ValueType
>
struct
TypeHelper
<
ValueType
,
float
>
{
static
bool
Is
(
const
ValueType
&
v
)
{
return
v
.
IsFloat
();
}
static
float
Get
(
const
ValueType
&
v
)
{
return
v
.
GetFloat
();
}
static
ValueType
&
Set
(
ValueType
&
v
,
float
data
)
{
return
v
.
SetFloat
(
data
);
}
static
ValueType
&
Set
(
ValueType
&
v
,
float
data
,
typename
ValueType
::
AllocatorType
&
)
{
return
v
.
SetFloat
(
data
);
}
};
template
<
typename
ValueType
>
struct
TypeHelper
<
ValueType
,
const
typename
ValueType
::
Ch
*>
{
typedef
const
typename
ValueType
::
Ch
*
StringType
;
static
bool
Is
(
const
ValueType
&
v
)
{
return
v
.
IsString
();
}
static
StringType
Get
(
const
ValueType
&
v
)
{
return
v
.
GetString
();
}
static
ValueType
&
Set
(
ValueType
&
v
,
const
StringType
data
)
{
return
v
.
SetString
(
typename
ValueType
::
StringRefType
(
data
));
}
static
ValueType
&
Set
(
ValueType
&
v
,
const
StringType
data
,
typename
ValueType
::
AllocatorType
&
a
)
{
return
v
.
SetString
(
data
,
a
);
}
};
#if RAPIDJSON_HAS_STDSTRING
template
<
typename
ValueType
>
struct
TypeHelper
<
ValueType
,
std
::
basic_string
<
typename
ValueType
::
Ch
>
>
{
typedef
std
::
basic_string
<
typename
ValueType
::
Ch
>
StringType
;
static
bool
Is
(
const
ValueType
&
v
)
{
return
v
.
IsString
();
}
static
StringType
Get
(
const
ValueType
&
v
)
{
return
v
.
GetString
();
}
static
ValueType
&
Set
(
ValueType
&
v
,
const
StringType
&
data
,
typename
ValueType
::
AllocatorType
&
a
)
{
return
v
.
SetString
(
data
,
a
);
}
};
#endif
template
<
typename
ValueType
>
struct
TypeHelper
<
ValueType
,
typename
ValueType
::
Array
>
{
typedef
typename
ValueType
::
Array
ArrayType
;
static
bool
Is
(
const
ValueType
&
v
)
{
return
v
.
IsArray
();
}
static
ArrayType
Get
(
ValueType
&
v
)
{
return
v
.
GetArray
();
}
static
ValueType
&
Set
(
ValueType
&
v
,
ArrayType
data
)
{
return
v
=
data
;
}
static
ValueType
&
Set
(
ValueType
&
v
,
ArrayType
data
,
typename
ValueType
::
AllocatorType
&
)
{
return
v
=
data
;
}
};
template
<
typename
ValueType
>
struct
TypeHelper
<
ValueType
,
typename
ValueType
::
ConstArray
>
{
typedef
typename
ValueType
::
ConstArray
ArrayType
;
static
bool
Is
(
const
ValueType
&
v
)
{
return
v
.
IsArray
();
}
static
ArrayType
Get
(
const
ValueType
&
v
)
{
return
v
.
GetArray
();
}
};
template
<
typename
ValueType
>
struct
TypeHelper
<
ValueType
,
typename
ValueType
::
Object
>
{
typedef
typename
ValueType
::
Object
ObjectType
;
static
bool
Is
(
const
ValueType
&
v
)
{
return
v
.
IsObject
();
}
static
ObjectType
Get
(
ValueType
&
v
)
{
return
v
.
GetObject
();
}
static
ValueType
&
Set
(
ValueType
&
v
,
ObjectType
data
)
{
return
v
=
data
;
}
static
ValueType
&
Set
(
ValueType
&
v
,
ObjectType
data
,
typename
ValueType
::
AllocatorType
&
)
{
v
=
data
;
}
};
template
<
typename
ValueType
>
struct
TypeHelper
<
ValueType
,
typename
ValueType
::
ConstObject
>
{
typedef
typename
ValueType
::
ConstObject
ObjectType
;
static
bool
Is
(
const
ValueType
&
v
)
{
return
v
.
IsObject
();
}
static
ObjectType
Get
(
const
ValueType
&
v
)
{
return
v
.
GetObject
();
}
};
}
// namespace internal
// Forward declarations
template
<
bool
,
typename
>
class
GenericArray
;
template
<
bool
,
typename
>
class
GenericObject
;
///////////////////////////////////////////////////////////////////////////////
// GenericValue
...
...
@@ -420,6 +541,10 @@ 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
<
false
,
ValueType
>
Array
;
typedef
GenericArray
<
true
,
ValueType
>
ConstArray
;
typedef
GenericObject
<
false
,
ValueType
>
Object
;
typedef
GenericObject
<
true
,
ValueType
>
ConstObject
;
//!@name Constructors and destructor.
//@{
...
...
@@ -556,6 +681,28 @@ public:
GenericValue
(
const
std
::
basic_string
<
Ch
>&
s
,
Allocator
&
allocator
)
:
data_
(),
flags_
()
{
SetStringRaw
(
StringRef
(
s
),
allocator
);
}
#endif
//! Constructor for Array.
/*!
\param a An array obtained by \c GetArray().
\note \c Array is always pass-by-value.
\note the source array is moved into this value and the sourec array becomes empty.
*/
GenericValue
(
Array
a
)
RAPIDJSON_NOEXCEPT
:
data_
(
a
.
value_
.
data_
),
flags_
(
a
.
value_
.
flags_
)
{
a
.
value_
.
data_
=
Data
();
a
.
value_
.
flags_
=
kArrayFlag
;
}
//! Constructor for Object.
/*!
\param o An object obtained by \c GetObject().
\note \c Object is always pass-by-value.
\note the source object is moved into this value and the sourec object becomes empty.
*/
GenericValue
(
Object
o
)
RAPIDJSON_NOEXCEPT
:
data_
(
o
.
value_
.
data_
),
flags_
(
o
.
value_
.
flags_
)
{
o
.
value_
.
data_
=
Data
();
o
.
value_
.
flags_
=
kObjectFlag
;
}
//! Destructor.
/*! Need to destruct elements of array, members of object, or copy-string.
*/
...
...
@@ -1020,7 +1167,7 @@ public:
RAPIDJSON_ASSERT
(
IsObject
());
RAPIDJSON_ASSERT
(
name
.
IsString
());
Object
&
o
=
data_
.
o
;
Object
Data
&
o
=
data_
.
o
;
if
(
o
.
size
>=
o
.
capacity
)
{
if
(
o
.
capacity
==
0
)
{
o
.
capacity
=
kDefaultObjectCapacity
;
...
...
@@ -1291,6 +1438,9 @@ public:
return
false
;
}
Object
GetObject
()
{
RAPIDJSON_ASSERT
(
IsObject
());
return
Object
(
*
this
);
}
ConstObject
GetObject
()
const
{
RAPIDJSON_ASSERT
(
IsObject
());
return
ConstObject
(
*
this
);
}
//@}
//!@name Array
...
...
@@ -1466,6 +1616,9 @@ public:
return
pos
;
}
Array
GetArray
()
{
RAPIDJSON_ASSERT
(
IsArray
());
return
Array
(
*
this
);
}
ConstArray
GetArray
()
const
{
RAPIDJSON_ASSERT
(
IsArray
());
return
ConstArray
(
*
this
);
}
//@}
//!@name Number
...
...
@@ -1563,6 +1716,30 @@ 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 const \c char*, \c std::basic_string<Ch>
*/
template
<
typename
T
>
bool
Is
()
const
{
return
internal
::
TypeHelper
<
ValueType
,
T
>::
Is
(
*
this
);
}
template
<
typename
T
>
T
Get
()
const
{
return
internal
::
TypeHelper
<
ValueType
,
T
>::
Get
(
*
this
);
}
template
<
typename
T
>
T
Get
()
{
return
internal
::
TypeHelper
<
ValueType
,
T
>::
Get
(
*
this
);
}
template
<
typename
T
>
ValueType
&
Set
(
const
T
&
data
)
{
return
internal
::
TypeHelper
<
ValueType
,
T
>::
Set
(
*
this
,
data
);
}
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.
...
...
@@ -1697,13 +1874,13 @@ private:
double
d
;
};
// 8 bytes
struct
Object
{
struct
Object
Data
{
Member
*
members
;
SizeType
size
;
SizeType
capacity
;
};
// 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
struct
Array
{
struct
Array
Data
{
GenericValue
*
elements
;
SizeType
size
;
SizeType
capacity
;
...
...
@@ -1713,8 +1890,8 @@ private:
String
s
;
ShortString
ss
;
Number
n
;
Object
o
;
Array
a
;
Object
Data
o
;
Array
Data
a
;
};
// 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
// Initialize this value as array with initial data, without calling destructor.
...
...
@@ -2172,6 +2349,145 @@ 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
<
bool
Const
,
typename
ValueT
>
class
GenericArray
{
public
:
typedef
GenericArray
<
true
,
ValueT
>
ConstArray
;
typedef
GenericArray
<
false
,
ValueT
>
Array
;
typedef
ValueT
PlainType
;
typedef
typename
internal
::
MaybeAddConst
<
Const
,
PlainType
>::
Type
ValueType
;
typedef
ValueType
*
ValueIterator
;
// This may be const or non-const iterator
typedef
const
ValueT
*
ConstValueIterator
;
typedef
typename
ValueType
::
AllocatorType
AllocatorType
;
typedef
typename
ValueType
::
StringRefType
StringRefType
;
template
<
typename
,
typename
>
friend
class
GenericValue
;
GenericArray
(
const
GenericArray
&
rhs
)
:
value_
(
rhs
.
value_
)
{}
GenericArray
&
operator
=
(
const
GenericArray
&
rhs
)
{
value_
=
rhs
.
value_
;
return
*
this
;
}
~
GenericArray
()
{}
SizeType
Size
()
const
{
return
value_
.
Size
();
}
SizeType
Capacity
()
const
{
return
value_
.
Capacity
();
}
bool
Empty
()
const
{
return
value_
.
Empty
();
}
void
Clear
()
const
{
value_
.
Clear
();
}
ValueType
&
operator
[](
SizeType
index
)
const
{
return
value_
[
index
];
}
ValueIterator
Begin
()
const
{
return
value_
.
Begin
();
}
ValueIterator
End
()
const
{
return
value_
.
End
();
}
GenericArray
Reserve
(
SizeType
newCapacity
,
AllocatorType
&
allocator
)
const
{
value_
.
Reserve
(
newCapacity
,
allocator
);
return
*
this
;
}
GenericArray
PushBack
(
ValueType
&
value
,
AllocatorType
&
allocator
)
const
{
value_
.
PushBack
(
value
,
allocator
);
return
*
this
;
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericArray
PushBack
(
ValueType
&&
value
,
AllocatorType
&
allocator
)
const
{
value_
.
PushBack
(
value
,
allocator
);
return
*
this
;
}
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericArray
PushBack
(
StringRefType
value
,
AllocatorType
&
allocator
)
const
{
value_
.
PushBack
(
value
,
allocator
);
return
*
this
;
}
template
<
typename
T
>
RAPIDJSON_DISABLEIF_RETURN
((
internal
::
OrExpr
<
internal
::
IsPointer
<
T
>
,
internal
::
IsGenericValue
<
T
>
>
),
(
const
GenericArray
&
))
PushBack
(
T
value
,
AllocatorType
&
allocator
)
const
{
value_
.
PushBack
(
value
,
allocator
);
return
*
this
;
}
GenericArray
PopBack
()
const
{
value_
.
PopBack
();
return
*
this
;
}
ValueIterator
Erase
(
ConstValueIterator
pos
)
const
{
return
value_
.
Erase
(
pos
);
}
ValueIterator
Erase
(
ConstValueIterator
first
,
ConstValueIterator
last
)
const
{
return
value_
.
Erase
(
first
,
last
);
}
#if RAPIDJSON_HAS_CXX11_RANGE_FOR
ValueIterator
begin
()
const
{
return
value_
.
Begin
();
}
ValueIterator
end
()
const
{
return
value_
.
End
();
}
#endif
private
:
GenericArray
();
GenericArray
(
ValueType
&
value
)
:
value_
(
value
)
{}
ValueType
&
value_
;
};
//! 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
<
bool
Const
,
typename
ValueT
>
class
GenericObject
{
public
:
typedef
GenericObject
<
true
,
ValueT
>
ConstObject
;
typedef
GenericObject
<
false
,
ValueT
>
Object
;
typedef
ValueT
PlainType
;
typedef
typename
internal
::
MaybeAddConst
<
Const
,
PlainType
>::
Type
ValueType
;
typedef
GenericMemberIterator
<
Const
,
typename
ValueT
::
EncodingType
,
typename
ValueT
::
AllocatorType
>
MemberIterator
;
// This may be const or non-const iterator
typedef
GenericMemberIterator
<
true
,
typename
ValueT
::
EncodingType
,
typename
ValueT
::
AllocatorType
>
ConstMemberIterator
;
typedef
typename
ValueType
::
AllocatorType
AllocatorType
;
typedef
typename
ValueType
::
StringRefType
StringRefType
;
typedef
typename
ValueType
::
EncodingType
EncodingType
;
typedef
typename
ValueType
::
Ch
Ch
;
template
<
typename
,
typename
>
friend
class
GenericValue
;
GenericObject
(
const
GenericObject
&
rhs
)
:
value_
(
rhs
.
value_
)
{}
GenericObject
&
operator
=
(
const
GenericObject
&
rhs
)
{
value_
=
rhs
.
value_
;
return
*
this
;
}
~
GenericObject
()
{}
SizeType
MemberCount
()
const
{
return
value_
.
MemberCount
();
}
bool
ObjectEmpty
()
const
{
return
value_
.
ObjectEmpty
();
}
template
<
typename
T
>
ValueType
&
operator
[](
T
*
name
)
const
{
return
value_
[
name
];
}
template
<
typename
SourceAllocator
>
ValueType
&
operator
[](
const
GenericValue
<
EncodingType
,
SourceAllocator
>&
name
)
const
{
return
value_
[
name
];
}
#if RAPIDJSON_HAS_STDSTRING
ValueType
&
operator
[](
const
std
::
basic_string
<
Ch
>&
name
)
const
{
return
value_
[
name
];
}
#endif
MemberIterator
MemberBegin
()
const
{
return
value_
.
MemberBegin
();
}
MemberIterator
MemberEnd
()
const
{
return
value_
.
MemberEnd
();
}
bool
HasMember
(
const
Ch
*
name
)
const
{
return
value_
.
HasMember
(
name
);
}
#if RAPIDJSON_HAS_STDSTRING
bool
HasMember
(
const
std
::
basic_string
<
Ch
>&
name
)
const
{
return
value_
.
HasMember
(
name
);
}
#endif
template
<
typename
SourceAllocator
>
bool
HasMember
(
const
GenericValue
<
EncodingType
,
SourceAllocator
>&
name
)
const
{
return
value_
.
HasMember
(
name
);
}
MemberIterator
FindMember
(
const
Ch
*
name
)
const
{
value_
.
FindMember
(
name
);
}
template
<
typename
SourceAllocator
>
MemberIterator
FindMember
(
const
GenericValue
<
EncodingType
,
SourceAllocator
>&
name
)
const
{
value_
.
FindMember
(
name
);
}
#if RAPIDJSON_HAS_STDSTRING
MemberIterator
FindMember
(
const
std
::
basic_string
<
Ch
>&
name
)
const
{
return
value_
.
FindMember
(
name
);
}
#endif
GenericObject
AddMember
(
ValueType
&
name
,
ValueType
&
value
,
AllocatorType
&
allocator
)
const
{
value_
.
AddMember
(
name
,
value
,
allocator
);
return
*
this
;
}
GenericObject
AddMember
(
ValueType
&
name
,
StringRefType
value
,
AllocatorType
&
allocator
)
const
{
value_
.
AddMember
(
name
,
value
,
allocator
);
return
*
this
;
}
#if RAPIDJSON_HAS_STDSTRING
GenericObject
AddMember
(
ValueType
&
name
,
std
::
basic_string
<
Ch
>&
value
,
AllocatorType
&
allocator
)
const
{
value_
.
AddMember
(
name
,
value
,
allocator
);
return
*
this
;
}
#endif
template
<
typename
T
>
RAPIDJSON_DISABLEIF_RETURN
((
internal
::
OrExpr
<
internal
::
IsPointer
<
T
>
,
internal
::
IsGenericValue
<
T
>
>
),
(
ValueType
&
))
AddMember
(
ValueType
&
name
,
T
value
,
AllocatorType
&
allocator
)
const
{
value_
.
AddMember
(
name
,
value
,
allocator
);
return
*
this
;
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericObject
AddMember
(
ValueType
&&
name
,
ValueType
&&
value
,
AllocatorType
&
allocator
)
const
{
value_
.
AddMember
(
name
,
value
,
allocator
);
return
*
this
;
}
GenericObject
AddMember
(
ValueType
&&
name
,
ValueType
&
value
,
AllocatorType
&
allocator
)
const
{
value_
.
AddMember
(
name
,
value
,
allocator
);
return
*
this
;
}
GenericObject
AddMember
(
ValueType
&
name
,
ValueType
&&
value
,
AllocatorType
&
allocator
)
const
{
value_
.
AddMember
(
name
,
value
,
allocator
);
return
*
this
;
}
GenericObject
AddMember
(
StringRefType
name
,
ValueType
&&
value
,
AllocatorType
&
allocator
)
const
{
value_
.
AddMember
(
name
,
value
,
allocator
);
return
*
this
;
}
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericObject
AddMember
(
StringRefType
name
,
ValueType
&
value
,
AllocatorType
&
allocator
)
const
{
value_
.
AddMember
(
name
,
value
,
allocator
);
return
*
this
;
}
GenericObject
AddMember
(
StringRefType
name
,
StringRefType
value
,
AllocatorType
&
allocator
)
const
{
value_
.
AddMember
(
name
,
value
,
allocator
);
return
*
this
;
}
template
<
typename
T
>
RAPIDJSON_DISABLEIF_RETURN
((
internal
::
OrExpr
<
internal
::
IsPointer
<
T
>
,
internal
::
IsGenericValue
<
T
>
>
),
(
GenericObject
))
AddMember
(
StringRefType
name
,
T
value
,
AllocatorType
&
allocator
)
const
{
value_
.
AddMember
(
name
,
value
,
allocator
);
return
*
this
;
}
void
RemoveAllMembers
()
{
return
value_
.
RemoveAllMembers
();
}
bool
RemoveMember
(
const
Ch
*
name
)
const
{
return
value_
.
RemoveMember
(
name
);
}
#if RAPIDJSON_HAS_STDSTRING
bool
RemoveMember
(
const
std
::
basic_string
<
Ch
>&
name
)
const
{
return
value_
.
RemoveMember
(
name
);
}
#endif
template
<
typename
SourceAllocator
>
bool
RemoveMember
(
const
GenericValue
<
EncodingType
,
SourceAllocator
>&
name
)
const
{
return
value_
.
RemoveMember
(
name
);
}
MemberIterator
RemoveMember
(
MemberIterator
m
)
const
{
return
value_
.
RemoveMember
(
m
);
}
MemberIterator
EraseMember
(
ConstMemberIterator
pos
)
const
{
return
value_
.
EraseMember
(
pos
);
}
MemberIterator
EraseMember
(
ConstMemberIterator
first
,
ConstMemberIterator
last
)
const
{
return
value_
.
EraseMember
(
first
,
last
);
}
bool
EraseMember
(
const
Ch
*
name
)
const
{
return
value_
.
EraseMember
(
name
);
}
#if RAPIDJSON_HAS_STDSTRING
bool
EraseMember
(
const
std
::
basic_string
<
Ch
>&
name
)
const
{
return
EraseMember
(
ValueType
(
StringRef
(
name
)));
}
#endif
template
<
typename
SourceAllocator
>
bool
EraseMember
(
const
GenericValue
<
EncodingType
,
SourceAllocator
>&
name
)
const
{
return
value_
.
EraseMember
(
name
);
}
#if RAPIDJSON_HAS_CXX11_RANGE_FOR
MemberIterator
begin
()
const
{
return
value_
.
MemberBegin
();
}
MemberIterator
end
()
const
{
return
value_
.
MemberEnd
();
}
#endif
private
:
GenericObject
();
GenericObject
(
ValueType
&
value
)
:
value_
(
value
)
{}
ValueType
&
value_
;
};
RAPIDJSON_NAMESPACE_END
#ifdef _MSC_VER
...
...
include/rapidjson/rapidjson.h
View file @
4029ddb1
...
...
@@ -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 @
4029ddb1
...
...
@@ -335,6 +335,12 @@ TEST(Value, True) {
Value
z
;
z
.
SetBool
(
true
);
EXPECT_TRUE
(
z
.
IsTrue
());
// Templated functions
EXPECT_TRUE
(
z
.
Is
<
bool
>
());
EXPECT_TRUE
(
z
.
Get
<
bool
>
());
EXPECT_FALSE
(
z
.
Set
<
bool
>
(
false
).
Get
<
bool
>
());
EXPECT_TRUE
(
z
.
Set
(
true
).
Get
<
bool
>
());
}
TEST
(
Value
,
False
)
{
...
...
@@ -414,6 +420,12 @@ TEST(Value, Int) {
// operator=(int)
z
=
5678
;
EXPECT_EQ
(
5678
,
z
.
GetInt
());
// Templated functions
EXPECT_TRUE
(
z
.
Is
<
int
>
());
EXPECT_EQ
(
5678
,
z
.
Get
<
int
>
());
EXPECT_EQ
(
5679
,
z
.
Set
(
5679
).
Get
<
int
>
());
EXPECT_EQ
(
5680
,
z
.
Set
<
int
>
(
5680
).
Get
<
int
>
());
}
TEST
(
Value
,
Uint
)
{
...
...
@@ -453,6 +465,12 @@ TEST(Value, Uint) {
EXPECT_EQ
(
2147483648u
,
z
.
GetUint
());
EXPECT_FALSE
(
z
.
IsInt
());
EXPECT_TRUE
(
z
.
IsInt64
());
// Issue 41: Incorrect parsing of unsigned int number types
// Templated functions
EXPECT_TRUE
(
z
.
Is
<
unsigned
>
());
EXPECT_EQ
(
2147483648u
,
z
.
Get
<
unsigned
>
());
EXPECT_EQ
(
2147483649u
,
z
.
Set
(
2147483649u
).
Get
<
unsigned
>
());
EXPECT_EQ
(
2147483650u
,
z
.
Set
<
unsigned
>
(
2147483650u
).
Get
<
unsigned
>
());
}
TEST
(
Value
,
Int64
)
{
...
...
@@ -505,8 +523,15 @@ TEST(Value, Int64) {
EXPECT_FALSE
(
z
.
IsInt
());
EXPECT_NEAR
(
-
2147483649.0
,
z
.
GetDouble
(),
0.0
);
z
.
SetInt64
(
static_cast
<
int64_t
>
(
RAPIDJSON_UINT64_C2
(
0x80000000
,
00000000
)));
int64_t
i
=
static_cast
<
int64_t
>
(
RAPIDJSON_UINT64_C2
(
0x80000000
,
00000000
));
z
.
SetInt64
(
i
);
EXPECT_DOUBLE_EQ
(
-
9223372036854775808.0
,
z
.
GetDouble
());
// Templated functions
EXPECT_TRUE
(
z
.
Is
<
int64_t
>
());
EXPECT_EQ
(
i
,
z
.
Get
<
int64_t
>
());
EXPECT_EQ
(
i
-
1
,
z
.
Set
(
i
-
1
).
Get
<
int64_t
>
());
EXPECT_EQ
(
i
-
2
,
z
.
Set
<
int64_t
>
(
i
-
2
).
Get
<
int64_t
>
());
}
TEST
(
Value
,
Uint64
)
{
...
...
@@ -547,10 +572,17 @@ TEST(Value, Uint64) {
EXPECT_FALSE
(
z
.
IsUint
());
EXPECT_TRUE
(
z
.
IsInt64
());
z
.
SetUint64
(
RAPIDJSON_UINT64_C2
(
0x80000000
,
0x00000000
));
// 2^63 cannot cast as int64
uint64_t
u
=
RAPIDJSON_UINT64_C2
(
0x80000000
,
0x00000000
);
z
.
SetUint64
(
u
);
// 2^63 cannot cast as int64
EXPECT_FALSE
(
z
.
IsInt64
());
EXPECT_EQ
(
RAPIDJSON_UINT64_C2
(
0x80000000
,
0x00000000
)
,
z
.
GetUint64
());
// Issue 48
EXPECT_EQ
(
u
,
z
.
GetUint64
());
// Issue 48
EXPECT_DOUBLE_EQ
(
9223372036854775808.0
,
z
.
GetDouble
());
// Templated functions
EXPECT_TRUE
(
z
.
Is
<
uint64_t
>
());
EXPECT_EQ
(
u
,
z
.
Get
<
uint64_t
>
());
EXPECT_EQ
(
u
+
1
,
z
.
Set
(
u
+
1
).
Get
<
uint64_t
>
());
EXPECT_EQ
(
u
+
2
,
z
.
Set
<
uint64_t
>
(
u
+
2
).
Get
<
uint64_t
>
());
}
TEST
(
Value
,
Double
)
{
...
...
@@ -577,6 +609,12 @@ TEST(Value, Double) {
z
=
56.78
;
EXPECT_NEAR
(
56.78
,
z
.
GetDouble
(),
0.0
);
// Templated functions
EXPECT_TRUE
(
z
.
Is
<
double
>
());
EXPECT_EQ
(
56.78
,
z
.
Get
<
double
>
());
EXPECT_EQ
(
57.78
,
z
.
Set
(
57.78
).
Get
<
double
>
());
EXPECT_EQ
(
58.78
,
z
.
Set
<
double
>
(
58.78
).
Get
<
double
>
());
}
TEST
(
Value
,
Float
)
{
...
...
@@ -604,6 +642,12 @@ TEST(Value, Float) {
z
=
56.78
f
;
EXPECT_NEAR
(
56.78
f
,
z
.
GetFloat
(),
0.0
f
);
// Templated functions
EXPECT_TRUE
(
z
.
Is
<
float
>
());
EXPECT_EQ
(
56.78
f
,
z
.
Get
<
float
>
());
EXPECT_EQ
(
57.78
f
,
z
.
Set
(
57.78
f
).
Get
<
float
>
());
EXPECT_EQ
(
58.78
f
,
z
.
Set
<
float
>
(
58.78
f
).
Get
<
float
>
());
}
TEST
(
Value
,
IsLosslessDouble
)
{
...
...
@@ -724,6 +768,11 @@ TEST(Value, String) {
EXPECT_STREQ
(
"World"
,
w
.
GetString
());
EXPECT_EQ
(
5u
,
w
.
GetStringLength
());
// templated functions
EXPECT_TRUE
(
z
.
Is
<
const
char
*>
());
EXPECT_STREQ
(
cstr
,
z
.
Get
<
const
char
*>
());
EXPECT_STREQ
(
"Apple"
,
z
.
Set
<
const
char
*>
(
"Apple"
).
Get
<
const
char
*>
());
#if RAPIDJSON_HAS_STDSTRING
{
std
::
string
str
=
"Hello World"
;
...
...
@@ -759,6 +808,14 @@ TEST(Value, String) {
vs1
=
StringRef
(
str
);
TestEqual
(
str
,
vs1
);
TestEqual
(
vs0
,
vs1
);
// Templated function.
EXPECT_TRUE
(
vs0
.
Is
<
std
::
string
>
());
EXPECT_EQ
(
str
,
vs0
.
Get
<
std
::
string
>
());
vs0
.
Set
<
std
::
string
>
(
std
::
string
(
"Apple"
),
allocator
);
EXPECT_EQ
(
std
::
string
(
"Apple"
),
vs0
.
Get
<
std
::
string
>
());
vs0
.
Set
(
std
::
string
(
"Orange"
),
allocator
);
EXPECT_EQ
(
std
::
string
(
"Orange"
),
vs0
.
Get
<
std
::
string
>
());
}
#endif // RAPIDJSON_HAS_STDSTRING
}
...
...
@@ -769,25 +826,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
>
static
void
TestArray
(
T
&
x
,
Allocator
&
allocator
)
{
const
T
&
y
=
x
;
// PushBack()
Value
v
;
...
...
@@ -834,7 +875,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
;
...
...
@@ -853,7 +894,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
;
...
...
@@ -939,6 +980,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
...
...
@@ -962,19 +1026,96 @@ TEST(Value, Array) {
EXPECT_TRUE
(
z
.
Empty
());
}
TEST
(
Value
,
Object
)
{
Value
x
(
kObjectType
);
const
Value
&
y
=
x
;
// const version
TEST
(
Value
,
ArrayHelper
)
{
Value
::
AllocatorType
allocator
;
{
Value
x
(
kArrayType
);
Value
::
Array
a
=
x
.
GetArray
();
TestArray
(
a
,
allocator
);
}
EXPECT_EQ
(
kObjectType
,
x
.
GetType
());
EXPECT_TRUE
(
x
.
IsObject
());
EXPECT_TRUE
(
x
.
ObjectEmpty
());
EXPECT_EQ
(
0u
,
x
.
MemberCount
());
EXPECT_EQ
(
kObjectType
,
y
.
GetType
());
EXPECT_TRUE
(
y
.
IsObject
());
EXPECT_TRUE
(
y
.
ObjectEmpty
());
EXPECT_EQ
(
0u
,
y
.
MemberCount
());
{
Value
x
(
kArrayType
);
Value
::
Array
a
=
x
.
GetArray
();
a
.
PushBack
(
1
,
allocator
);
Value
::
Array
a2
(
a
);
// copy constructor
EXPECT_EQ
(
1
,
a2
.
Size
());
Value
::
Array
a3
=
a
;
EXPECT_EQ
(
1
,
a3
.
Size
());
Value
::
ConstArray
y
=
static_cast
<
const
Value
&>
(
x
).
GetArray
();
(
void
)
y
;
// y.PushBack(1, allocator); // should not compile
// Templated functions
x
.
Clear
();
EXPECT_TRUE
(
x
.
Is
<
Value
::
Array
>
());
EXPECT_TRUE
(
x
.
Is
<
Value
::
ConstArray
>
());
a
.
PushBack
(
1
,
allocator
);
EXPECT_EQ
(
1
,
x
.
Get
<
Value
::
Array
>
()[
0
].
GetInt
());
EXPECT_EQ
(
1
,
x
.
Get
<
Value
::
ConstArray
>
()[
0
].
GetInt
());
Value
x2
;
x2
.
Set
<
Value
::
Array
>
(
a
);
EXPECT_TRUE
(
x
.
IsArray
());
// IsArray() is invariant after moving.
EXPECT_EQ
(
1
,
x2
.
Get
<
Value
::
Array
>
()[
0
].
GetInt
());
}
{
Value
y
(
kArrayType
);
y
.
PushBack
(
123
,
allocator
);
Value
x
(
y
.
GetArray
());
// Construct value form array.
EXPECT_TRUE
(
x
.
IsArray
());
EXPECT_EQ
(
123
,
x
[
0
].
GetInt
());
EXPECT_TRUE
(
y
.
IsArray
());
// Invariant
EXPECT_TRUE
(
y
.
Empty
());
}
{
Value
x
(
kArrayType
);
Value
y
(
kArrayType
);
y
.
PushBack
(
123
,
allocator
);
x
.
PushBack
(
y
.
GetArray
(),
allocator
);
// Implicit constructor to convert Array to GenericValue
EXPECT_EQ
(
1
,
x
.
Size
());
EXPECT_EQ
(
123
,
x
[
0
][
0
].
GetInt
());
EXPECT_TRUE
(
y
.
IsArray
());
EXPECT_TRUE
(
y
.
Empty
());
}
}
#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
(
const
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
template
<
typename
T
,
typename
Allocator
>
static
void
TestObject
(
T
&
x
,
Allocator
&
allocator
)
{
const
T
&
y
=
x
;
// const version
// AddMember()
x
.
AddMember
(
"A"
,
"Apple"
,
allocator
);
...
...
@@ -1215,7 +1356,7 @@ TEST(Value, Object) {
const
unsigned
n
=
10
;
for
(
unsigned
first
=
0
;
first
<
n
;
first
++
)
{
for
(
unsigned
last
=
first
;
last
<=
n
;
last
++
)
{
Value
(
kObjectType
).
Swap
(
x
);
x
.
RemoveAllMembers
(
);
for
(
unsigned
i
=
0
;
i
<
n
;
i
++
)
x
.
AddMember
(
keys
[
i
],
Value
(
kArrayType
).
PushBack
(
i
,
allocator
),
allocator
);
...
...
@@ -1238,6 +1379,23 @@ TEST(Value, Object) {
x
.
RemoveAllMembers
();
EXPECT_TRUE
(
x
.
ObjectEmpty
());
EXPECT_EQ
(
0u
,
x
.
MemberCount
());
}
TEST
(
Value
,
Object
)
{
Value
x
(
kObjectType
);
const
Value
&
y
=
x
;
// const version
Value
::
AllocatorType
allocator
;
EXPECT_EQ
(
kObjectType
,
x
.
GetType
());
EXPECT_TRUE
(
x
.
IsObject
());
EXPECT_TRUE
(
x
.
ObjectEmpty
());
EXPECT_EQ
(
0u
,
x
.
MemberCount
());
EXPECT_EQ
(
kObjectType
,
y
.
GetType
());
EXPECT_TRUE
(
y
.
IsObject
());
EXPECT_TRUE
(
y
.
ObjectEmpty
());
EXPECT_EQ
(
0u
,
y
.
MemberCount
());
TestObject
(
x
,
allocator
);
// SetObject()
Value
z
;
...
...
@@ -1245,6 +1403,100 @@ TEST(Value, Object) {
EXPECT_TRUE
(
z
.
IsObject
());
}
TEST
(
Value
,
ObjectHelper
)
{
Value
::
AllocatorType
allocator
;
{
Value
x
(
kObjectType
);
Value
::
Object
o
=
x
.
GetObject
();
TestObject
(
o
,
allocator
);
}
{
Value
x
(
kObjectType
);
Value
::
Object
o
=
x
.
GetObject
();
o
.
AddMember
(
"1"
,
1
,
allocator
);
Value
::
Object
o2
(
o
);
// copy constructor
EXPECT_EQ
(
1
,
o2
.
MemberCount
());
Value
::
Object
o3
=
o
;
EXPECT_EQ
(
1
,
o3
.
MemberCount
());
Value
::
ConstObject
y
=
static_cast
<
const
Value
&>
(
x
).
GetObject
();
(
void
)
y
;
// y.AddMember("1", 1, allocator); // should not compile
// Templated functions
x
.
RemoveAllMembers
();
EXPECT_TRUE
(
x
.
Is
<
Value
::
Object
>
());
EXPECT_TRUE
(
x
.
Is
<
Value
::
ConstObject
>
());
o
.
AddMember
(
"1"
,
1
,
allocator
);
EXPECT_EQ
(
1
,
x
.
Get
<
Value
::
Object
>
()[
"1"
].
GetInt
());
EXPECT_EQ
(
1
,
x
.
Get
<
Value
::
ConstObject
>
()[
"1"
].
GetInt
());
Value
x2
;
x2
.
Set
<
Value
::
Object
>
(
o
);
EXPECT_TRUE
(
x
.
IsObject
());
// IsObject() is invariant after moving
EXPECT_EQ
(
1
,
x2
.
Get
<
Value
::
Object
>
()[
"1"
].
GetInt
());
}
{
Value
x
(
kObjectType
);
x
.
AddMember
(
"a"
,
"apple"
,
allocator
);
Value
y
(
x
.
GetObject
());
EXPECT_STREQ
(
"apple"
,
y
[
"a"
].
GetString
());
EXPECT_TRUE
(
x
.
IsObject
());
// Invariant
}
{
Value
x
(
kObjectType
);
x
.
AddMember
(
"a"
,
"apple"
,
allocator
);
Value
y
(
kObjectType
);
y
.
AddMember
(
"fruits"
,
x
.
GetObject
(),
allocator
);
EXPECT_STREQ
(
"apple"
,
y
[
"fruits"
][
"a"
].
GetString
());
EXPECT_TRUE
(
x
.
IsObject
());
// Invariant
}
}
#if RAPIDJSON_HAS_CXX11_RANGE_FOR
TEST
(
Value
,
ObjectHelperRangeFor
)
{
Value
::
AllocatorType
allocator
;
Value
x
(
kObjectType
);
for
(
int
i
=
0
;
i
<
10
;
i
++
)
{
char
name
[
10
];
Value
n
(
name
,
static_cast
<
SizeType
>
(
sprintf
(
name
,
"%d"
,
i
)),
allocator
);
x
.
AddMember
(
n
,
i
,
allocator
);
}
{
int
i
=
0
;
for
(
auto
&
m
:
x
.
GetObject
())
{
char
name
[
10
];
sprintf
(
name
,
"%d"
,
i
);
EXPECT_STREQ
(
name
,
m
.
name
.
GetString
());
EXPECT_EQ
(
i
,
m
.
value
.
GetInt
());
i
++
;
}
EXPECT_EQ
(
i
,
10
);
}
{
int
i
=
0
;
for
(
const
auto
&
m
:
const_cast
<
const
Value
&>
(
x
).
GetObject
())
{
char
name
[
10
];
sprintf
(
name
,
"%d"
,
i
);
EXPECT_STREQ
(
name
,
m
.
name
.
GetString
());
EXPECT_EQ
(
i
,
m
.
value
.
GetInt
());
i
++
;
}
EXPECT_EQ
(
i
,
10
);
}
// Object a = x.GetObject();
// Object ca = const_cast<const Value&>(x).GetObject();
}
#endif
TEST
(
Value
,
EraseMember_String
)
{
Value
::
AllocatorType
allocator
;
Value
x
(
kObjectType
);
...
...
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