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
881c91d6
Commit
881c91d6
authored
Sep 05, 2014
by
Milo Yip
Browse files
Options
Browse Files
Download
Plain Diff
Merge master and implement kParseFullPrecision
parents
d875f16a
5e03cbf1
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
709 additions
and
275 deletions
+709
-275
Doxyfile
build/Doxyfile
+5
-2
capitalize.cpp
example/capitalize/capitalize.cpp
+1
-0
simplereader.cpp
example/simplereader/simplereader.cpp
+4
-0
document.h
include/rapidjson/document.h
+176
-64
meta.h
include/rapidjson/internal/meta.h
+114
-31
prettywriter.h
include/rapidjson/prettywriter.h
+3
-0
rapidjson.h
include/rapidjson/rapidjson.h
+43
-2
reader.h
include/rapidjson/reader.h
+111
-63
writer.h
include/rapidjson/writer.h
+3
-0
readertest.cpp
test/unittest/readertest.cpp
+111
-88
unittest.h
test/unittest/unittest.h
+2
-8
valuetest.cpp
test/unittest/valuetest.cpp
+136
-17
No files found.
build/Doxyfile
View file @
881c91d6
...
...
@@ -1993,7 +1993,9 @@ INCLUDE_FILE_PATTERNS =
PREDEFINED = \
RAPIDJSON_DOXYGEN_RUNNING \
RAPIDJSON_DISABLEIF_RETURN(cond,returntype)=returntype
RAPIDJSON_REMOVEFPTR_(x)=x \
RAPIDJSON_ENABLEIF_RETURN(cond,returntype)="RAPIDJSON_REMOVEFPTR_ returntype" \
RAPIDJSON_DISABLEIF_RETURN(cond,returntype)="RAPIDJSON_REMOVEFPTR_ returntype"
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The
...
...
@@ -2002,7 +2004,8 @@ PREDEFINED = \
# definition found in the source code.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_AS_DEFINED =
EXPAND_AS_DEFINED = \
RAPIDJSON_NOEXCEPT
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
# remove all references to function-like macros that are alone on a line, have
...
...
example/capitalize/capitalize.cpp
View file @
881c91d6
...
...
@@ -31,6 +31,7 @@ struct CapitalizeFilter {
return
out_
.
String
(
&
buffer_
.
front
(),
length
,
true
);
// true = output handler need to copy the string
}
bool
StartObject
()
{
return
out_
.
StartObject
();
}
bool
Key
(
const
char
*
str
,
SizeType
length
,
bool
copy
)
{
return
String
(
str
,
length
,
copy
);
}
bool
EndObject
(
SizeType
memberCount
)
{
return
out_
.
EndObject
(
memberCount
);
}
bool
StartArray
()
{
return
out_
.
StartArray
();
}
bool
EndArray
(
SizeType
elementCount
)
{
return
out_
.
EndArray
(
elementCount
);
}
...
...
example/simplereader/simplereader.cpp
View file @
881c91d6
...
...
@@ -17,6 +17,10 @@ struct MyHandler {
return
true
;
}
bool
StartObject
()
{
cout
<<
"StartObject()"
<<
endl
;
return
true
;
}
bool
Key
(
const
char
*
str
,
SizeType
length
,
bool
copy
)
{
cout
<<
"Key("
<<
str
<<
", "
<<
length
<<
", "
<<
boolalpha
<<
copy
<<
")"
<<
endl
;
return
true
;
}
bool
EndObject
(
SizeType
memberCount
)
{
cout
<<
"EndObject("
<<
memberCount
<<
")"
<<
endl
;
return
true
;
}
bool
StartArray
()
{
cout
<<
"StartArray()"
<<
endl
;
return
true
;
}
bool
EndArray
(
SizeType
elementCount
)
{
cout
<<
"EndArray("
<<
elementCount
<<
")"
<<
endl
;
return
true
;
}
...
...
include/rapidjson/document.h
View file @
881c91d6
...
...
@@ -24,6 +24,7 @@
/*! \file document.h */
#include "reader.h"
#include "internal/meta.h"
#include "internal/strfunc.h"
#include <new> // placement new
...
...
@@ -38,15 +39,17 @@ RAPIDJSON_DIAG_OFF(effc++)
///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_HAS_STDSTRING
#ifndef RAPIDJSON_HAS_STDSTRING
#ifdef RAPIDJSON_DOXYGEN_RUNNING
#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation
#else
#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default
#endif
#ifdef RAPIDJSON_HAS_STDSTRING
/*! \def RAPIDJSON_HAS_STDSTRING
\ingroup RAPIDJSON_CONFIG
\brief Enable RapidJSON support for \c std::string
By defining this preprocessor symbol, several convenience functions for using
By defining this preprocessor symbol
to \c 1
, several convenience functions for using
\ref rapidjson::GenericValue with \c std::string are enabled, especially
for construction and comparison.
...
...
@@ -56,7 +59,6 @@ RAPIDJSON_DIAG_OFF(effc++)
#endif // RAPIDJSON_HAS_STDSTRING
#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
#include "internal/meta.h"
#include <iterator> // std::iterator, std::random_access_iterator_tag
#endif
...
...
@@ -277,7 +279,7 @@ struct GenericStringRef {
GenericValue instead.
*/
template
<
SizeType
N
>
GenericStringRef
(
const
CharType
(
&
str
)[
N
])
GenericStringRef
(
const
CharType
(
&
str
)[
N
])
RAPIDJSON_NOEXCEPT
:
s
(
str
),
length
(
N
-
1
)
{}
//! Explicitly create string reference from \c const character pointer
...
...
@@ -300,7 +302,7 @@ struct GenericStringRef {
GenericValue instead.
*/
explicit
GenericStringRef
(
const
CharType
*
str
)
:
s
(
str
),
length
(
internal
::
StrLen
(
str
)){}
:
s
(
str
),
length
(
internal
::
StrLen
(
str
)){
RAPIDJSON_ASSERT
(
s
!=
NULL
);
}
//! Create constant string reference from pointer and length
/*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
...
...
@@ -363,7 +365,7 @@ inline GenericStringRef<CharType> StringRef(const CharType* str, size_t length)
return
GenericStringRef
<
CharType
>
(
str
,
SizeType
(
length
));
}
#if
def
RAPIDJSON_HAS_STDSTRING
#if RAPIDJSON_HAS_STDSTRING
//! Mark a string object as constant string
/*! Mark a string object (e.g. \c std::string) as a "string literal".
This function can be used to avoid copying a string to be referenced as a
...
...
@@ -382,6 +384,22 @@ inline GenericStringRef<CharType> StringRef(const std::basic_string<CharType>& s
}
#endif
///////////////////////////////////////////////////////////////////////////////
// GenericValue type traits
namespace
internal
{
template
<
typename
T
,
typename
Encoding
=
void
,
typename
Allocator
=
void
>
struct
IsGenericValueImpl
:
FalseType
{};
// select candidates according to nested encoding and allocator types
template
<
typename
T
>
struct
IsGenericValueImpl
<
T
,
typename
Void
<
typename
T
::
EncodingType
>::
Type
,
typename
Void
<
typename
T
::
AllocatorType
>::
Type
>
:
IsBaseOf
<
GenericValue
<
typename
T
::
EncodingType
,
typename
T
::
AllocatorType
>
,
T
>::
Type
{};
// helper to match arbitrary GenericValue instantiations, including derived classes
template
<
typename
T
>
struct
IsGenericValue
:
IsGenericValueImpl
<
T
>::
Type
{};
}
// namespace internal
///////////////////////////////////////////////////////////////////////////////
// GenericValue
...
...
@@ -414,7 +432,14 @@ public:
//@{
//! Default constructor creates a null value.
GenericValue
()
:
data_
(),
flags_
(
kNullFlag
)
{}
GenericValue
()
RAPIDJSON_NOEXCEPT
:
data_
(),
flags_
(
kNullFlag
)
{}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Move constructor in C++11
GenericValue
(
GenericValue
&&
rhs
)
RAPIDJSON_NOEXCEPT
:
data_
(
rhs
.
data_
),
flags_
(
rhs
.
flags_
)
{
rhs
.
flags_
=
kNullFlag
;
// give up contents
}
#endif
private
:
//! Copy constructor is not permitted.
...
...
@@ -427,7 +452,7 @@ public:
\param type Type of the value.
\note Default content for number is zero.
*/
GenericValue
(
Type
type
)
:
data_
(),
flags_
()
{
GenericValue
(
Type
type
)
RAPIDJSON_NOEXCEPT
:
data_
(),
flags_
()
{
static
const
unsigned
defaultFlags
[
7
]
=
{
kNullFlag
,
kFalseFlag
,
kTrueFlag
,
kObjectFlag
,
kArrayFlag
,
kConstStringFlag
,
kNumberAnyFlag
...
...
@@ -444,7 +469,7 @@ public:
\see CopyFrom()
*/
template
<
typename
SourceAllocator
>
GenericValue
(
const
GenericValue
<
Encoding
,
SourceAllocator
>&
rhs
,
Allocator
&
allocator
);
GenericValue
(
const
GenericValue
<
Encoding
,
SourceAllocator
>&
rhs
,
Allocator
&
allocator
);
//! Constructor for boolean value.
/*! \param b Boolean value
...
...
@@ -454,28 +479,31 @@ public:
*/
#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen
template
<
typename
T
>
explicit
GenericValue
(
T
b
,
RAPIDJSON_ENABLEIF
((
internal
::
IsSame
<
T
,
bool
>
)))
explicit
GenericValue
(
T
b
,
RAPIDJSON_ENABLEIF
((
internal
::
IsSame
<
T
,
bool
>
)))
RAPIDJSON_NOEXCEPT
#else
explicit
GenericValue
(
bool
b
)
explicit
GenericValue
(
bool
b
)
RAPIDJSON_NOEXCEPT
#endif
:
data_
(),
flags_
(
b
?
kTrueFlag
:
kFalseFlag
)
{}
:
data_
(),
flags_
(
b
?
kTrueFlag
:
kFalseFlag
)
{
// safe-guard against failing SFINAE
RAPIDJSON_STATIC_ASSERT
((
internal
::
IsSame
<
bool
,
T
>::
Value
));
}
//! Constructor for int value.
explicit
GenericValue
(
int
i
)
:
data_
(),
flags_
(
kNumberIntFlag
)
{
explicit
GenericValue
(
int
i
)
RAPIDJSON_NOEXCEPT
:
data_
(),
flags_
(
kNumberIntFlag
)
{
data_
.
n
.
i64
=
i
;
if
(
i
>=
0
)
flags_
|=
kUintFlag
|
kUint64Flag
;
}
//! Constructor for unsigned value.
explicit
GenericValue
(
unsigned
u
)
:
data_
(),
flags_
(
kNumberUintFlag
)
{
explicit
GenericValue
(
unsigned
u
)
RAPIDJSON_NOEXCEPT
:
data_
(),
flags_
(
kNumberUintFlag
)
{
data_
.
n
.
u64
=
u
;
if
(
!
(
u
&
0x80000000
))
flags_
|=
kIntFlag
|
kInt64Flag
;
}
//! Constructor for int64_t value.
explicit
GenericValue
(
int64_t
i64
)
:
data_
(),
flags_
(
kNumberInt64Flag
)
{
explicit
GenericValue
(
int64_t
i64
)
RAPIDJSON_NOEXCEPT
:
data_
(),
flags_
(
kNumberInt64Flag
)
{
data_
.
n
.
i64
=
i64
;
if
(
i64
>=
0
)
{
flags_
|=
kNumberUint64Flag
;
...
...
@@ -489,7 +517,7 @@ public:
}
//! Constructor for uint64_t value.
explicit
GenericValue
(
uint64_t
u64
)
:
data_
(),
flags_
(
kNumberUint64Flag
)
{
explicit
GenericValue
(
uint64_t
u64
)
RAPIDJSON_NOEXCEPT
:
data_
(),
flags_
(
kNumberUint64Flag
)
{
data_
.
n
.
u64
=
u64
;
if
(
!
(
u64
&
RAPIDJSON_UINT64_C2
(
0x80000000
,
0x00000000
)))
flags_
|=
kInt64Flag
;
...
...
@@ -500,13 +528,13 @@ public:
}
//! Constructor for double value.
explicit
GenericValue
(
double
d
)
:
data_
(),
flags_
(
kNumberDoubleFlag
)
{
data_
.
n
.
d
=
d
;
}
explicit
GenericValue
(
double
d
)
RAPIDJSON_NOEXCEPT
:
data_
(),
flags_
(
kNumberDoubleFlag
)
{
data_
.
n
.
d
=
d
;
}
//! Constructor for constant string (i.e. do not make a copy of string)
GenericValue
(
const
Ch
*
s
,
SizeType
length
)
:
data_
(),
flags_
()
{
SetStringRaw
(
StringRef
(
s
,
length
));
}
GenericValue
(
const
Ch
*
s
,
SizeType
length
)
RAPIDJSON_NOEXCEPT
:
data_
(),
flags_
()
{
SetStringRaw
(
StringRef
(
s
,
length
));
}
//! Constructor for constant string (i.e. do not make a copy of string)
explicit
GenericValue
(
StringRefType
s
)
:
data_
(),
flags_
()
{
SetStringRaw
(
s
);
}
explicit
GenericValue
(
StringRefType
s
)
RAPIDJSON_NOEXCEPT
:
data_
(),
flags_
()
{
SetStringRaw
(
s
);
}
//! Constructor for copy-string (i.e. do make a copy of string)
GenericValue
(
const
Ch
*
s
,
SizeType
length
,
Allocator
&
allocator
)
:
data_
(),
flags_
()
{
SetStringRaw
(
StringRef
(
s
,
length
),
allocator
);
}
...
...
@@ -514,7 +542,7 @@ public:
//! Constructor for copy-string (i.e. do make a copy of string)
GenericValue
(
const
Ch
*
s
,
Allocator
&
allocator
)
:
data_
(),
flags_
()
{
SetStringRaw
(
StringRef
(
s
),
allocator
);
}
#if
def
RAPIDJSON_HAS_STDSTRING
#if RAPIDJSON_HAS_STDSTRING
//! Constructor for copy-string from a string object (i.e. do make a copy of string)
/*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
*/
...
...
@@ -557,19 +585,26 @@ public:
//! Assignment with move semantics.
/*! \param rhs Source of the assignment. It will become a null value after assignment.
*/
GenericValue
&
operator
=
(
GenericValue
&
rhs
)
{
GenericValue
&
operator
=
(
GenericValue
&
rhs
)
RAPIDJSON_NOEXCEPT
{
RAPIDJSON_ASSERT
(
this
!=
&
rhs
);
this
->~
GenericValue
();
RawAssign
(
rhs
);
return
*
this
;
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Move assignment in C++11
GenericValue
&
operator
=
(
GenericValue
&&
rhs
)
RAPIDJSON_NOEXCEPT
{
return
*
this
=
rhs
.
Move
();
}
#endif
//! Assignment of constant string reference (no copy)
/*! \param str Constant string reference to be assigned
\note This overload is needed to avoid clashes with the generic primitive type assignment overload below.
\see GenericStringRef, operator=(T)
*/
GenericValue
&
operator
=
(
StringRefType
str
)
{
GenericValue
&
operator
=
(
StringRefType
str
)
RAPIDJSON_NOEXCEPT
{
GenericValue
s
(
str
);
return
*
this
=
s
;
}
...
...
@@ -587,7 +622,7 @@ public:
use \ref SetBool() instead.
*/
template
<
typename
T
>
RAPIDJSON_DISABLEIF_RETURN
(
internal
::
IsPointer
<
T
>
,
GenericValue
&
)
RAPIDJSON_DISABLEIF_RETURN
(
(
internal
::
IsPointer
<
T
>
),
(
GenericValue
&
)
)
operator
=
(
T
value
)
{
GenericValue
v
(
value
);
return
*
this
=
v
;
...
...
@@ -600,10 +635,10 @@ public:
\param allocator Allocator to use for copying
*/
template
<
typename
SourceAllocator
>
GenericValue
&
CopyFrom
(
const
GenericValue
<
Encoding
,
SourceAllocator
>&
rhs
,
Allocator
&
allocator
)
{
GenericValue
&
CopyFrom
(
const
GenericValue
<
Encoding
,
SourceAllocator
>&
rhs
,
Allocator
&
allocator
)
{
RAPIDJSON_ASSERT
((
void
*
)
this
!=
(
void
const
*
)
&
rhs
);
this
->~
GenericValue
();
new
(
this
)
GenericValue
(
rhs
,
allocator
);
new
(
this
)
GenericValue
(
rhs
,
allocator
);
return
*
this
;
}
...
...
@@ -612,7 +647,7 @@ public:
\param other Another value.
\note Constant complexity.
*/
GenericValue
&
Swap
(
GenericValue
&
other
)
{
GenericValue
&
Swap
(
GenericValue
&
other
)
RAPIDJSON_NOEXCEPT
{
GenericValue
temp
;
temp
.
RawAssign
(
*
this
);
RawAssign
(
other
);
...
...
@@ -622,7 +657,7 @@ public:
//! Prepare Value for move semantics
/*! \return *this */
GenericValue
&
Move
()
{
return
*
this
;
}
GenericValue
&
Move
()
RAPIDJSON_NOEXCEPT
{
return
*
this
;
}
//@}
//!@name Equal-to and not-equal-to operators
...
...
@@ -632,7 +667,9 @@ public:
\note If an object contains duplicated named member, comparing equality with any object is always \c false.
\note Linear time complexity (number of all values in the subtree and total lengths of all strings).
*/
bool
operator
==
(
const
GenericValue
&
rhs
)
const
{
template
<
typename
SourceAllocator
>
bool
operator
==
(
const
GenericValue
<
Encoding
,
SourceAllocator
>&
rhs
)
const
{
typedef
GenericValue
<
Encoding
,
SourceAllocator
>
RhsType
;
if
(
GetType
()
!=
rhs
.
GetType
())
return
false
;
...
...
@@ -641,7 +678,7 @@ public:
if
(
data_
.
o
.
size
!=
rhs
.
data_
.
o
.
size
)
return
false
;
for
(
ConstMemberIterator
lhsMemberItr
=
MemberBegin
();
lhsMemberItr
!=
MemberEnd
();
++
lhsMemberItr
)
{
ConstMemberIterator
rhsMemberItr
=
rhs
.
FindMember
(
lhsMemberItr
->
name
);
typename
RhsType
::
ConstMemberIterator
rhsMemberItr
=
rhs
.
FindMember
(
lhsMemberItr
->
name
);
if
(
rhsMemberItr
==
rhs
.
MemberEnd
()
||
lhsMemberItr
->
value
!=
rhsMemberItr
->
value
)
return
false
;
}
...
...
@@ -659,7 +696,7 @@ public:
return
StringEqual
(
rhs
);
case
kNumberType
:
if
(
IsDouble
()
||
rhs
.
Get
Double
())
if
(
IsDouble
()
||
rhs
.
Is
Double
())
return
GetDouble
()
==
rhs
.
GetDouble
();
// May convert one operand from integer to double.
else
return
data_
.
n
.
u64
==
rhs
.
data_
.
n
.
u64
;
...
...
@@ -672,7 +709,7 @@ public:
//! Equal-to operator with const C-string pointer
bool
operator
==
(
const
Ch
*
rhs
)
const
{
return
*
this
==
GenericValue
(
StringRef
(
rhs
));
}
#if
def
RAPIDJSON_HAS_STDSTRING
#if RAPIDJSON_HAS_STDSTRING
//! Equal-to operator with string object
/*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
*/
...
...
@@ -682,22 +719,31 @@ public:
//! Equal-to operator with primitive types
/*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false
*/
template
<
typename
T
>
RAPIDJSON_DISABLEIF_RETURN
(
internal
::
IsPointer
<
T
>
,
bool
)
operator
==
(
const
T
&
rhs
)
const
{
return
*
this
==
GenericValue
(
rhs
);
}
template
<
typename
T
>
RAPIDJSON_DISABLEIF_RETURN
((
internal
::
OrExpr
<
internal
::
IsPointer
<
T
>
,
internal
::
IsGenericValue
<
T
>
>
),
(
bool
))
operator
==
(
const
T
&
rhs
)
const
{
return
*
this
==
GenericValue
(
rhs
);
}
//! Not-equal-to operator
/*! \return !(*this == rhs)
*/
template
<
typename
SourceAllocator
>
bool
operator
!=
(
const
GenericValue
<
Encoding
,
SourceAllocator
>&
rhs
)
const
{
return
!
(
*
this
==
rhs
);
}
//! Not-equal-to operator with const C-string pointer
bool
operator
!=
(
const
Ch
*
rhs
)
const
{
return
!
(
*
this
==
rhs
);
}
//! Not-equal-to operator with arbitrary types
/*! \return !(*this == rhs)
*/
template
<
typename
T
>
bool
operator
!=
(
const
T
&
rhs
)
const
{
return
!
(
*
this
==
rhs
);
}
template
<
typename
T
>
RAPIDJSON_DISABLEIF_RETURN
((
internal
::
IsGenericValue
<
T
>
),
(
bool
))
operator
!=
(
const
T
&
rhs
)
const
{
return
!
(
*
this
==
rhs
);
}
//! Equal-to operator with arbitrary types (symmetric version)
/*! \return (rhs == lhs)
*/
template
<
typename
T
>
friend
bool
operator
==
(
const
T
&
lhs
,
const
GenericValue
&
rhs
)
{
return
rhs
==
lhs
;
}
template
<
typename
T
>
friend
RAPIDJSON_DISABLEIF_RETURN
((
internal
::
IsGenericValue
<
T
>
),
(
bool
))
operator
==
(
const
T
&
lhs
,
const
GenericValue
&
rhs
)
{
return
rhs
==
lhs
;
}
//! Not-Equal-to operator with arbitrary types (symmetric version)
/*! \return !(rhs == lhs)
*/
template
<
typename
T
>
friend
bool
operator
!=
(
const
T
&
lhs
,
const
GenericValue
&
rhs
)
{
return
!
(
rhs
==
lhs
);
}
template
<
typename
T
>
friend
RAPIDJSON_DISABLEIF_RETURN
((
internal
::
IsGenericValue
<
T
>
),
(
bool
))
operator
!=
(
const
T
&
lhs
,
const
GenericValue
&
rhs
)
{
return
!
(
rhs
==
lhs
);
}
//@}
//!@name Type
...
...
@@ -766,7 +812,8 @@ public:
// This version is faster because it does not need a StrLen().
// It can also handle string with null character.
GenericValue
&
operator
[](
const
GenericValue
&
name
)
{
template
<
typename
SourceAllocator
>
GenericValue
&
operator
[](
const
GenericValue
<
Encoding
,
SourceAllocator
>&
name
)
{
MemberIterator
member
=
FindMember
(
name
);
if
(
member
!=
MemberEnd
())
return
member
->
value
;
...
...
@@ -776,7 +823,8 @@ public:
return
NullValue
;
}
}
const
GenericValue
&
operator
[](
const
GenericValue
&
name
)
const
{
return
const_cast
<
GenericValue
&>
(
*
this
)[
name
];
}
template
<
typename
SourceAllocator
>
const
GenericValue
&
operator
[](
const
GenericValue
<
Encoding
,
SourceAllocator
>&
name
)
const
{
return
const_cast
<
GenericValue
&>
(
*
this
)[
name
];
}
//! Const member iterator
/*! \pre IsObject() == true */
...
...
@@ -810,7 +858,8 @@ public:
\note It is better to use FindMember() directly if you need the obtain the value as well.
\note Linear time complexity.
*/
bool
HasMember
(
const
GenericValue
&
name
)
const
{
return
FindMember
(
name
)
!=
MemberEnd
();
}
template
<
typename
SourceAllocator
>
bool
HasMember
(
const
GenericValue
<
Encoding
,
SourceAllocator
>&
name
)
const
{
return
FindMember
(
name
)
!=
MemberEnd
();
}
//! Find member by name.
/*!
...
...
@@ -844,7 +893,8 @@ public:
\c std::map, this has been changed to MemberEnd() now.
\note Linear time complexity.
*/
MemberIterator
FindMember
(
const
GenericValue
&
name
)
{
template
<
typename
SourceAllocator
>
MemberIterator
FindMember
(
const
GenericValue
<
Encoding
,
SourceAllocator
>&
name
)
{
RAPIDJSON_ASSERT
(
IsObject
());
RAPIDJSON_ASSERT
(
name
.
IsString
());
MemberIterator
member
=
MemberBegin
();
...
...
@@ -853,7 +903,7 @@ public:
break
;
return
member
;
}
ConstMemberIterator
FindMember
(
const
GenericValue
&
name
)
const
{
return
const_cast
<
GenericValue
&>
(
*
this
).
FindMember
(
name
);
}
template
<
typename
SourceAllocator
>
ConstMemberIterator
FindMember
(
const
GenericValue
<
Encoding
,
SourceAllocator
>
&
name
)
const
{
return
const_cast
<
GenericValue
&>
(
*
this
).
FindMember
(
name
);
}
//! Add a member (name-value pair) to the object.
/*! \param name A string value as name of member.
...
...
@@ -877,7 +927,7 @@ public:
}
else
{
SizeType
oldCapacity
=
o
.
capacity
;
o
.
capacity
*=
2
;
o
.
capacity
+=
(
oldCapacity
+
1
)
/
2
;
// grow by factor 1.5
o
.
members
=
reinterpret_cast
<
Member
*>
(
allocator
.
Realloc
(
o
.
members
,
oldCapacity
*
sizeof
(
Member
),
o
.
capacity
*
sizeof
(
Member
)));
}
}
...
...
@@ -887,6 +937,23 @@ public:
return
*
this
;
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericValue
&
AddMember
(
GenericValue
&&
name
,
GenericValue
&&
value
,
Allocator
&
allocator
)
{
return
AddMember
(
name
,
value
,
allocator
);
}
GenericValue
&
AddMember
(
GenericValue
&&
name
,
GenericValue
&
value
,
Allocator
&
allocator
)
{
return
AddMember
(
name
,
value
,
allocator
);
}
GenericValue
&
AddMember
(
GenericValue
&
name
,
GenericValue
&&
value
,
Allocator
&
allocator
)
{
return
AddMember
(
name
,
value
,
allocator
);
}
GenericValue
&
AddMember
(
StringRefType
name
,
GenericValue
&&
value
,
Allocator
&
allocator
)
{
GenericValue
n
(
name
);
return
AddMember
(
n
,
value
,
allocator
);
}
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Add a member (name-value pair) to the object.
/*! \param name A constant string reference as name of member.
\param value Value of any type.
...
...
@@ -934,7 +1001,7 @@ public:
\note Amortized Constant time complexity.
*/
template
<
typename
T
>
RAPIDJSON_DISABLEIF_RETURN
(
internal
::
IsPointer
<
T
>
,
GenericValue
&
)
RAPIDJSON_DISABLEIF_RETURN
(
(
internal
::
OrExpr
<
internal
::
IsPointer
<
T
>
,
internal
::
IsGenericValue
<
T
>
>
),
(
GenericValue
&
)
)
AddMember
(
StringRefType
name
,
T
value
,
Allocator
&
allocator
)
{
GenericValue
n
(
name
);
GenericValue
v
(
value
);
...
...
@@ -963,7 +1030,8 @@ public:
return
RemoveMember
(
n
);
}
bool
RemoveMember
(
const
GenericValue
&
name
)
{
template
<
typename
SourceAllocator
>
bool
RemoveMember
(
const
GenericValue
<
Encoding
,
SourceAllocator
>&
name
)
{
MemberIterator
m
=
FindMember
(
name
);
if
(
m
!=
MemberEnd
())
{
RemoveMember
(
m
);
...
...
@@ -1122,11 +1190,17 @@ int z = a[0u].GetInt(); // This works too.
GenericValue
&
PushBack
(
GenericValue
&
value
,
Allocator
&
allocator
)
{
RAPIDJSON_ASSERT
(
IsArray
());
if
(
data_
.
a
.
size
>=
data_
.
a
.
capacity
)
Reserve
(
data_
.
a
.
capacity
==
0
?
kDefaultArrayCapacity
:
data_
.
a
.
capacity
*
2
,
allocator
);
Reserve
(
data_
.
a
.
capacity
==
0
?
kDefaultArrayCapacity
:
(
data_
.
a
.
capacity
+
(
data_
.
a
.
capacity
+
1
)
/
2
)
,
allocator
);
data_
.
a
.
elements
[
data_
.
a
.
size
++
].
RawAssign
(
value
);
return
*
this
;
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericValue
&
PushBack
(
GenericValue
&&
value
,
Allocator
&
allocator
)
{
return
PushBack
(
value
,
allocator
);
}
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Append a constant string reference at the end of the array.
/*! \param value Constant string reference to be appended.
\param allocator Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator().
...
...
@@ -1158,7 +1232,7 @@ int z = a[0u].GetInt(); // This works too.
\note Amortized constant time complexity.
*/
template
<
typename
T
>
RAPIDJSON_DISABLEIF_RETURN
(
internal
::
IsPointer
<
T
>
,
GenericValue
&
)
RAPIDJSON_DISABLEIF_RETURN
(
(
internal
::
OrExpr
<
internal
::
IsPointer
<
T
>
,
internal
::
IsGenericValue
<
T
>
>
),
(
GenericValue
&
)
)
PushBack
(
T
value
,
Allocator
&
allocator
)
{
GenericValue
v
(
value
);
return
PushBack
(
v
,
allocator
);
...
...
@@ -1239,12 +1313,12 @@ int z = a[0u].GetInt(); // This works too.
//!@name String
//@{
const
Ch
*
GetString
()
const
{
RAPIDJSON_ASSERT
(
IsString
());
return
data_
.
s
.
str
;
}
const
Ch
*
GetString
()
const
{
RAPIDJSON_ASSERT
(
IsString
());
return
((
flags_
&
kInlineStrFlag
)
?
data_
.
ss
.
str
:
data_
.
s
.
str
)
;
}
//! Get the length of string.
/*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength().
*/
SizeType
GetStringLength
()
const
{
RAPIDJSON_ASSERT
(
IsString
());
return
data_
.
s
.
length
;
}
SizeType
GetStringLength
()
const
{
RAPIDJSON_ASSERT
(
IsString
());
return
((
flags_
&
kInlineStrFlag
)
?
(
data_
.
ss
.
GetLength
())
:
data_
.
s
.
length
)
;
}
//! Set this value as a string without copying source string.
/*! This version has better performance with supplied length, and also support string containing null character.
...
...
@@ -1281,7 +1355,7 @@ int z = a[0u].GetInt(); // This works too.
*/
GenericValue
&
SetString
(
const
Ch
*
s
,
Allocator
&
allocator
)
{
return
SetString
(
s
,
internal
::
StrLen
(
s
),
allocator
);
}
#if
def
RAPIDJSON_HAS_STDSTRING
#if RAPIDJSON_HAS_STDSTRING
//! Set this value as a string by copying from source string.
/*! \param s source string.
\param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
...
...
@@ -1312,7 +1386,7 @@ int z = a[0u].GetInt(); // This works too.
if
(
!
handler
.
StartObject
())
return
false
;
for
(
ConstMemberIterator
m
=
MemberBegin
();
m
!=
MemberEnd
();
++
m
)
{
if
(
!
handler
.
String
(
m
->
name
.
data_
.
s
.
str
,
m
->
name
.
data_
.
s
.
length
,
(
m
->
name
.
flags_
&
kCopyFlag
)
!=
0
))
if
(
!
handler
.
Key
(
m
->
name
.
GetString
(),
m
->
name
.
GetStringLength
()
,
(
m
->
name
.
flags_
&
kCopyFlag
)
!=
0
))
return
false
;
if
(
!
m
->
value
.
Accept
(
handler
))
return
false
;
...
...
@@ -1328,7 +1402,7 @@ int z = a[0u].GetInt(); // This works too.
return
handler
.
EndArray
(
data_
.
a
.
size
);
case
kStringType
:
return
handler
.
String
(
data_
.
s
.
str
,
data_
.
s
.
length
,
(
flags_
&
kCopyFlag
)
!=
0
);
return
handler
.
String
(
GetString
(),
GetStringLength
()
,
(
flags_
&
kCopyFlag
)
!=
0
);
case
kNumberType
:
if
(
IsInt
())
return
handler
.
Int
(
data_
.
n
.
i
.
i
);
...
...
@@ -1344,8 +1418,8 @@ int z = a[0u].GetInt(); // This works too.
}
private
:
template
<
typename
,
typename
,
typename
>
friend
class
GenericDocument
;
template
<
typename
,
typename
>
friend
class
GenericValue
;
template
<
typename
,
typename
,
typename
>
friend
class
GenericDocument
;
enum
{
kBoolFlag
=
0x100
,
...
...
@@ -1357,6 +1431,7 @@ private:
kDoubleFlag
=
0x4000
,
kStringFlag
=
0x100000
,
kCopyFlag
=
0x200000
,
kInlineStrFlag
=
0x400000
,
// Initial flags of different types.
kNullFlag
=
kNullType
,
...
...
@@ -1370,6 +1445,7 @@ private:
kNumberAnyFlag
=
kNumberType
|
kNumberFlag
|
kIntFlag
|
kInt64Flag
|
kUintFlag
|
kUint64Flag
|
kDoubleFlag
,
kConstStringFlag
=
kStringType
|
kStringFlag
,
kCopyStringFlag
=
kStringType
|
kStringFlag
|
kCopyFlag
,
kShortStringFlag
=
kStringType
|
kStringFlag
|
kCopyFlag
|
kInlineStrFlag
,
kObjectFlag
=
kObjectType
,
kArrayFlag
=
kArrayType
,
...
...
@@ -1385,6 +1461,23 @@ private:
unsigned
hashcode
;
//!< reserved
};
// 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
// implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars
// (excluding the terminating zero) and store a value to determine the length of the contained
// string in the last character str[LenPos] by storing "MaxSize - length" there. If the string
// to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as
// the string terminator as well. For getting the string length back from that value just use
// "MaxSize - str[LenPos]".
// This allows to store 11-chars strings in 32-bit mode and 15-chars strings in 64-bit mode
// inline (for `UTF8`-encoded strings).
struct
ShortString
{
enum
{
MaxChars
=
sizeof
(
String
)
/
sizeof
(
Ch
),
MaxSize
=
MaxChars
-
1
,
LenPos
=
MaxSize
};
Ch
str
[
MaxChars
];
inline
static
bool
Usable
(
SizeType
len
)
{
return
(
MaxSize
>=
len
);
}
inline
void
SetLength
(
SizeType
len
)
{
str
[
LenPos
]
=
(
Ch
)(
MaxSize
-
len
);
}
inline
SizeType
GetLength
()
const
{
return
(
SizeType
)(
MaxSize
-
str
[
LenPos
]);
}
};
// at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
// By using proper binary layout, retrieval of different integer types do not need conversions.
union
Number
{
#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN
...
...
@@ -1425,6 +1518,7 @@ private:
union
Data
{
String
s
;
ShortString
ss
;
Number
n
;
Object
o
;
Array
a
;
...
...
@@ -1447,7 +1541,7 @@ private:
}
//! Initialize this value as constant string, without calling destructor.
void
SetStringRaw
(
StringRefType
s
)
{
void
SetStringRaw
(
StringRefType
s
)
RAPIDJSON_NOEXCEPT
{
flags_
=
kConstStringFlag
;
data_
.
s
.
str
=
s
;
data_
.
s
.
length
=
s
.
length
;
...
...
@@ -1455,26 +1549,42 @@ private:
//! Initialize this value as copy string with initial data, without calling destructor.
void
SetStringRaw
(
StringRefType
s
,
Allocator
&
allocator
)
{
flags_
=
kCopyStringFlag
;
data_
.
s
.
str
=
(
Ch
*
)
allocator
.
Malloc
((
s
.
length
+
1
)
*
sizeof
(
Ch
));
data_
.
s
.
length
=
s
.
length
;
memcpy
(
const_cast
<
Ch
*>
(
data_
.
s
.
str
),
s
,
s
.
length
*
sizeof
(
Ch
));
const_cast
<
Ch
*>
(
data_
.
s
.
str
)[
s
.
length
]
=
'\0'
;
Ch
*
str
=
NULL
;
if
(
ShortString
::
Usable
(
s
.
length
))
{
flags_
=
kShortStringFlag
;
data_
.
ss
.
SetLength
(
s
.
length
);
str
=
data_
.
ss
.
str
;
}
else
{
flags_
=
kCopyStringFlag
;
data_
.
s
.
length
=
s
.
length
;
str
=
(
Ch
*
)
allocator
.
Malloc
((
s
.
length
+
1
)
*
sizeof
(
Ch
));
data_
.
s
.
str
=
str
;
}
memcpy
(
str
,
s
,
s
.
length
*
sizeof
(
Ch
));
str
[
s
.
length
]
=
'\0'
;
}
//! Assignment without calling destructor
void
RawAssign
(
GenericValue
&
rhs
)
{
void
RawAssign
(
GenericValue
&
rhs
)
RAPIDJSON_NOEXCEPT
{
data_
=
rhs
.
data_
;
flags_
=
rhs
.
flags_
;
rhs
.
flags_
=
kNullFlag
;
}
bool
StringEqual
(
const
GenericValue
&
rhs
)
const
{
template
<
typename
SourceAllocator
>
bool
StringEqual
(
const
GenericValue
<
Encoding
,
SourceAllocator
>&
rhs
)
const
{
RAPIDJSON_ASSERT
(
IsString
());
RAPIDJSON_ASSERT
(
rhs
.
IsString
());
return
data_
.
s
.
length
==
rhs
.
data_
.
s
.
length
&&
(
data_
.
s
.
str
==
rhs
.
data_
.
s
.
str
// fast path for constant string
||
memcmp
(
data_
.
s
.
str
,
rhs
.
data_
.
s
.
str
,
sizeof
(
Ch
)
*
data_
.
s
.
length
)
==
0
);
const
SizeType
len1
=
GetStringLength
();
const
SizeType
len2
=
rhs
.
GetStringLength
();
if
(
len1
!=
len2
)
{
return
false
;
}
const
Ch
*
const
str1
=
GetString
();
const
Ch
*
const
str2
=
rhs
.
GetString
();
if
(
str1
==
str2
)
{
return
true
;
}
// fast path for constant string
return
(
memcmp
(
str1
,
str2
,
sizeof
(
Ch
)
*
len1
)
==
0
);
}
Data
data_
;
...
...
@@ -1663,7 +1773,7 @@ private:
// callers of the following private Handler functions
template
<
typename
,
typename
,
typename
>
friend
class
GenericReader
;
// for parsing
friend
class
GenericValue
<
Encoding
,
Allocator
>
;
// for deep copying
template
<
typename
,
typename
>
friend
class
GenericValue
;
// for deep copying
// Implementation of Handler
bool
Null
()
{
new
(
stack_
.
template
Push
<
ValueType
>
())
ValueType
();
return
true
;
}
...
...
@@ -1684,6 +1794,8 @@ private:
bool
StartObject
()
{
new
(
stack_
.
template
Push
<
ValueType
>
())
ValueType
(
kObjectType
);
return
true
;
}
bool
Key
(
const
Ch
*
str
,
SizeType
length
,
bool
copy
)
{
return
String
(
str
,
length
,
copy
);
}
bool
EndObject
(
SizeType
memberCount
)
{
typename
ValueType
::
Member
*
members
=
stack_
.
template
Pop
<
typename
ValueType
::
Member
>
(
memberCount
);
stack_
.
template
Top
<
ValueType
>
()
->
SetObjectRaw
(
members
,
(
SizeType
)
memberCount
,
GetAllocator
());
...
...
include/rapidjson/internal/meta.h
View file @
881c91d6
...
...
@@ -21,57 +21,129 @@
#ifndef RAPIDJSON_INTERNAL_META_H_
#define RAPIDJSON_INTERNAL_META_H_
#ifndef RAPIDJSON_RAPIDJSON_H_
#error <rapidjson.h> not yet included. Do not include this file directly.
#endif
#ifdef __GNUC__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF
(
effc
++
)
#endif
#if defined(_MSC_VER)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF
(
6334
)
#endif
#if RAPIDJSON_HAS_CXX11_TYPETRAITS
#include <type_traits>
#endif
//@cond RAPIDJSON_INTERNAL
namespace
rapidjson
{
namespace
internal
{
template
<
int
N
>
struct
IntegralC
{
enum
{
Value
=
N
};
};
template
<
bool
Cond
>
struct
BoolType
:
IntegralC
<
Cond
>
{};
struct
TrueType
:
BoolType
<
true
>
{};
struct
FalseType
:
BoolType
<
false
>
{};
// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching
template
<
typename
T
>
struct
Void
{
typedef
void
Type
;
};
///////////////////////////////////////////////////////////////////////////////
// BoolType, TrueType, FalseType
//
template
<
bool
Cond
>
struct
BoolType
{
static
const
bool
Value
=
Cond
;
typedef
BoolType
Type
;
};
typedef
BoolType
<
true
>
TrueType
;
typedef
BoolType
<
false
>
FalseType
;
///////////////////////////////////////////////////////////////////////////////
// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr
//
template
<
bool
C
>
struct
SelectIfImpl
{
template
<
typename
T1
,
typename
T2
>
struct
Apply
{
typedef
T1
Type
;
};
};
template
<>
struct
SelectIfImpl
<
false
>
{
template
<
typename
T1
,
typename
T2
>
struct
Apply
{
typedef
T2
Type
;
};
};
template
<
bool
C
,
typename
T1
,
typename
T2
>
struct
SelectIfCond
:
SelectIfImpl
<
C
>::
template
Apply
<
T1
,
T2
>
{};
template
<
typename
C
,
typename
T1
,
typename
T2
>
struct
SelectIf
:
SelectIfCond
<
C
::
Value
,
T1
,
T2
>
{};
template
<
bool
Cond1
,
bool
Cond2
>
struct
AndExprCond
:
FalseType
{};
template
<>
struct
AndExprCond
<
true
,
true
>
:
TrueType
{};
template
<
bool
Cond1
,
bool
Cond2
>
struct
OrExprCond
:
TrueType
{};
template
<>
struct
OrExprCond
<
false
,
false
>
:
FalseType
{};
template
<
typename
C
>
struct
BoolExpr
:
SelectIf
<
C
,
TrueType
,
FalseType
>::
Type
{};
template
<
typename
C
>
struct
NotExpr
:
SelectIf
<
C
,
FalseType
,
TrueType
>::
Type
{};
template
<
typename
C1
,
typename
C2
>
struct
AndExpr
:
AndExprCond
<
C1
::
Value
,
C2
::
Value
>::
Type
{};
template
<
typename
C1
,
typename
C2
>
struct
OrExpr
:
OrExprCond
<
C1
::
Value
,
C2
::
Value
>::
Type
{};
///////////////////////////////////////////////////////////////////////////////
// AddConst, MaybeAddConst, RemoveConst
template
<
typename
T
>
struct
AddConst
{
typedef
const
T
Type
;
};
template
<
bool
Constify
,
typename
T
>
struct
MaybeAddConst
:
SelectIfCond
<
Constify
,
const
T
,
T
>
{};
template
<
typename
T
>
struct
RemoveConst
{
typedef
T
Type
;
};
template
<
typename
T
>
struct
RemoveConst
<
const
T
>
{
typedef
T
Type
;
};
template
<
bool
Condition
,
typename
T1
,
typename
T2
>
struct
SelectIfCond
;
template
<
typename
T1
,
typename
T2
>
struct
SelectIfCond
<
true
,
T1
,
T2
>
{
typedef
T1
Type
;
};
template
<
typename
T1
,
typename
T2
>
struct
SelectIfCond
<
false
,
T1
,
T2
>
{
typedef
T2
Type
;
};
template
<
typename
Condition
,
typename
T1
,
typename
T2
>
struct
SelectIf
:
SelectIfCond
<
Condition
::
Value
,
T1
,
T2
>
{};
template
<
bool
Constify
,
typename
T
>
struct
MaybeAddConst
:
SelectIfCond
<
Constify
,
const
T
,
T
>
{};
template
<
typename
T
,
typename
U
>
struct
IsSame
:
FalseType
{};
template
<
typename
T
>
struct
IsSame
<
T
,
T
>
:
TrueType
{};
///////////////////////////////////////////////////////////////////////////////
// IsSame, IsConst, IsMoreConst, IsPointer
//
template
<
typename
T
,
typename
U
>
struct
IsSame
:
FalseType
{};
template
<
typename
T
>
struct
IsSame
<
T
,
T
>
:
TrueType
{};
template
<
typename
T
>
struct
IsConst
:
FalseType
{};
template
<
typename
T
>
struct
IsConst
<
const
T
>
:
TrueType
{};
template
<
typename
CT
,
typename
T
>
struct
IsMoreConst
:
AndExpr
<
IsSame
<
typename
RemoveConst
<
CT
>::
Type
,
typename
RemoveConst
<
T
>::
Type
>
,
BoolType
<
IsConst
<
CT
>::
Value
>=
IsConst
<
T
>::
Value
>
>::
Type
{};
template
<
typename
T
>
struct
IsPointer
:
FalseType
{};
template
<
typename
T
>
struct
IsPointer
<
T
*>
:
TrueType
{};
template
<
typename
CT
,
typename
T
>
struct
IsMoreConst
{
enum
{
Value
=
(
IsSame
<
typename
RemoveConst
<
CT
>::
Type
,
typename
RemoveConst
<
T
>::
Type
>::
Value
&&
(
IsConst
<
CT
>::
Value
>=
IsConst
<
T
>::
Value
)
)
///////////////////////////////////////////////////////////////////////////////
// IsBaseOf
//
#if RAPIDJSON_HAS_CXX11_TYPETRAITS
template
<
typename
B
,
typename
D
>
struct
IsBaseOf
:
BoolType
<
::
std
::
is_base_of
<
B
,
D
>::
value
>
{};
#else // simplified version adopted from Boost
template
<
typename
B
,
typename
D
>
struct
IsBaseOfImpl
{
RAPIDJSON_STATIC_ASSERT
(
sizeof
(
B
)
!=
0
);
RAPIDJSON_STATIC_ASSERT
(
sizeof
(
D
)
!=
0
);
typedef
char
(
&
Yes
)[
1
];
typedef
char
(
&
No
)
[
2
];
template
<
typename
T
>
static
Yes
Check
(
const
D
*
,
T
);
static
No
Check
(
const
B
*
,
int
);
struct
Host
{
operator
const
B
*
()
const
;
operator
const
D
*
();
};
enum
{
Value
=
(
sizeof
(
Check
(
Host
(),
0
))
==
sizeof
(
Yes
))
};
};
template
<
bool
Condition
,
typename
T
=
void
>
struct
EnableIfCond
;
template
<
typename
T
>
struct
EnableIfCond
<
true
,
T
>
{
typedef
T
Type
;
};
template
<
typename
B
,
typename
D
>
struct
IsBaseOf
:
OrExpr
<
IsSame
<
B
,
D
>
,
BoolExpr
<
IsBaseOfImpl
<
B
,
D
>
>
>::
Type
{};
#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS
//////////////////////////////////////////////////////////////////////////
// EnableIf / DisableIf
//
template
<
bool
Condition
,
typename
T
=
void
>
struct
EnableIfCond
{
typedef
T
Type
;
};
template
<
typename
T
>
struct
EnableIfCond
<
false
,
T
>
{
/* empty */
};
template
<
bool
Condition
,
typename
T
=
void
>
struct
DisableIfCond
:
EnableIfCond
<!
Condition
,
T
>
{
};
template
<
bool
Condition
,
typename
T
=
void
>
struct
DisableIfCond
{
typedef
T
Type
;
};
template
<
typename
T
>
struct
DisableIfCond
<
true
,
T
>
{
/* empty */
};
template
<
typename
Condition
,
typename
T
=
void
>
struct
EnableIf
:
EnableIfCond
<
Condition
::
Value
,
T
>
{};
...
...
@@ -80,26 +152,37 @@ template <typename Condition, typename T = void>
struct
DisableIf
:
DisableIfCond
<
Condition
::
Value
,
T
>
{};
// SFINAE helpers
struct
Sfinae
Result
Tag
{};
template
<
typename
T
>
struct
RemoveSfinae
Fptr
{}
;
template
<
typename
T
>
struct
RemoveSfinae
Fptr
<
SfinaeResult
Tag
&
(
*
)(
T
)
>
{
typedef
T
Type
;
};
struct
SfinaeTag
{};
template
<
typename
T
>
struct
RemoveSfinae
Tag
;
template
<
typename
T
>
struct
RemoveSfinae
Tag
<
Sfinae
Tag
&
(
*
)(
T
)
>
{
typedef
T
Type
;
};
#define RAPIDJSON_REMOVEFPTR_(type) \
typename
::
rapidjson
::
internal
::
RemoveSfinae
Fptr
\
<
::
rapidjson
::
internal
::
Sfinae
Result
Tag
&
(
*
)
type
>::
Type
typename
::
rapidjson
::
internal
::
RemoveSfinae
Tag
\
<
::
rapidjson
::
internal
::
SfinaeTag
&
(
*
)
type
>::
Type
#define RAPIDJSON_ENABLEIF(cond) \
typename
::
rapidjson
::
internal
::
EnableIf
\
<
RAPIDJSON_REMOVEFPTR_
(
cond
)
>::
Type
*
=
NULL
#define RAPIDJSON_DISABLEIF(cond) \
typename
::
rapidjson
::
internal
::
DisableIf
\
<
RAPIDJSON_REMOVEFPTR_
(
cond
)
>::
Type
*
=
NULL
#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \
typename
::
rapidjson
::
internal
::
EnableIf
\
<
RAPIDJSON_REMOVEFPTR_
(
cond
),
\
RAPIDJSON_REMOVEFPTR_
(
returntype
)
>::
Type
#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \
typename
::
rapidjson
::
internal
::
DisableIf
<
cond
,
returntype
>::
Type
typename
::
rapidjson
::
internal
::
DisableIf
\
<
RAPIDJSON_REMOVEFPTR_
(
cond
),
\
RAPIDJSON_REMOVEFPTR_
(
returntype
)
>::
Type
}
// namespace internal
}
// namespace rapidjson
//@endcond
#if
def __GNUC__
#if
defined(__GNUC__) || defined(_MSC_VER)
RAPIDJSON_DIAG_POP
#endif
...
...
include/rapidjson/prettywriter.h
View file @
881c91d6
...
...
@@ -88,6 +88,8 @@ public:
return
Base
::
WriteStartObject
();
}
bool
Key
(
const
Ch
*
str
,
SizeType
length
,
bool
copy
=
false
)
{
return
String
(
str
,
length
,
copy
);
}
bool
EndObject
(
SizeType
memberCount
=
0
)
{
(
void
)
memberCount
;
RAPIDJSON_ASSERT
(
Base
::
level_stack_
.
GetSize
()
>=
sizeof
(
typename
Base
::
Level
));
...
...
@@ -135,6 +137,7 @@ public:
//! Simpler but slower overload.
bool
String
(
const
Ch
*
str
)
{
return
String
(
str
,
internal
::
StrLen
(
str
));
}
bool
Key
(
const
Ch
*
str
)
{
return
Key
(
str
,
internal
::
StrLen
(
str
));
}
//@}
protected
:
...
...
include/rapidjson/rapidjson.h
View file @
881c91d6
...
...
@@ -318,7 +318,12 @@ template<int x> struct StaticAssertTest {};
///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF
#if defined(__clang__) || (defined(__GNUC__) && RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__) >= RAPIDJSON_VERSION_CODE(4,2,0))
#if defined(__GNUC__)
#define RAPIDJSON_GNUC \
RAPIDJSON_VERSION_CODE
(
__GNUC__
,
__GNUC_MINOR__
,
__GNUC_PATCHLEVEL__
)
#endif
#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,2,0))
#define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x))
#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x)
...
...
@@ -326,7 +331,7 @@ template<int x> struct StaticAssertTest {};
RAPIDJSON_DIAG_PRAGMA
(
ignored
RAPIDJSON_STRINGIFY
(
RAPIDJSON_JOIN
(
-
W
,
x
)))
// push/pop support in Clang and GCC>=4.6
#if defined(__clang__) || (defined(
__GNUC__) && RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__)
>= RAPIDJSON_VERSION_CODE(4,6,0))
#if defined(__clang__) || (defined(
RAPIDJSON_GNUC) && RAPIDJSON_GNUC
>= RAPIDJSON_VERSION_CODE(4,6,0))
#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push)
#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop)
#else // GCC >= 4.2, < 4.6
...
...
@@ -352,6 +357,42 @@ template<int x> struct StaticAssertTest {};
#endif // RAPIDJSON_DIAG_*
///////////////////////////////////////////////////////////////////////////////
// C++11 features
#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS
#if defined(__clang__)
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS __has_feature(cxx_rvalue_references)
#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_RVALUE_REFS 1
#else
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
#endif
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT
#if defined(__clang__)
#define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept)
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__))
// (defined(_MSC_VER) && _MSC_VER >= ????) // not yet supported
#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
#else
#define RAPIDJSON_HAS_CXX11_NOEXCEPT 0
#endif
#endif
#if RAPIDJSON_HAS_CXX11_NOEXCEPT
#define RAPIDJSON_NOEXCEPT noexcept
#else
#define RAPIDJSON_NOEXCEPT
/* noexcept */
#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT
// no automatic detection, yet
#ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS
#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0
#endif
//!@endcond
///////////////////////////////////////////////////////////////////////////////
...
...
include/rapidjson/reader.h
View file @
881c91d6
...
...
@@ -48,6 +48,11 @@ RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
RAPIDJSON_DIAG_OFF
(
4702
)
// unreachable code
#endif
#ifdef __GNUC__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF
(
effc
++
)
#endif
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
#define RAPIDJSON_NOTHING
/* deliberately empty */
#ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN
...
...
@@ -156,6 +161,7 @@ concept Handler {
bool Double(double d);
bool String(const Ch* str, SizeType length, bool copy);
bool StartObject();
bool Key(const Ch* str, SizeType length, bool copy);
bool EndObject(SizeType memberCount);
bool StartArray();
bool EndArray(SizeType elementCount);
...
...
@@ -185,6 +191,7 @@ struct BaseReaderHandler {
bool
Double
(
double
)
{
return
static_cast
<
Override
&>
(
*
this
).
Default
();
}
bool
String
(
const
Ch
*
,
SizeType
,
bool
)
{
return
static_cast
<
Override
&>
(
*
this
).
Default
();
}
bool
StartObject
()
{
return
static_cast
<
Override
&>
(
*
this
).
Default
();
}
bool
Key
(
const
Ch
*
str
,
SizeType
len
,
bool
copy
)
{
return
static_cast
<
Override
&>
(
*
this
).
String
(
str
,
len
,
copy
);
}
bool
EndObject
(
SizeType
)
{
return
static_cast
<
Override
&>
(
*
this
).
Default
();
}
bool
StartArray
()
{
return
static_cast
<
Override
&>
(
*
this
).
Default
();
}
bool
EndArray
(
SizeType
)
{
return
static_cast
<
Override
&>
(
*
this
).
Default
();
}
...
...
@@ -475,7 +482,7 @@ private:
if
(
is
.
Peek
()
!=
'"'
)
RAPIDJSON_PARSE_ERROR
(
kParseErrorObjectMissName
,
is
.
Tell
());
ParseString
<
parseFlags
>
(
is
,
handler
);
ParseString
<
parseFlags
>
(
is
,
handler
,
true
);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID
;
SkipWhitespace
(
is
);
...
...
@@ -627,27 +634,30 @@ private:
// Parse string and generate String event. Different code paths for kParseInsituFlag.
template
<
unsigned
parseFlags
,
typename
InputStream
,
typename
Handler
>
void
ParseString
(
InputStream
&
is
,
Handler
&
handler
)
{
void
ParseString
(
InputStream
&
is
,
Handler
&
handler
,
bool
isKey
=
false
)
{
internal
::
StreamLocalCopy
<
InputStream
>
copy
(
is
);
InputStream
&
s
(
copy
.
s
);
bool
success
=
false
;
if
(
parseFlags
&
kParseInsituFlag
)
{
typename
InputStream
::
Ch
*
head
=
s
.
PutBegin
();
ParseStringToStream
<
parseFlags
,
SourceEncoding
,
SourceEncoding
>
(
s
,
s
);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID
;
size_t
length
=
s
.
PutEnd
(
head
)
-
1
;
RAPIDJSON_ASSERT
(
length
<=
0xFFFFFFFF
);
if
(
!
handler
.
String
((
typename
TargetEncoding
::
Ch
*
)
head
,
SizeType
(
length
),
false
))
RAPIDJSON_PARSE_ERROR
(
kParseErrorTermination
,
s
.
Tell
(
));
const
typename
TargetEncoding
::
Ch
*
const
str
=
(
typename
TargetEncoding
::
Ch
*
)
head
;
success
=
(
isKey
?
handler
.
Key
(
str
,
SizeType
(
length
),
false
)
:
handler
.
String
(
str
,
SizeType
(
length
),
false
));
}
else
{
StackStream
<
typename
TargetEncoding
::
Ch
>
stackStream
(
stack_
);
ParseStringToStream
<
parseFlags
,
SourceEncoding
,
TargetEncoding
>
(
s
,
stackStream
);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID
;
size_t
length
=
stackStream
.
Length
()
;
if
(
!
handler
.
String
(
stackStream
.
Pop
(),
SizeType
(
length
-
1
),
true
))
RAPIDJSON_PARSE_ERROR
(
kParseErrorTermination
,
s
.
Tell
(
));
SizeType
length
=
static_cast
<
SizeType
>
(
stackStream
.
Length
())
-
1
;
const
typename
TargetEncoding
::
Ch
*
const
str
=
stackStream
.
Pop
();
success
=
(
isKey
?
handler
.
Key
(
str
,
length
,
true
)
:
handler
.
String
(
str
,
length
,
true
));
}
if
(
!
success
)
RAPIDJSON_PARSE_ERROR
(
kParseErrorTermination
,
s
.
Tell
());
}
// Parse string to an output is
...
...
@@ -712,29 +722,35 @@ private:
}
template
<
typename
InputStream
,
bool
backup
>
class
NumberStream
{
class
NumberStream
{};
template
<
typename
InputStream
>
class
NumberStream
<
InputStream
,
false
>
{
public
:
NumberStream
(
GenericReader
&
reader
,
InputStream
&
is
)
:
reader
(
reader
),
is
(
is
)
{}
NumberStream
(
GenericReader
&
reader
,
InputStream
&
is
)
:
is
(
is
)
{
(
void
)
reader
;
}
~
NumberStream
()
{}
Ch
Peek
()
{
return
is
.
Peek
();
}
Ch
Take
()
{
return
is
.
Take
();
}
size_t
Tell
()
{
return
is
.
Tell
();
}
const
char
*
Pop
()
{
return
0
;
}
pr
ivate
:
pr
otected
:
NumberStream
&
operator
=
(
const
NumberStream
&
);
GenericReader
&
reader
;
InputStream
&
is
;
};
template
<
typename
InputStream
>
struct
NumberStream
<
InputStream
,
true
>
{
class
NumberStream
<
InputStream
,
true
>
:
public
NumberStream
<
InputStream
,
false
>
{
typedef
NumberStream
<
InputStream
,
false
>
Base
;
public
:
NumberStream
(
GenericReader
&
reader
,
InputStream
&
is
)
:
reader
(
reader
),
is
(
is
),
stackStream
(
reader
.
stack_
)
{}
NumberStream
(
GenericReader
&
reader
,
InputStream
&
is
)
:
NumberStream
<
InputStream
,
false
>
(
reader
,
is
),
stackStream
(
reader
.
stack_
)
{}
~
NumberStream
()
{}
Ch
Take
()
{
stackStream
.
Put
((
char
)
is
.
Peek
());
return
is
.
Take
();
stackStream
.
Put
((
char
)
Base
::
is
.
Peek
());
return
Base
::
is
.
Take
();
}
const
char
*
Pop
()
{
...
...
@@ -743,15 +759,22 @@ private:
}
private
:
GenericReader
&
reader
;
InputStream
&
is
;
StackStream
<
char
>
stackStream
;
};
double
StrtodFastPath
(
double
significand
,
int
exp
)
{
if
(
exp
<
-
308
)
return
0
.
0
;
else
if
(
exp
>=
0
)
return
significand
*
internal
::
Pow10
(
exp
);
else
return
significand
/
internal
::
Pow10
(
-
exp
);
}
template
<
unsigned
parseFlags
,
typename
InputStream
,
typename
Handler
>
void
ParseNumber
(
InputStream
&
is
,
Handler
&
handler
)
{
internal
::
StreamLocalCopy
<
InputStream
>
copy
(
is
);
NumberStream
<
InputStream
,
parseFlags
&
kParseFullPrecisionFlag
>
s
(
*
this
,
copy
.
s
);
NumberStream
<
InputStream
,
(
parseFlags
&
kParseFullPrecisionFlag
)
!=
0
>
s
(
*
this
,
copy
.
s
);
// Parse minus
bool
minus
=
false
;
...
...
@@ -800,11 +823,13 @@ private:
// Parse 64bit int
bool
useDouble
=
false
;
bool
useStrtod
=
false
;
double
d
=
0
.
0
;
if
(
use64bit
)
{
if
(
minus
)
while
(
s
.
Peek
()
>=
'0'
&&
s
.
Peek
()
<=
'9'
)
{
if
(
i64
>=
RAPIDJSON_UINT64_C2
(
0x0CCCCCCC
,
0xCCCCCCCC
))
// 2^63 = 9223372036854775808
if
(
i64
!=
RAPIDJSON_UINT64_C2
(
0x0CCCCCCC
,
0xCCCCCCCC
)
||
s
.
Peek
()
>
'8'
)
{
d
=
i64
;
useDouble
=
true
;
break
;
}
...
...
@@ -814,6 +839,7 @@ private:
while
(
s
.
Peek
()
>=
'0'
&&
s
.
Peek
()
<=
'9'
)
{
if
(
i64
>=
RAPIDJSON_UINT64_C2
(
0x19999999
,
0x99999999
))
// 2^64 - 1 = 18446744073709551615
if
(
i64
!=
RAPIDJSON_UINT64_C2
(
0x19999999
,
0x99999999
)
||
s
.
Peek
()
>
'5'
)
{
d
=
i64
;
useDouble
=
true
;
break
;
}
...
...
@@ -823,9 +849,18 @@ private:
// Force double for big integer
if
(
useDouble
)
{
while
(
s
.
Peek
()
>=
'0'
&&
s
.
Peek
()
<=
'9'
)
s
.
Take
();
useStrtod
=
true
;
if
(
parseFlags
&
kParseFullPrecisionFlag
)
{
while
(
s
.
Peek
()
>=
'0'
&&
s
.
Peek
()
<=
'9'
)
s
.
Take
();
useStrtod
=
true
;
}
else
{
while
(
s
.
Peek
()
>=
'0'
&&
s
.
Peek
()
<=
'9'
)
{
if
(
d
>=
1.7976931348623157e307
)
// DBL_MAX / 10.0
RAPIDJSON_PARSE_ERROR
(
kParseErrorNumberTooBig
,
s
.
Tell
());
d
=
d
*
10
+
(
s
.
Take
()
-
'0'
);
}
}
}
// Parse frac = decimal-point 1*DIGIT
...
...
@@ -834,27 +869,28 @@ private:
s
.
Take
();
if
(
!
useDouble
)
{
if
(
!
use64bit
)
{
i64
=
i
;
use64bit
=
true
;
}
d
=
use64bit
?
i64
:
i
;
useDouble
=
true
;
while
(
s
.
Peek
()
>=
'0'
&&
s
.
Peek
()
<=
'9'
)
{
if
(
i64
>=
RAPIDJSON_UINT64_C2
(
0x19999999
,
0x99999999
))
{
useStrtod
=
true
;
if
(
d
>=
9007199254740991
.
0
)
{
if
(
parseFlags
&
kParseFullPrecisionFlag
)
useStrtod
=
true
;
break
;
}
else
{
i64
=
i64
*
1
0
+
static_cast
<
unsigned
>
(
s
.
Take
()
-
'0'
);
d
=
d
*
10
.
0
+
static_cast
<
unsigned
>
(
s
.
Take
()
-
'0'
);
--
expFrac
;
}
}
}
useDouble
=
true
;
while
(
s
.
Peek
()
>=
'0'
&&
s
.
Peek
()
<=
'9'
)
{
s
.
Take
();
//s.Take();
if
(
parseFlags
&
kParseFullPrecisionFlag
)
s
.
Take
();
else
d
=
d
*
10
+
(
s
.
Take
()
-
'0'
);
--
expFrac
;
}
...
...
@@ -865,7 +901,10 @@ private:
// Parse exp = e [ minus / plus ] 1*DIGIT
int
exp
=
0
;
if
(
s
.
Peek
()
==
'e'
||
s
.
Peek
()
==
'E'
)
{
useDouble
=
true
;
if
(
!
useDouble
)
{
d
=
use64bit
?
i64
:
i
;
useDouble
=
true
;
}
s
.
Take
();
bool
expMinus
=
false
;
...
...
@@ -893,43 +932,48 @@ private:
// Finish parsing, call event according to the type of number.
bool
cont
=
true
;
// Pop stack no matter if it will be used or not.
const
char
*
str
=
s
.
Pop
();
const
char
*
str
=
s
.
Pop
();
// Pop stack no matter if it will be used or not.
if
(
useDouble
)
{
int
p
=
exp
+
expFrac
;
double
d
;
double
significand
=
use64bit
?
i64
:
i
;
// Use fast path for string-to-double conversion if possible
// see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
if
(
!
useStrtod
&&
p
>
22
)
{
if
(
p
<
22
+
16
)
{
// Fast Path Cases In Disguise
significand
*=
internal
::
Pow10
(
p
-
22
);
p
=
22
;
if
(
parseFlags
&
kParseFullPrecisionFlag
)
{
// Use fast path for string-to-double conversion if possible
// see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
if
(
!
useStrtod
&&
p
>
22
)
{
if
(
p
<
22
+
16
)
{
// Fast Path Cases In Disguise
d
*=
internal
::
Pow10
(
p
-
22
);
p
=
22
;
}
else
useStrtod
=
true
;
}
else
useStrtod
=
true
;
}
if
(
!
useStrtod
&&
p
>=
-
22
&&
significand
<=
9007199254740991
.
0
)
{
// 2^53 - 1
if
(
p
>=
0
)
d
=
significand
*
internal
::
Pow10
(
p
);
else
d
=
significand
/
internal
::
Pow10
(
-
p
);
if
(
minus
)
d
=
-
d
;
if
(
!
useStrtod
&&
p
>=
-
22
&&
d
<=
9007199254740991
.
0
)
{
// 2^53 - 1
d
=
StrtodFastPath
(
d
,
p
);
if
(
minus
)
d
=
-
d
;
}
else
{
char
*
end
=
0
;
d
=
strtod
(
str
,
&
end
);
RAPIDJSON_ASSERT
(
*
end
==
'\0'
);
// Should have consumed the whole string.
if
(
d
==
HUGE_VAL
||
d
==
-
HUGE_VAL
)
RAPIDJSON_PARSE_ERROR
(
kParseErrorNumberTooBig
,
s
.
Tell
());
}
}
else
{
char
*
end
=
0
;
d
=
strtod
(
str
,
&
end
);
RAPIDJSON_ASSERT
(
*
end
==
'\0'
);
// Should have consumed the whole string.
if
(
p
<
-
308
)
{
// Prevent expSum < -308, making Pow10(p) = 0
d
=
StrtodFastPath
(
d
,
exp
);
d
=
StrtodFastPath
(
d
,
expFrac
);
}
else
d
=
StrtodFastPath
(
d
,
p
);
if
(
d
==
HUGE_VAL
||
d
==
-
HUGE_VAL
)
RAPIDJSON_PARSE_ERROR
(
kParseErrorNumberTooBig
,
s
.
Tell
());
if
(
minus
)
d
=
-
d
;
}
cont
=
handler
.
Double
(
d
);
}
...
...
@@ -1247,7 +1291,7 @@ private:
}
case
IterativeParsingMemberKeyState
:
ParseString
<
parseFlags
>
(
is
,
handler
);
ParseString
<
parseFlags
>
(
is
,
handler
,
true
);
if
(
HasParseError
())
return
IterativeParsingErrorState
;
else
...
...
@@ -1410,6 +1454,10 @@ typedef GenericReader<UTF8<>, UTF8<> > Reader;
}
// namespace rapidjson
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
#endif
#ifdef _MSC_VER
RAPIDJSON_DIAG_POP
#endif
...
...
include/rapidjson/writer.h
View file @
881c91d6
...
...
@@ -131,6 +131,8 @@ public:
return
WriteStartObject
();
}
bool
Key
(
const
Ch
*
str
,
SizeType
length
,
bool
copy
=
false
)
{
return
String
(
str
,
length
,
copy
);
}
bool
EndObject
(
SizeType
memberCount
=
0
)
{
(
void
)
memberCount
;
RAPIDJSON_ASSERT
(
level_stack_
.
GetSize
()
>=
sizeof
(
Level
));
...
...
@@ -165,6 +167,7 @@ public:
//! Simpler but slower overload.
bool
String
(
const
Ch
*
str
)
{
return
String
(
str
,
internal
::
StrLen
(
str
));
}
bool
Key
(
const
Ch
*
str
)
{
return
Key
(
str
,
internal
::
StrLen
(
str
));
}
//@}
...
...
test/unittest/readertest.cpp
View file @
881c91d6
...
...
@@ -103,8 +103,8 @@ struct ParseDoubleHandler : BaseReaderHandler<UTF8<>, ParseDoubleHandler> {
double
actual_
;
};
TEST
(
Reader
,
ParseNumber
Handl
er
)
{
#define TEST_
NUMB
ER(Handler, str, x) \
TEST
(
Reader
,
ParseNumber
_Integ
er
)
{
#define TEST_
INTEG
ER(Handler, str, x) \
{
\
StringStream
s
(
str
);
\
Handler
h
;
\
...
...
@@ -114,67 +114,19 @@ TEST(Reader, ParseNumberHandler) {
EXPECT_EQ
(
double
(
x
),
h
.
actual_
);
\
}
#define TEST_DOUBLE(str, x) \
{
\
StringStream
s
(
str
);
\
ParseDoubleHandler
h
;
\
Reader
reader
;
\
reader
.
Parse
(
s
,
h
);
\
EXPECT_EQ
(
1u
,
h
.
step_
);
\
EXPECT_EQ
(
x
,
h
.
actual_
);
\
if
(
x
!=
h
.
actual_
)
\
printf
(
" Actual: %.17g
\n
Expected: %.17g
\n
"
,
h
.
actual_
,
x
);
\
}
TEST_INTEGER
(
ParseUintHandler
,
"0"
,
0
);
TEST_INTEGER
(
ParseUintHandler
,
"123"
,
123
);
TEST_INTEGER
(
ParseUintHandler
,
"2147483648"
,
2147483648u
);
// 2^31 - 1 (cannot be stored in int)
TEST_INTEGER
(
ParseUintHandler
,
"4294967295"
,
4294967295u
);
TEST_NUMBER
(
ParseUintHandler
,
"0"
,
0
);
TEST_NUMBER
(
ParseUintHandler
,
"123"
,
123
);
TEST_NUMBER
(
ParseUintHandler
,
"2147483648"
,
2147483648u
);
// 2^31 - 1 (cannot be stored in int)
TEST_NUMBER
(
ParseUintHandler
,
"4294967295"
,
4294967295u
);
TEST_NUMBER
(
ParseIntHandler
,
"-123"
,
-
123
);
TEST_NUMBER
(
ParseIntHandler
,
"-2147483648"
,
-
2147483648LL
);
// -2^31 (min of int)
TEST_NUMBER
(
ParseUint64Handler
,
"4294967296"
,
4294967296ULL
);
// 2^32 (max of unsigned + 1, force to use uint64_t)
TEST_NUMBER
(
ParseUint64Handler
,
"18446744073709551615"
,
18446744073709551615ULL
);
// 2^64 - 1 (max of uint64_t)
TEST_NUMBER
(
ParseInt64Handler
,
"-2147483649"
,
-
2147483649LL
);
// -2^31 -1 (min of int - 1, force to use int64_t)
TEST_NUMBER
(
ParseInt64Handler
,
"-9223372036854775808"
,
(
-
9223372036854775807LL
-
1
));
// -2^63 (min of int64_t)
TEST_DOUBLE
(
"0.0"
,
0.0
);
TEST_DOUBLE
(
"1.0"
,
1.0
);
TEST_DOUBLE
(
"-1.0"
,
-
1.0
);
TEST_DOUBLE
(
"1.5"
,
1.5
);
TEST_DOUBLE
(
"-1.5"
,
-
1.5
);
TEST_DOUBLE
(
"3.1416"
,
3.1416
);
TEST_DOUBLE
(
"1E10"
,
1E10
);
TEST_DOUBLE
(
"1e10"
,
1e10
);
TEST_DOUBLE
(
"1E+10"
,
1E+10
);
TEST_DOUBLE
(
"1E-10"
,
1E-10
);
TEST_DOUBLE
(
"-1E10"
,
-
1E10
);
TEST_DOUBLE
(
"-1e10"
,
-
1e10
);
TEST_DOUBLE
(
"-1E+10"
,
-
1E+10
);
TEST_DOUBLE
(
"-1E-10"
,
-
1E-10
);
TEST_DOUBLE
(
"1.234E+10"
,
1.234E+10
);
TEST_DOUBLE
(
"1.234E-10"
,
1.234E-10
);
TEST_DOUBLE
(
"1.79769e+308"
,
1.79769e+308
);
TEST_DOUBLE
(
"2.22507e-308"
,
2.22507e-308
);
TEST_DOUBLE
(
"-1.79769e+308"
,
-
1.79769e+308
);
TEST_DOUBLE
(
"-2.22507e-308"
,
-
2.22507e-308
);
TEST_DOUBLE
(
"4.9406564584124654e-324"
,
4.9406564584124654e-324
);
// minimum denormal
TEST_DOUBLE
(
"1e-10000"
,
0.0
);
// must underflow
TEST_DOUBLE
(
"18446744073709551616"
,
18446744073709551616.0
);
// 2^64 (max of uint64_t + 1, force to use double)
TEST_DOUBLE
(
"-9223372036854775809"
,
-
9223372036854775809.0
);
// -2^63 - 1(min of int64_t + 1, force to use double)
TEST_DOUBLE
(
"0.9868011474609375"
,
0.9868011474609375
);
// https://github.com/miloyip/rapidjson/issues/120
TEST_DOUBLE
(
"123e34"
,
123e34
);
// Fast Path Cases In Disguise
TEST_INTEGER
(
ParseIntHandler
,
"-123"
,
-
123
);
TEST_INTEGER
(
ParseIntHandler
,
"-2147483648"
,
-
2147483648LL
);
// -2^31 (min of int)
{
char
n1e308
[
310
];
// '1' followed by 308 '0'
n1e308
[
0
]
=
'1'
;
for
(
int
i
=
1
;
i
<
309
;
i
++
)
n1e308
[
i
]
=
'0'
;
n1e308
[
309
]
=
'\0'
;
TEST_DOUBLE
(
n1e308
,
1E308
);
}
TEST_INTEGER
(
ParseUint64Handler
,
"4294967296"
,
4294967296ULL
);
// 2^32 (max of unsigned + 1, force to use uint64_t)
TEST_INTEGER
(
ParseUint64Handler
,
"18446744073709551615"
,
18446744073709551615ULL
);
// 2^64 - 1 (max of uint64_t)
TEST_INTEGER
(
ParseInt64Handler
,
"-2147483649"
,
-
2147483649LL
);
// -2^31 -1 (min of int - 1, force to use int64_t)
TEST_INTEGER
(
ParseInt64Handler
,
"-9223372036854775808"
,
(
-
9223372036854775807LL
-
1
));
// -2^63 (min of int64_t)
// Random test for uint32_t/int32_t
{
...
...
@@ -189,11 +141,11 @@ TEST(Reader, ParseNumberHandler) {
char
buffer
[
32
];
*
internal
::
u32toa
(
u
.
u
,
buffer
)
=
'\0'
;
TEST_
NUMB
ER
(
ParseUintHandler
,
buffer
,
u
.
u
);
TEST_
INTEG
ER
(
ParseUintHandler
,
buffer
,
u
.
u
);
if
(
u
.
i
<
0
)
{
*
internal
::
i32toa
(
u
.
i
,
buffer
)
=
'\0'
;
TEST_
NUMB
ER
(
ParseIntHandler
,
buffer
,
u
.
i
);
TEST_
INTEG
ER
(
ParseIntHandler
,
buffer
,
u
.
i
);
}
}
}
...
...
@@ -213,41 +165,109 @@ TEST(Reader, ParseNumberHandler) {
char
buffer
[
32
];
if
(
u
.
u
>=
4294967296ULL
)
{
*
internal
::
u64toa
(
u
.
u
,
buffer
)
=
'\0'
;
TEST_
NUMB
ER
(
ParseUint64Handler
,
buffer
,
u
.
u
);
TEST_
INTEG
ER
(
ParseUint64Handler
,
buffer
,
u
.
u
);
}
if
(
u
.
i
<=
-
2147483649LL
)
{
*
internal
::
i64toa
(
u
.
i
,
buffer
)
=
'\0'
;
TEST_
NUMB
ER
(
ParseInt64Handler
,
buffer
,
u
.
i
);
TEST_
INTEG
ER
(
ParseInt64Handler
,
buffer
,
u
.
i
);
}
}
}
#undef TEST_INTEGER
}
// Random test for double
{
union
{
double
d
;
uint64_t
u
;
}
u
;
Random
r
;
template
<
bool
fullPrecision
>
static
void
TestParseDouble
()
{
#define TEST_DOUBLE(fullPrecision, str, x) \
{
\
StringStream
s
(
str
);
\
ParseDoubleHandler
h
;
\
Reader
reader
;
\
reader
.
Parse
<
fullPrecision
?
kParseFullPrecisionFlag
:
0
>
(
s
,
h
);
\
EXPECT_EQ
(
1u
,
h
.
step_
);
\
if
(
fullPrecision
)
{
\
EXPECT_EQ
(
x
,
h
.
actual_
);
\
if
(
x
!=
h
.
actual_
)
\
printf
(
" String: %s
\n
Actual: %.17g
\n
Expected: %.17g
\n
"
,
str
,
h
.
actual_
,
x
);
\
}
\
else
\
EXPECT_DOUBLE_EQ
(
x
,
h
.
actual_
);
\
}
for
(
unsigned
i
=
0
;
i
<
100000
;
i
++
)
{
do
{
// Need to call r() in two statements for cross-platform coherent sequence.
u
.
u
=
uint64_t
(
r
())
<<
32
;
u
.
u
|=
uint64_t
(
r
());
}
while
(
isnan
(
u
.
d
)
||
isinf
(
u
.
d
));
TEST_DOUBLE
(
fullPrecision
,
"0.0"
,
0.0
);
TEST_DOUBLE
(
fullPrecision
,
"1.0"
,
1.0
);
TEST_DOUBLE
(
fullPrecision
,
"-1.0"
,
-
1.0
);
TEST_DOUBLE
(
fullPrecision
,
"1.5"
,
1.5
);
TEST_DOUBLE
(
fullPrecision
,
"-1.5"
,
-
1.5
);
TEST_DOUBLE
(
fullPrecision
,
"3.1416"
,
3.1416
);
TEST_DOUBLE
(
fullPrecision
,
"1E10"
,
1E10
);
TEST_DOUBLE
(
fullPrecision
,
"1e10"
,
1e10
);
TEST_DOUBLE
(
fullPrecision
,
"1E+10"
,
1E+10
);
TEST_DOUBLE
(
fullPrecision
,
"1E-10"
,
1E-10
);
TEST_DOUBLE
(
fullPrecision
,
"-1E10"
,
-
1E10
);
TEST_DOUBLE
(
fullPrecision
,
"-1e10"
,
-
1e10
);
TEST_DOUBLE
(
fullPrecision
,
"-1E+10"
,
-
1E+10
);
TEST_DOUBLE
(
fullPrecision
,
"-1E-10"
,
-
1E-10
);
TEST_DOUBLE
(
fullPrecision
,
"1.234E+10"
,
1.234E+10
);
TEST_DOUBLE
(
fullPrecision
,
"1.234E-10"
,
1.234E-10
);
TEST_DOUBLE
(
fullPrecision
,
"1.79769e+308"
,
1.79769e+308
);
TEST_DOUBLE
(
fullPrecision
,
"2.22507e-308"
,
2.22507e-308
);
TEST_DOUBLE
(
fullPrecision
,
"-1.79769e+308"
,
-
1.79769e+308
);
TEST_DOUBLE
(
fullPrecision
,
"-2.22507e-308"
,
-
2.22507e-308
);
TEST_DOUBLE
(
fullPrecision
,
"4.9406564584124654e-324"
,
4.9406564584124654e-324
);
// minimum denormal
TEST_DOUBLE
(
fullPrecision
,
"1e-10000"
,
0.0
);
// must underflow
TEST_DOUBLE
(
fullPrecision
,
"18446744073709551616"
,
18446744073709551616.0
);
// 2^64 (max of uint64_t + 1, force to use double)
TEST_DOUBLE
(
fullPrecision
,
"-9223372036854775809"
,
-
9223372036854775809.0
);
// -2^63 - 1(min of int64_t + 1, force to use double)
TEST_DOUBLE
(
fullPrecision
,
"0.9868011474609375"
,
0.9868011474609375
);
// https://github.com/miloyip/rapidjson/issues/120
TEST_DOUBLE
(
fullPrecision
,
"123e34"
,
123e34
);
// Fast Path Cases In Disguise
{
char
n1e308
[
310
];
// '1' followed by 308 '0'
n1e308
[
0
]
=
'1'
;
for
(
int
i
=
1
;
i
<
309
;
i
++
)
n1e308
[
i
]
=
'0'
;
n1e308
[
309
]
=
'\0'
;
TEST_DOUBLE
(
fullPrecision
,
n1e308
,
1E308
);
}
char
buffer
[
32
];
*
internal
::
dtoa
(
u
.
d
,
buffer
)
=
'\0'
;
TEST_DOUBLE
(
buffer
,
u
.
d
);
}
// Random test for double
{
union
{
double
d
;
uint64_t
u
;
}
u
;
Random
r
;
for
(
unsigned
i
=
0
;
i
<
100000
;
i
++
)
{
do
{
// Need to call r() in two statements for cross-platform coherent sequence.
u
.
u
=
uint64_t
(
r
())
<<
32
;
u
.
u
|=
uint64_t
(
r
());
}
while
(
std
::
isnan
(
u
.
d
)
||
std
::
isinf
(
u
.
d
)
#ifdef _MSC_VER
// VC's strtod() has problem with denormal numbers
||
!
std
::
isnormal
(
u
.
d
)
#endif
);
char
buffer
[
32
];
*
internal
::
dtoa
(
u
.
d
,
buffer
)
=
'\0'
;
TEST_DOUBLE
(
fullPrecision
,
buffer
,
u
.
d
);
}
}
#undef TEST_NUMBER
#undef TEST_DOUBLE
}
TEST
(
Reader
,
ParseNumber_NormalPrecisionDouble
)
{
TestParseDouble
<
false
>
();
}
TEST
(
Reader
,
ParseNumber_FullPrecisionDouble
)
{
TestParseDouble
<
true
>
();
}
TEST
(
Reader
,
ParseNumber_Error
)
{
#define TEST_NUMBER_ERROR(errorCode, str) \
{
\
...
...
@@ -894,9 +914,10 @@ struct IterativeParsingReaderHandler {
const
static
int
LOG_DOUBLE
=
-
7
;
const
static
int
LOG_STRING
=
-
8
;
const
static
int
LOG_STARTOBJECT
=
-
9
;
const
static
int
LOG_ENDOBJECT
=
-
10
;
const
static
int
LOG_STARTARRAY
=
-
11
;
const
static
int
LOG_ENDARRAY
=
-
12
;
const
static
int
LOG_KEY
=
-
10
;
const
static
int
LOG_ENDOBJECT
=
-
11
;
const
static
int
LOG_STARTARRAY
=
-
12
;
const
static
int
LOG_ENDARRAY
=
-
13
;
const
static
size_t
LogCapacity
=
256
;
int
Logs
[
LogCapacity
];
...
...
@@ -923,6 +944,8 @@ struct IterativeParsingReaderHandler {
bool
StartObject
()
{
RAPIDJSON_ASSERT
(
LogCount
<
LogCapacity
);
Logs
[
LogCount
++
]
=
LOG_STARTOBJECT
;
return
true
;
}
bool
Key
(
const
Ch
*
,
SizeType
,
bool
)
{
RAPIDJSON_ASSERT
(
LogCount
<
LogCapacity
);
Logs
[
LogCount
++
]
=
LOG_KEY
;
return
true
;
}
bool
EndObject
(
SizeType
c
)
{
RAPIDJSON_ASSERT
(
LogCount
<
LogCapacity
);
Logs
[
LogCount
++
]
=
LOG_ENDOBJECT
;
...
...
@@ -955,7 +978,7 @@ TEST(Reader, IterativeParsing_General) {
handler
.
LOG_STARTARRAY
,
handler
.
LOG_INT
,
handler
.
LOG_STARTOBJECT
,
handler
.
LOG_
STRING
,
handler
.
LOG_
KEY
,
handler
.
LOG_STARTARRAY
,
handler
.
LOG_INT
,
handler
.
LOG_INT
,
...
...
@@ -993,7 +1016,7 @@ TEST(Reader, IterativeParsing_Count) {
handler
.
LOG_STARTOBJECT
,
handler
.
LOG_ENDOBJECT
,
0
,
handler
.
LOG_STARTOBJECT
,
handler
.
LOG_
STRING
,
handler
.
LOG_
KEY
,
handler
.
LOG_INT
,
handler
.
LOG_ENDOBJECT
,
1
,
handler
.
LOG_STARTARRAY
,
...
...
test/unittest/unittest.h
View file @
881c91d6
...
...
@@ -89,15 +89,9 @@ inline FILE* TempFile(char *filename) {
#pragma warning(disable : 4127)
#endif
class
AssertException
:
public
std
::
exception
{
class
AssertException
:
public
std
::
logic_error
{
public
:
AssertException
(
const
char
*
w
)
:
what_
(
w
)
{}
AssertException
(
const
AssertException
&
other
)
:
what_
(
other
.
what_
)
{}
AssertException
&
operator
=
(
const
AssertException
&
rhs
)
{
what_
=
rhs
.
what_
;
return
*
this
;
}
virtual
const
char
*
what
()
const
throw
()
{
return
what_
;
}
private
:
const
char
*
what_
;
AssertException
(
const
char
*
w
)
:
std
::
logic_error
(
w
)
{}
};
#define RAPIDJSON_ASSERT(x) if (!(x)) throw AssertException(RAPIDJSON_STRINGIFY(x))
...
...
test/unittest/valuetest.cpp
View file @
881c91d6
...
...
@@ -24,7 +24,7 @@
using
namespace
rapidjson
;
TEST
(
Value
,
default_c
onstructor
)
{
TEST
(
Value
,
DefaultC
onstructor
)
{
Value
x
;
EXPECT_EQ
(
kNullType
,
x
.
GetType
());
EXPECT_TRUE
(
x
.
IsNull
());
...
...
@@ -38,7 +38,32 @@ TEST(Value, default_constructor) {
// Value y = x;
//}
TEST
(
Value
,
assignment_operator
)
{
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
TEST
(
Value
,
MoveConstructor
)
{
typedef
GenericValue
<
UTF8
<>
,
CrtAllocator
>
Value
;
Value
::
AllocatorType
allocator
;
Value
x
((
Value
(
kArrayType
)));
x
.
Reserve
(
4u
,
allocator
);
x
.
PushBack
(
1
,
allocator
).
PushBack
(
2
,
allocator
).
PushBack
(
3
,
allocator
).
PushBack
(
4
,
allocator
);
EXPECT_TRUE
(
x
.
IsArray
());
EXPECT_EQ
(
4u
,
x
.
Size
());
// Value y(x); // should not compile
Value
y
(
std
::
move
(
x
));
EXPECT_TRUE
(
x
.
IsNull
());
EXPECT_TRUE
(
y
.
IsArray
());
EXPECT_EQ
(
4u
,
y
.
Size
());
// Value z = y; // should not compile
Value
z
=
std
::
move
(
y
);
EXPECT_TRUE
(
y
.
IsNull
());
EXPECT_TRUE
(
z
.
IsArray
());
EXPECT_EQ
(
4u
,
z
.
Size
());
}
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
TEST
(
Value
,
AssignmentOperator
)
{
Value
x
(
1234
);
Value
y
;
y
=
x
;
...
...
@@ -63,6 +88,22 @@ TEST(Value, assignment_operator) {
y
=
StringRef
(
mstr
);
EXPECT_TRUE
(
y
.
IsString
());
EXPECT_EQ
(
y
.
GetString
(),
mstr
);
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
// C++11 move assignment
x
=
Value
(
"World"
);
EXPECT_TRUE
(
x
.
IsString
());
EXPECT_STREQ
(
"World"
,
x
.
GetString
());
x
=
std
::
move
(
y
);
EXPECT_TRUE
(
y
.
IsNull
());
EXPECT_TRUE
(
x
.
IsString
());
EXPECT_EQ
(
x
.
GetString
(),
mstr
);
y
=
std
::
move
(
Value
().
SetInt
(
1234
));
EXPECT_TRUE
(
y
.
IsInt
());
EXPECT_EQ
(
1234
,
y
);
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
}
template
<
typename
A
,
typename
B
>
...
...
@@ -81,7 +122,7 @@ void TestUnequal(const A& a, const B& b) {
EXPECT_TRUE
(
b
!=
a
);
}
TEST
(
Value
,
equalto_o
perator
)
{
TEST
(
Value
,
EqualtoO
perator
)
{
Value
::
AllocatorType
allocator
;
Value
x
(
kObjectType
);
x
.
AddMember
(
"hello"
,
"world"
,
allocator
)
...
...
@@ -105,16 +146,33 @@ TEST(Value, equalto_operator) {
TestEqual
(
x
[
"i"
],
123
);
TestEqual
(
x
[
"pi"
],
3.14
);
// Test operator==()
Value
y
;
y
.
CopyFrom
(
x
,
allocator
);
// Test operator==() (including different allocators)
CrtAllocator
crtAllocator
;
GenericValue
<
UTF8
<>
,
CrtAllocator
>
y
;
GenericDocument
<
UTF8
<>
,
CrtAllocator
>
z
(
&
crtAllocator
);
y
.
CopyFrom
(
x
,
crtAllocator
);
z
.
CopyFrom
(
y
,
z
.
GetAllocator
());
TestEqual
(
x
,
y
);
TestEqual
(
y
,
z
);
TestEqual
(
z
,
x
);
// Swapping member order should be fine.
y
.
RemoveMember
(
"t"
);
EXPECT_TRUE
(
y
.
RemoveMember
(
"t"
)
);
TestUnequal
(
x
,
y
);
y
.
AddMember
(
"t"
,
Value
(
true
).
Move
(),
allocator
);
TestUnequal
(
z
,
y
);
EXPECT_TRUE
(
z
.
RemoveMember
(
"t"
));
TestUnequal
(
x
,
z
);
TestEqual
(
y
,
z
);
y
.
AddMember
(
"t"
,
true
,
crtAllocator
);
z
.
AddMember
(
"t"
,
true
,
z
.
GetAllocator
());
TestEqual
(
x
,
y
);
TestEqual
(
y
,
z
);
TestEqual
(
z
,
x
);
// Issue #129: compare Uint64
x
.
SetUint64
(
RAPIDJSON_UINT64_C2
(
0xFFFFFFFF
,
0xFFFFFFF0
));
y
.
SetUint64
(
RAPIDJSON_UINT64_C2
(
0xFFFFFFFF
,
0xFFFFFFFF
));
TestUnequal
(
x
,
y
);
}
template
<
typename
Value
>
...
...
@@ -538,7 +596,7 @@ TEST(Value, String) {
EXPECT_STREQ
(
"World"
,
w
.
GetString
());
EXPECT_EQ
(
5u
,
w
.
GetStringLength
());
#if
def
RAPIDJSON_HAS_STDSTRING
#if RAPIDJSON_HAS_STDSTRING
{
std
::
string
str
=
"Hello World"
;
str
[
5
]
=
'\0'
;
...
...
@@ -626,6 +684,21 @@ TEST(Value, Array) {
EXPECT_TRUE
(
y
[
4u
].
IsString
());
EXPECT_STREQ
(
"foo"
,
y
[
4u
].
GetString
());
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
// PushBack(GenericValue&&, Allocator&);
{
Value
y
(
kArrayType
);
y
.
PushBack
(
Value
(
true
),
allocator
);
y
.
PushBack
(
std
::
move
(
Value
(
kArrayType
).
PushBack
(
Value
(
1
),
allocator
).
PushBack
(
"foo"
,
allocator
)),
allocator
);
EXPECT_EQ
(
2u
,
y
.
Size
());
EXPECT_TRUE
(
y
[
0u
].
IsTrue
());
EXPECT_TRUE
(
y
[
1u
].
IsArray
());
EXPECT_EQ
(
2u
,
y
[
1u
].
Size
());
EXPECT_TRUE
(
y
[
1u
][
0u
].
IsInt
());
EXPECT_TRUE
(
y
[
1u
][
1u
].
IsString
());
}
#endif
// iterator
Value
::
ValueIterator
itr
=
x
.
Begin
();
EXPECT_TRUE
(
itr
!=
x
.
End
());
...
...
@@ -734,7 +807,6 @@ TEST(Value, Array) {
}
// Working in gcc without C++11, but VS2013 cannot compile. To be diagnosed.
#if 0
// http://en.wikipedia.org/wiki/Erase-remove_idiom
x
.
Clear
();
for
(
int
i
=
0
;
i
<
10
;
i
++
)
...
...
@@ -743,11 +815,11 @@ TEST(Value, Array) {
else
x
.
PushBack
(
Value
(
kNullType
).
Move
(),
allocator
);
x.Erase(std::remove(x.Begin(), x.End(), Value(kNullType)), x.End());
const
Value
null
(
kNullType
);
x
.
Erase
(
std
::
remove
(
x
.
Begin
(),
x
.
End
(),
null
),
x
.
End
());
EXPECT_EQ
(
5u
,
x
.
Size
());
for
(
int
i
=
0
;
i
<
5
;
i
++
)
EXPECT_EQ
(
i
*
2
,
x
[
i
]);
#endif
// SetArray()
Value
z
;
...
...
@@ -801,6 +873,22 @@ TEST(Value, Object) {
EXPECT_EQ
(
8u
,
o
.
MemberCount
());
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
// AddMember(GenericValue&&, ...) variants
{
Value
o
(
kObjectType
);
o
.
AddMember
(
Value
(
"true"
),
Value
(
true
),
allocator
);
o
.
AddMember
(
Value
(
"false"
),
Value
(
false
).
Move
(),
allocator
);
// value is lvalue ref
o
.
AddMember
(
Value
(
"int"
).
Move
(),
Value
(
-
1
),
allocator
);
// name is lvalue ref
o
.
AddMember
(
"uint"
,
std
::
move
(
Value
().
SetUint
(
1u
)),
allocator
);
// name is literal, value is rvalue
EXPECT_TRUE
(
o
[
"true"
].
GetBool
());
EXPECT_FALSE
(
o
[
"false"
].
GetBool
());
EXPECT_EQ
(
-
1
,
o
[
"int"
].
GetInt
());
EXPECT_EQ
(
1u
,
o
[
"uint"
].
GetUint
());
EXPECT_EQ
(
4u
,
o
.
MemberCount
());
}
#endif
// Tests a member with null character
Value
name
;
const
Value
C0D
(
"C
\0
D"
,
3
);
...
...
@@ -818,10 +906,18 @@ TEST(Value, Object) {
EXPECT_TRUE
(
x
.
HasMember
(
name
));
EXPECT_TRUE
(
y
.
HasMember
(
name
));
GenericValue
<
UTF8
<>
,
CrtAllocator
>
othername
(
"A"
);
EXPECT_TRUE
(
x
.
HasMember
(
othername
));
EXPECT_TRUE
(
y
.
HasMember
(
othername
));
othername
.
SetString
(
"C
\0
D"
);
EXPECT_TRUE
(
x
.
HasMember
(
othername
));
EXPECT_TRUE
(
y
.
HasMember
(
othername
));
// operator[]
EXPECT_STREQ
(
"Apple"
,
x
[
"A"
].
GetString
());
EXPECT_STREQ
(
"Banana"
,
x
[
"B"
].
GetString
());
EXPECT_STREQ
(
"CherryD"
,
x
[
C0D
].
GetString
());
EXPECT_STREQ
(
"CherryD"
,
x
[
othername
].
GetString
());
// const operator[]
EXPECT_STREQ
(
"Apple"
,
y
[
"A"
].
GetString
());
...
...
@@ -892,7 +988,7 @@ TEST(Value, Object) {
x
.
RemoveMember
(
"B"
);
EXPECT_FALSE
(
x
.
HasMember
(
"B"
));
x
.
RemoveMember
(
name
);
x
.
RemoveMember
(
other
name
);
EXPECT_FALSE
(
x
.
HasMember
(
name
));
EXPECT_TRUE
(
x
.
MemberBegin
()
==
x
.
MemberEnd
());
...
...
@@ -905,11 +1001,14 @@ TEST(Value, Object) {
for
(
int
i
=
0
;
i
<
10
;
i
++
)
x
.
AddMember
(
keys
[
i
],
Value
(
kArrayType
).
PushBack
(
i
,
allocator
),
allocator
);
// MemberCount, iterator difference
EXPECT_EQ
(
x
.
MemberCount
(),
SizeType
(
x
.
MemberEnd
()
-
x
.
MemberBegin
()));
// Erase the first
itr
=
x
.
EraseMember
(
x
.
MemberBegin
());
EXPECT_FALSE
(
x
.
HasMember
(
keys
[
0
]));
EXPECT_EQ
(
x
.
MemberBegin
(),
itr
);
EXPECT_EQ
(
9
,
x
.
MemberEnd
()
-
x
.
MemberBegin
());
EXPECT_EQ
(
9
u
,
x
.
MemberCount
());
for
(;
itr
!=
x
.
MemberEnd
();
++
itr
)
{
int
i
=
(
itr
-
x
.
MemberBegin
())
+
1
;
EXPECT_STREQ
(
itr
->
name
.
GetString
(),
keys
[
i
]);
...
...
@@ -920,7 +1019,7 @@ TEST(Value, Object) {
itr
=
x
.
EraseMember
(
x
.
MemberEnd
()
-
1
);
EXPECT_FALSE
(
x
.
HasMember
(
keys
[
9
]));
EXPECT_EQ
(
x
.
MemberEnd
(),
itr
);
EXPECT_EQ
(
8
,
x
.
MemberEnd
()
-
x
.
MemberBegin
());
EXPECT_EQ
(
8
u
,
x
.
MemberCount
());
for
(;
itr
!=
x
.
MemberEnd
();
++
itr
)
{
int
i
=
(
itr
-
x
.
MemberBegin
())
+
1
;
EXPECT_STREQ
(
itr
->
name
.
GetString
(),
keys
[
i
]);
...
...
@@ -931,7 +1030,7 @@ TEST(Value, Object) {
itr
=
x
.
EraseMember
(
x
.
MemberBegin
()
+
4
);
EXPECT_FALSE
(
x
.
HasMember
(
keys
[
5
]));
EXPECT_EQ
(
x
.
MemberBegin
()
+
4
,
itr
);
EXPECT_EQ
(
7
,
x
.
MemberEnd
()
-
x
.
MemberBegin
());
EXPECT_EQ
(
7
u
,
x
.
MemberCount
());
for
(;
itr
!=
x
.
MemberEnd
();
++
itr
)
{
int
i
=
(
itr
-
x
.
MemberBegin
());
i
+=
(
i
<
4
)
?
1
:
2
;
...
...
@@ -955,7 +1054,7 @@ TEST(Value, Object) {
EXPECT_EQ
(
x
.
MemberBegin
()
+
first
,
itr
);
size_t
removeCount
=
last
-
first
;
EXPECT_EQ
(
n
-
removeCount
,
size_t
(
x
.
MemberEnd
()
-
x
.
MemberBegin
()
));
EXPECT_EQ
(
n
-
removeCount
,
x
.
MemberCount
(
));
for
(
unsigned
i
=
0
;
i
<
first
;
i
++
)
EXPECT_EQ
(
i
,
x
[
keys
[
i
]][
0u
].
GetUint
());
for
(
unsigned
i
=
first
;
i
<
n
-
removeCount
;
i
++
)
...
...
@@ -1059,3 +1158,23 @@ TEST(Document, CrtAllocator) {
V
a
(
kArrayType
);
a
.
PushBack
(
1
,
allocator
);
// Should not call destructor on uninitialized Value of newly allocated elements.
}
static
void
TestShortStringOptimization
(
const
char
*
str
)
{
const
rapidjson
::
SizeType
len
=
(
rapidjson
::
SizeType
)
strlen
(
str
);
rapidjson
::
Document
doc
;
rapidjson
::
Value
val
;
val
.
SetString
(
str
,
len
,
doc
.
GetAllocator
());
EXPECT_EQ
(
val
.
GetStringLength
(),
len
);
EXPECT_STREQ
(
val
.
GetString
(),
str
);
}
TEST
(
Value
,
AllocateShortString
)
{
TestShortStringOptimization
(
""
);
// edge case: empty string
TestShortStringOptimization
(
"12345678"
);
// regular case for short strings: 8 chars
TestShortStringOptimization
(
"12345678901"
);
// edge case: 11 chars in 32-bit mode (=> short string)
TestShortStringOptimization
(
"123456789012"
);
// edge case: 12 chars in 32-bit mode (=> regular string)
TestShortStringOptimization
(
"123456789012345"
);
// edge case: 15 chars in 64-bit mode (=> short string)
TestShortStringOptimization
(
"1234567890123456"
);
// edge case: 16 chars in 64-bit mode (=> regular string)
}
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