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
e731726c
Commit
e731726c
authored
Feb 15, 2016
by
Milo Yip
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Optimize memory consumption with RAPIDJSON_48BITPOINTER_OPTIMIZATION
#330
parent
90c0235f
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
200 additions
and
135 deletions
+200
-135
document.h
include/rapidjson/document.h
+156
-134
rapidjson.h
include/rapidjson/rapidjson.h
+32
-1
valuetest.cpp
test/unittest/valuetest.cpp
+12
-0
No files found.
include/rapidjson/document.h
View file @
e731726c
...
@@ -295,7 +295,7 @@ struct GenericStringRef {
...
@@ -295,7 +295,7 @@ struct GenericStringRef {
*/
*/
#endif
#endif
explicit
GenericStringRef
(
const
CharType
*
str
)
explicit
GenericStringRef
(
const
CharType
*
str
)
:
s
(
str
),
length
(
internal
::
StrLen
(
str
)){
RAPIDJSON_ASSERT
(
s
!=
NULL
);
}
:
s
(
str
),
length
(
internal
::
StrLen
(
str
)){
RAPIDJSON_ASSERT
(
s
!=
0
);
}
//! Create constant string reference from pointer and length
//! Create constant string reference from pointer and length
#ifndef __clang__ // -Wdocumentation
#ifndef __clang__ // -Wdocumentation
...
@@ -307,7 +307,7 @@ struct GenericStringRef {
...
@@ -307,7 +307,7 @@ struct GenericStringRef {
*/
*/
#endif
#endif
GenericStringRef
(
const
CharType
*
str
,
SizeType
len
)
GenericStringRef
(
const
CharType
*
str
,
SizeType
len
)
:
s
(
str
),
length
(
len
)
{
RAPIDJSON_ASSERT
(
s
!=
NULL
);
}
:
s
(
str
),
length
(
len
)
{
RAPIDJSON_ASSERT
(
s
!=
0
);
}
//! implicit conversion to plain CharType pointer
//! implicit conversion to plain CharType pointer
operator
const
Ch
*
()
const
{
return
s
;
}
operator
const
Ch
*
()
const
{
return
s
;
}
...
@@ -425,12 +425,12 @@ public:
...
@@ -425,12 +425,12 @@ public:
//@{
//@{
//! Default constructor creates a null value.
//! Default constructor creates a null value.
GenericValue
()
RAPIDJSON_NOEXCEPT
:
data_
()
,
flags_
(
kNullFlag
)
{
}
GenericValue
()
RAPIDJSON_NOEXCEPT
:
data_
()
{
data_
.
f
.
flags
=
kNullFlag
;
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Move constructor in C++11
//! Move constructor in C++11
GenericValue
(
GenericValue
&&
rhs
)
RAPIDJSON_NOEXCEPT
:
data_
(
rhs
.
data_
)
,
flags_
(
rhs
.
flags_
)
{
GenericValue
(
GenericValue
&&
rhs
)
RAPIDJSON_NOEXCEPT
:
data_
(
rhs
.
data_
)
{
rhs
.
flags_
=
kNullFlag
;
// give up contents
rhs
.
data_
.
f
.
flags
=
kNullFlag
;
// give up contents
}
}
#endif
#endif
...
@@ -455,13 +455,13 @@ public:
...
@@ -455,13 +455,13 @@ public:
\param type Type of the value.
\param type Type of the value.
\note Default content for number is zero.
\note Default content for number is zero.
*/
*/
explicit
GenericValue
(
Type
type
)
RAPIDJSON_NOEXCEPT
:
data_
()
,
flags_
()
{
explicit
GenericValue
(
Type
type
)
RAPIDJSON_NOEXCEPT
:
data_
()
{
static
const
u
nsigned
defaultFlags
[
7
]
=
{
static
const
u
int16_t
defaultFlags
[
7
]
=
{
kNullFlag
,
kFalseFlag
,
kTrueFlag
,
kObjectFlag
,
kArrayFlag
,
kShortStringFlag
,
kNullFlag
,
kFalseFlag
,
kTrueFlag
,
kObjectFlag
,
kArrayFlag
,
kShortStringFlag
,
kNumberAnyFlag
kNumberAnyFlag
};
};
RAPIDJSON_ASSERT
(
type
<=
kNumberType
);
RAPIDJSON_ASSERT
(
type
<=
kNumberType
);
flags_
=
defaultFlags
[
type
];
data_
.
f
.
flags
=
defaultFlags
[
type
];
// Use ShortString to store empty string.
// Use ShortString to store empty string.
if
(
type
==
kStringType
)
if
(
type
==
kStringType
)
...
@@ -490,70 +490,71 @@ public:
...
@@ -490,70 +490,71 @@ public:
#else
#else
explicit
GenericValue
(
bool
b
)
RAPIDJSON_NOEXCEPT
explicit
GenericValue
(
bool
b
)
RAPIDJSON_NOEXCEPT
#endif
#endif
:
data_
()
,
flags_
(
b
?
kTrueFlag
:
kFalseFlag
)
{
:
data_
()
{
// safe-guard against failing SFINAE
// safe-guard against failing SFINAE
RAPIDJSON_STATIC_ASSERT
((
internal
::
IsSame
<
bool
,
T
>::
Value
));
RAPIDJSON_STATIC_ASSERT
((
internal
::
IsSame
<
bool
,
T
>::
Value
));
data_
.
f
.
flags
=
b
?
kTrueFlag
:
kFalseFlag
;
}
}
//! Constructor for int value.
//! Constructor for int value.
explicit
GenericValue
(
int
i
)
RAPIDJSON_NOEXCEPT
:
data_
()
,
flags_
(
kNumberIntFlag
)
{
explicit
GenericValue
(
int
i
)
RAPIDJSON_NOEXCEPT
:
data_
()
{
data_
.
n
.
i64
=
i
;
data_
.
n
.
i64
=
i
;
if
(
i
>=
0
)
data_
.
f
.
flags
=
(
i
>=
0
)
?
(
kNumberIntFlag
|
kUintFlag
|
kUint64Flag
)
:
kNumberIntFlag
;
flags_
|=
kUintFlag
|
kUint64Flag
;
}
}
//! Constructor for unsigned value.
//! Constructor for unsigned value.
explicit
GenericValue
(
unsigned
u
)
RAPIDJSON_NOEXCEPT
:
data_
()
,
flags_
(
kNumberUintFlag
)
{
explicit
GenericValue
(
unsigned
u
)
RAPIDJSON_NOEXCEPT
:
data_
()
{
data_
.
n
.
u64
=
u
;
data_
.
n
.
u64
=
u
;
if
(
!
(
u
&
0x80000000
))
data_
.
f
.
flags
=
(
u
&
0x80000000
)
?
kNumberUintFlag
:
(
kNumberUintFlag
|
kIntFlag
|
kInt64Flag
);
flags_
|=
kIntFlag
|
kInt64Flag
;
}
}
//! Constructor for int64_t value.
//! Constructor for int64_t value.
explicit
GenericValue
(
int64_t
i64
)
RAPIDJSON_NOEXCEPT
:
data_
()
,
flags_
(
kNumberInt64Flag
)
{
explicit
GenericValue
(
int64_t
i64
)
RAPIDJSON_NOEXCEPT
:
data_
()
{
data_
.
n
.
i64
=
i64
;
data_
.
n
.
i64
=
i64
;
data_
.
f
.
flags
=
kNumberInt64Flag
;
if
(
i64
>=
0
)
{
if
(
i64
>=
0
)
{
flags_
|=
kNumberUint64Flag
;
data_
.
f
.
flags
|=
kNumberUint64Flag
;
if
(
!
(
static_cast
<
uint64_t
>
(
i64
)
&
RAPIDJSON_UINT64_C2
(
0xFFFFFFFF
,
0x00000000
)))
if
(
!
(
static_cast
<
uint64_t
>
(
i64
)
&
RAPIDJSON_UINT64_C2
(
0xFFFFFFFF
,
0x00000000
)))
flags_
|=
kUintFlag
;
data_
.
f
.
flags
|=
kUintFlag
;
if
(
!
(
static_cast
<
uint64_t
>
(
i64
)
&
RAPIDJSON_UINT64_C2
(
0xFFFFFFFF
,
0x80000000
)))
if
(
!
(
static_cast
<
uint64_t
>
(
i64
)
&
RAPIDJSON_UINT64_C2
(
0xFFFFFFFF
,
0x80000000
)))
flags_
|=
kIntFlag
;
data_
.
f
.
flags
|=
kIntFlag
;
}
}
else
if
(
i64
>=
static_cast
<
int64_t
>
(
RAPIDJSON_UINT64_C2
(
0xFFFFFFFF
,
0x80000000
)))
else
if
(
i64
>=
static_cast
<
int64_t
>
(
RAPIDJSON_UINT64_C2
(
0xFFFFFFFF
,
0x80000000
)))
flags_
|=
kIntFlag
;
data_
.
f
.
flags
|=
kIntFlag
;
}
}
//! Constructor for uint64_t value.
//! Constructor for uint64_t value.
explicit
GenericValue
(
uint64_t
u64
)
RAPIDJSON_NOEXCEPT
:
data_
()
,
flags_
(
kNumberUint64Flag
)
{
explicit
GenericValue
(
uint64_t
u64
)
RAPIDJSON_NOEXCEPT
:
data_
()
{
data_
.
n
.
u64
=
u64
;
data_
.
n
.
u64
=
u64
;
data_
.
f
.
flags
=
kNumberUint64Flag
;
if
(
!
(
u64
&
RAPIDJSON_UINT64_C2
(
0x80000000
,
0x00000000
)))
if
(
!
(
u64
&
RAPIDJSON_UINT64_C2
(
0x80000000
,
0x00000000
)))
flags_
|=
kInt64Flag
;
data_
.
f
.
flags
|=
kInt64Flag
;
if
(
!
(
u64
&
RAPIDJSON_UINT64_C2
(
0xFFFFFFFF
,
0x00000000
)))
if
(
!
(
u64
&
RAPIDJSON_UINT64_C2
(
0xFFFFFFFF
,
0x00000000
)))
flags_
|=
kUintFlag
;
data_
.
f
.
flags
|=
kUintFlag
;
if
(
!
(
u64
&
RAPIDJSON_UINT64_C2
(
0xFFFFFFFF
,
0x80000000
)))
if
(
!
(
u64
&
RAPIDJSON_UINT64_C2
(
0xFFFFFFFF
,
0x80000000
)))
flags_
|=
kIntFlag
;
data_
.
f
.
flags
|=
kIntFlag
;
}
}
//! Constructor for double value.
//! Constructor for double value.
explicit
GenericValue
(
double
d
)
RAPIDJSON_NOEXCEPT
:
data_
()
,
flags_
(
kNumberDoubleFlag
)
{
data_
.
n
.
d
=
d
;
}
explicit
GenericValue
(
double
d
)
RAPIDJSON_NOEXCEPT
:
data_
()
{
data_
.
n
.
d
=
d
;
data_
.
f
.
flags
=
kNumberDoubleFlag
;
}
//! Constructor for constant string (i.e. do not make a copy of string)
//! Constructor for constant string (i.e. do not make a copy of string)
GenericValue
(
const
Ch
*
s
,
SizeType
length
)
RAPIDJSON_NOEXCEPT
:
data_
()
,
flags_
()
{
SetStringRaw
(
StringRef
(
s
,
length
));
}
GenericValue
(
const
Ch
*
s
,
SizeType
length
)
RAPIDJSON_NOEXCEPT
:
data_
()
{
SetStringRaw
(
StringRef
(
s
,
length
));
}
//! Constructor for constant string (i.e. do not make a copy of string)
//! Constructor for constant string (i.e. do not make a copy of string)
explicit
GenericValue
(
StringRefType
s
)
RAPIDJSON_NOEXCEPT
:
data_
()
,
flags_
()
{
SetStringRaw
(
s
);
}
explicit
GenericValue
(
StringRefType
s
)
RAPIDJSON_NOEXCEPT
:
data_
()
{
SetStringRaw
(
s
);
}
//! Constructor for copy-string (i.e. do make a copy of string)
//! 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
);
}
GenericValue
(
const
Ch
*
s
,
SizeType
length
,
Allocator
&
allocator
)
:
data_
()
{
SetStringRaw
(
StringRef
(
s
,
length
),
allocator
);
}
//! Constructor for copy-string (i.e. do make a copy of string)
//! Constructor for copy-string (i.e. do make a copy of string)
GenericValue
(
const
Ch
*
s
,
Allocator
&
allocator
)
:
data_
()
,
flags_
()
{
SetStringRaw
(
StringRef
(
s
),
allocator
);
}
GenericValue
(
const
Ch
*
s
,
Allocator
&
allocator
)
:
data_
()
{
SetStringRaw
(
StringRef
(
s
),
allocator
);
}
#if RAPIDJSON_HAS_STDSTRING
#if RAPIDJSON_HAS_STDSTRING
//! Constructor for copy-string from a string object (i.e. do make a copy of string)
//! 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.
/*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
*/
*/
GenericValue
(
const
std
::
basic_string
<
Ch
>&
s
,
Allocator
&
allocator
)
:
data_
()
,
flags_
()
{
SetStringRaw
(
StringRef
(
s
),
allocator
);
}
GenericValue
(
const
std
::
basic_string
<
Ch
>&
s
,
Allocator
&
allocator
)
:
data_
()
{
SetStringRaw
(
StringRef
(
s
),
allocator
);
}
#endif
#endif
//! Destructor.
//! Destructor.
...
@@ -561,21 +562,24 @@ public:
...
@@ -561,21 +562,24 @@ public:
*/
*/
~
GenericValue
()
{
~
GenericValue
()
{
if
(
Allocator
::
kNeedFree
)
{
// Shortcut by Allocator's trait
if
(
Allocator
::
kNeedFree
)
{
// Shortcut by Allocator's trait
switch
(
flags_
)
{
switch
(
data_
.
f
.
flags
)
{
case
kArrayFlag
:
case
kArrayFlag
:
for
(
GenericValue
*
v
=
data_
.
a
.
elements
;
v
!=
data_
.
a
.
elements
+
data_
.
a
.
size
;
++
v
)
{
v
->~
GenericValue
();
GenericValue
*
e
=
GetElementsPointer
();
Allocator
::
Free
(
data_
.
a
.
elements
);
for
(
GenericValue
*
v
=
e
;
v
!=
e
+
data_
.
a
.
size
;
++
v
)
v
->~
GenericValue
();
Allocator
::
Free
(
e
);
}
break
;
break
;
case
kObjectFlag
:
case
kObjectFlag
:
for
(
MemberIterator
m
=
MemberBegin
();
m
!=
MemberEnd
();
++
m
)
for
(
MemberIterator
m
=
MemberBegin
();
m
!=
MemberEnd
();
++
m
)
m
->~
Member
();
m
->~
Member
();
Allocator
::
Free
(
data_
.
o
.
members
);
Allocator
::
Free
(
GetMembersPointer
()
);
break
;
break
;
case
kCopyStringFlag
:
case
kCopyStringFlag
:
Allocator
::
Free
(
const_cast
<
Ch
*>
(
data_
.
s
.
str
));
Allocator
::
Free
(
GetStringPointer
(
));
break
;
break
;
default
:
default
:
...
@@ -773,20 +777,20 @@ public:
...
@@ -773,20 +777,20 @@ public:
//!@name Type
//!@name Type
//@{
//@{
Type
GetType
()
const
{
return
static_cast
<
Type
>
(
flags_
&
kTypeMask
);
}
Type
GetType
()
const
{
return
static_cast
<
Type
>
(
data_
.
f
.
flags
&
kTypeMask
);
}
bool
IsNull
()
const
{
return
flags_
==
kNullFlag
;
}
bool
IsNull
()
const
{
return
data_
.
f
.
flags
==
kNullFlag
;
}
bool
IsFalse
()
const
{
return
flags_
==
kFalseFlag
;
}
bool
IsFalse
()
const
{
return
data_
.
f
.
flags
==
kFalseFlag
;
}
bool
IsTrue
()
const
{
return
flags_
==
kTrueFlag
;
}
bool
IsTrue
()
const
{
return
data_
.
f
.
flags
==
kTrueFlag
;
}
bool
IsBool
()
const
{
return
(
flags_
&
kBoolFlag
)
!=
0
;
}
bool
IsBool
()
const
{
return
(
data_
.
f
.
flags
&
kBoolFlag
)
!=
0
;
}
bool
IsObject
()
const
{
return
flags_
==
kObjectFlag
;
}
bool
IsObject
()
const
{
return
data_
.
f
.
flags
==
kObjectFlag
;
}
bool
IsArray
()
const
{
return
flags_
==
kArrayFlag
;
}
bool
IsArray
()
const
{
return
data_
.
f
.
flags
==
kArrayFlag
;
}
bool
IsNumber
()
const
{
return
(
flags_
&
kNumberFlag
)
!=
0
;
}
bool
IsNumber
()
const
{
return
(
data_
.
f
.
flags
&
kNumberFlag
)
!=
0
;
}
bool
IsInt
()
const
{
return
(
flags_
&
kIntFlag
)
!=
0
;
}
bool
IsInt
()
const
{
return
(
data_
.
f
.
flags
&
kIntFlag
)
!=
0
;
}
bool
IsUint
()
const
{
return
(
flags_
&
kUintFlag
)
!=
0
;
}
bool
IsUint
()
const
{
return
(
data_
.
f
.
flags
&
kUintFlag
)
!=
0
;
}
bool
IsInt64
()
const
{
return
(
flags_
&
kInt64Flag
)
!=
0
;
}
bool
IsInt64
()
const
{
return
(
data_
.
f
.
flags
&
kInt64Flag
)
!=
0
;
}
bool
IsUint64
()
const
{
return
(
flags_
&
kUint64Flag
)
!=
0
;
}
bool
IsUint64
()
const
{
return
(
data_
.
f
.
flags
&
kUint64Flag
)
!=
0
;
}
bool
IsDouble
()
const
{
return
(
flags_
&
kDoubleFlag
)
!=
0
;
}
bool
IsDouble
()
const
{
return
(
data_
.
f
.
flags
&
kDoubleFlag
)
!=
0
;
}
bool
IsString
()
const
{
return
(
flags_
&
kStringFlag
)
!=
0
;
}
bool
IsString
()
const
{
return
(
data_
.
f
.
flags
&
kStringFlag
)
!=
0
;
}
// Checks whether a number can be losslessly converted to a double.
// Checks whether a number can be losslessly converted to a double.
bool
IsLosslessDouble
()
const
{
bool
IsLosslessDouble
()
const
{
...
@@ -806,7 +810,7 @@ public:
...
@@ -806,7 +810,7 @@ public:
// Checks whether a number is a float (possible lossy).
// Checks whether a number is a float (possible lossy).
bool
IsFloat
()
const
{
bool
IsFloat
()
const
{
if
((
flags_
&
kDoubleFlag
)
==
0
)
if
((
data_
.
f
.
flags
&
kDoubleFlag
)
==
0
)
return
false
;
return
false
;
double
d
=
GetDouble
();
double
d
=
GetDouble
();
return
d
>=
-
3.4028234e38
&&
d
<=
3.4028234e38
;
return
d
>=
-
3.4028234e38
&&
d
<=
3.4028234e38
;
...
@@ -831,7 +835,7 @@ public:
...
@@ -831,7 +835,7 @@ public:
//!@name Bool
//!@name Bool
//@{
//@{
bool
GetBool
()
const
{
RAPIDJSON_ASSERT
(
IsBool
());
return
flags_
==
kTrueFlag
;
}
bool
GetBool
()
const
{
RAPIDJSON_ASSERT
(
IsBool
());
return
data_
.
f
.
flags
==
kTrueFlag
;
}
//!< Set boolean value
//!< Set boolean value
/*! \post IsBool() == true */
/*! \post IsBool() == true */
GenericValue
&
SetBool
(
bool
b
)
{
this
->~
GenericValue
();
new
(
this
)
GenericValue
(
b
);
return
*
this
;
}
GenericValue
&
SetBool
(
bool
b
)
{
this
->~
GenericValue
();
new
(
this
)
GenericValue
(
b
);
return
*
this
;
}
...
@@ -905,16 +909,16 @@ public:
...
@@ -905,16 +909,16 @@ public:
//! Const member iterator
//! Const member iterator
/*! \pre IsObject() == true */
/*! \pre IsObject() == true */
ConstMemberIterator
MemberBegin
()
const
{
RAPIDJSON_ASSERT
(
IsObject
());
return
ConstMemberIterator
(
data_
.
o
.
members
);
}
ConstMemberIterator
MemberBegin
()
const
{
RAPIDJSON_ASSERT
(
IsObject
());
return
ConstMemberIterator
(
GetMembersPointer
()
);
}
//! Const \em past-the-end member iterator
//! Const \em past-the-end member iterator
/*! \pre IsObject() == true */
/*! \pre IsObject() == true */
ConstMemberIterator
MemberEnd
()
const
{
RAPIDJSON_ASSERT
(
IsObject
());
return
ConstMemberIterator
(
data_
.
o
.
members
+
data_
.
o
.
size
);
}
ConstMemberIterator
MemberEnd
()
const
{
RAPIDJSON_ASSERT
(
IsObject
());
return
ConstMemberIterator
(
GetMembersPointer
()
+
data_
.
o
.
size
);
}
//! Member iterator
//! Member iterator
/*! \pre IsObject() == true */
/*! \pre IsObject() == true */
MemberIterator
MemberBegin
()
{
RAPIDJSON_ASSERT
(
IsObject
());
return
MemberIterator
(
data_
.
o
.
members
);
}
MemberIterator
MemberBegin
()
{
RAPIDJSON_ASSERT
(
IsObject
());
return
MemberIterator
(
GetMembersPointer
()
);
}
//! \em Past-the-end member iterator
//! \em Past-the-end member iterator
/*! \pre IsObject() == true */
/*! \pre IsObject() == true */
MemberIterator
MemberEnd
()
{
RAPIDJSON_ASSERT
(
IsObject
());
return
MemberIterator
(
data_
.
o
.
members
+
data_
.
o
.
size
);
}
MemberIterator
MemberEnd
()
{
RAPIDJSON_ASSERT
(
IsObject
());
return
MemberIterator
(
GetMembersPointer
()
+
data_
.
o
.
size
);
}
//! Check whether a member exists in the object.
//! Check whether a member exists in the object.
/*!
/*!
...
@@ -1024,16 +1028,17 @@ public:
...
@@ -1024,16 +1028,17 @@ public:
if
(
o
.
size
>=
o
.
capacity
)
{
if
(
o
.
size
>=
o
.
capacity
)
{
if
(
o
.
capacity
==
0
)
{
if
(
o
.
capacity
==
0
)
{
o
.
capacity
=
kDefaultObjectCapacity
;
o
.
capacity
=
kDefaultObjectCapacity
;
o
.
members
=
reinterpret_cast
<
Member
*>
(
allocator
.
Malloc
(
o
.
capacity
*
sizeof
(
Member
)));
SetMembersPointer
(
reinterpret_cast
<
Member
*>
(
allocator
.
Malloc
(
o
.
capacity
*
sizeof
(
Member
)
)));
}
}
else
{
else
{
SizeType
oldCapacity
=
o
.
capacity
;
SizeType
oldCapacity
=
o
.
capacity
;
o
.
capacity
+=
(
oldCapacity
+
1
)
/
2
;
// grow by factor 1.5
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
)));
SetMembersPointer
(
reinterpret_cast
<
Member
*>
(
allocator
.
Realloc
(
GetMembersPointer
(),
oldCapacity
*
sizeof
(
Member
),
o
.
capacity
*
sizeof
(
Member
)
)));
}
}
}
}
o
.
members
[
o
.
size
].
name
.
RawAssign
(
name
);
Member
*
members
=
GetMembersPointer
();
o
.
members
[
o
.
size
].
value
.
RawAssign
(
value
);
members
[
o
.
size
].
name
.
RawAssign
(
name
);
members
[
o
.
size
].
value
.
RawAssign
(
value
);
o
.
size
++
;
o
.
size
++
;
return
*
this
;
return
*
this
;
}
}
...
@@ -1212,18 +1217,14 @@ public:
...
@@ -1212,18 +1217,14 @@ public:
MemberIterator
RemoveMember
(
MemberIterator
m
)
{
MemberIterator
RemoveMember
(
MemberIterator
m
)
{
RAPIDJSON_ASSERT
(
IsObject
());
RAPIDJSON_ASSERT
(
IsObject
());
RAPIDJSON_ASSERT
(
data_
.
o
.
size
>
0
);
RAPIDJSON_ASSERT
(
data_
.
o
.
size
>
0
);
RAPIDJSON_ASSERT
(
data_
.
o
.
members
!=
0
);
RAPIDJSON_ASSERT
(
GetMembersPointer
()
!=
0
);
RAPIDJSON_ASSERT
(
m
>=
MemberBegin
()
&&
m
<
MemberEnd
());
RAPIDJSON_ASSERT
(
m
>=
MemberBegin
()
&&
m
<
MemberEnd
());
MemberIterator
last
(
data_
.
o
.
members
+
(
data_
.
o
.
size
-
1
));
MemberIterator
last
(
GetMembersPointer
()
+
(
data_
.
o
.
size
-
1
));
if
(
data_
.
o
.
size
>
1
&&
m
!=
last
)
{
if
(
data_
.
o
.
size
>
1
&&
m
!=
last
)
// Move the last one to this place
*
m
=
*
last
;
// Move the last one to this place
*
m
=
*
last
;
else
}
m
->~
Member
();
// Only one left, just destroy
else
{
// Only one left, just destroy
m
->~
Member
();
}
--
data_
.
o
.
size
;
--
data_
.
o
.
size
;
return
m
;
return
m
;
}
}
...
@@ -1253,7 +1254,7 @@ public:
...
@@ -1253,7 +1254,7 @@ public:
MemberIterator
EraseMember
(
ConstMemberIterator
first
,
ConstMemberIterator
last
)
{
MemberIterator
EraseMember
(
ConstMemberIterator
first
,
ConstMemberIterator
last
)
{
RAPIDJSON_ASSERT
(
IsObject
());
RAPIDJSON_ASSERT
(
IsObject
());
RAPIDJSON_ASSERT
(
data_
.
o
.
size
>
0
);
RAPIDJSON_ASSERT
(
data_
.
o
.
size
>
0
);
RAPIDJSON_ASSERT
(
data_
.
o
.
members
!=
0
);
RAPIDJSON_ASSERT
(
GetMembersPointer
()
!=
0
);
RAPIDJSON_ASSERT
(
first
>=
MemberBegin
());
RAPIDJSON_ASSERT
(
first
>=
MemberBegin
());
RAPIDJSON_ASSERT
(
first
<=
last
);
RAPIDJSON_ASSERT
(
first
<=
last
);
RAPIDJSON_ASSERT
(
last
<=
MemberEnd
());
RAPIDJSON_ASSERT
(
last
<=
MemberEnd
());
...
@@ -1315,8 +1316,9 @@ public:
...
@@ -1315,8 +1316,9 @@ public:
*/
*/
void
Clear
()
{
void
Clear
()
{
RAPIDJSON_ASSERT
(
IsArray
());
RAPIDJSON_ASSERT
(
IsArray
());
for
(
SizeType
i
=
0
;
i
<
data_
.
a
.
size
;
++
i
)
GenericValue
*
e
=
GetElementsPointer
();
data_
.
a
.
elements
[
i
].
~
GenericValue
();
for
(
GenericValue
*
v
=
e
;
v
!=
e
+
data_
.
a
.
size
;
++
v
)
v
->~
GenericValue
();
data_
.
a
.
size
=
0
;
data_
.
a
.
size
=
0
;
}
}
...
@@ -1328,16 +1330,16 @@ public:
...
@@ -1328,16 +1330,16 @@ public:
GenericValue
&
operator
[](
SizeType
index
)
{
GenericValue
&
operator
[](
SizeType
index
)
{
RAPIDJSON_ASSERT
(
IsArray
());
RAPIDJSON_ASSERT
(
IsArray
());
RAPIDJSON_ASSERT
(
index
<
data_
.
a
.
size
);
RAPIDJSON_ASSERT
(
index
<
data_
.
a
.
size
);
return
data_
.
a
.
elements
[
index
];
return
GetElementsPointer
()
[
index
];
}
}
const
GenericValue
&
operator
[](
SizeType
index
)
const
{
return
const_cast
<
GenericValue
&>
(
*
this
)[
index
];
}
const
GenericValue
&
operator
[](
SizeType
index
)
const
{
return
const_cast
<
GenericValue
&>
(
*
this
)[
index
];
}
//! Element iterator
//! Element iterator
/*! \pre IsArray() == true */
/*! \pre IsArray() == true */
ValueIterator
Begin
()
{
RAPIDJSON_ASSERT
(
IsArray
());
return
data_
.
a
.
elements
;
}
ValueIterator
Begin
()
{
RAPIDJSON_ASSERT
(
IsArray
());
return
GetElementsPointer
()
;
}
//! \em Past-the-end element iterator
//! \em Past-the-end element iterator
/*! \pre IsArray() == true */
/*! \pre IsArray() == true */
ValueIterator
End
()
{
RAPIDJSON_ASSERT
(
IsArray
());
return
data_
.
a
.
elements
+
data_
.
a
.
size
;
}
ValueIterator
End
()
{
RAPIDJSON_ASSERT
(
IsArray
());
return
GetElementsPointer
()
+
data_
.
a
.
size
;
}
//! Constant element iterator
//! Constant element iterator
/*! \pre IsArray() == true */
/*! \pre IsArray() == true */
ConstValueIterator
Begin
()
const
{
return
const_cast
<
GenericValue
&>
(
*
this
).
Begin
();
}
ConstValueIterator
Begin
()
const
{
return
const_cast
<
GenericValue
&>
(
*
this
).
Begin
();
}
...
@@ -1354,7 +1356,7 @@ public:
...
@@ -1354,7 +1356,7 @@ public:
GenericValue
&
Reserve
(
SizeType
newCapacity
,
Allocator
&
allocator
)
{
GenericValue
&
Reserve
(
SizeType
newCapacity
,
Allocator
&
allocator
)
{
RAPIDJSON_ASSERT
(
IsArray
());
RAPIDJSON_ASSERT
(
IsArray
());
if
(
newCapacity
>
data_
.
a
.
capacity
)
{
if
(
newCapacity
>
data_
.
a
.
capacity
)
{
data_
.
a
.
elements
=
static_cast
<
GenericValue
*>
(
allocator
.
Realloc
(
data_
.
a
.
elements
,
data_
.
a
.
capacity
*
sizeof
(
GenericValue
),
newCapacity
*
sizeof
(
GenericValue
)));
SetElementsPointer
(
reinterpret_cast
<
GenericValue
*>
(
allocator
.
Realloc
(
GetElementsPointer
(),
data_
.
a
.
capacity
*
sizeof
(
GenericValue
),
newCapacity
*
sizeof
(
GenericValue
)
)));
data_
.
a
.
capacity
=
newCapacity
;
data_
.
a
.
capacity
=
newCapacity
;
}
}
return
*
this
;
return
*
this
;
...
@@ -1374,7 +1376,7 @@ public:
...
@@ -1374,7 +1376,7 @@ public:
RAPIDJSON_ASSERT
(
IsArray
());
RAPIDJSON_ASSERT
(
IsArray
());
if
(
data_
.
a
.
size
>=
data_
.
a
.
capacity
)
if
(
data_
.
a
.
size
>=
data_
.
a
.
capacity
)
Reserve
(
data_
.
a
.
capacity
==
0
?
kDefaultArrayCapacity
:
(
data_
.
a
.
capacity
+
(
data_
.
a
.
capacity
+
1
)
/
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
);
GetElementsPointer
()
[
data_
.
a
.
size
++
].
RawAssign
(
value
);
return
*
this
;
return
*
this
;
}
}
...
@@ -1428,7 +1430,7 @@ public:
...
@@ -1428,7 +1430,7 @@ public:
GenericValue
&
PopBack
()
{
GenericValue
&
PopBack
()
{
RAPIDJSON_ASSERT
(
IsArray
());
RAPIDJSON_ASSERT
(
IsArray
());
RAPIDJSON_ASSERT
(
!
Empty
());
RAPIDJSON_ASSERT
(
!
Empty
());
data_
.
a
.
elements
[
--
data_
.
a
.
size
].
~
GenericValue
();
GetElementsPointer
()
[
--
data_
.
a
.
size
].
~
GenericValue
();
return
*
this
;
return
*
this
;
}
}
...
@@ -1454,7 +1456,7 @@ public:
...
@@ -1454,7 +1456,7 @@ public:
ValueIterator
Erase
(
ConstValueIterator
first
,
ConstValueIterator
last
)
{
ValueIterator
Erase
(
ConstValueIterator
first
,
ConstValueIterator
last
)
{
RAPIDJSON_ASSERT
(
IsArray
());
RAPIDJSON_ASSERT
(
IsArray
());
RAPIDJSON_ASSERT
(
data_
.
a
.
size
>
0
);
RAPIDJSON_ASSERT
(
data_
.
a
.
size
>
0
);
RAPIDJSON_ASSERT
(
data_
.
a
.
elements
!=
0
);
RAPIDJSON_ASSERT
(
GetElementsPointer
()
!=
0
);
RAPIDJSON_ASSERT
(
first
>=
Begin
());
RAPIDJSON_ASSERT
(
first
>=
Begin
());
RAPIDJSON_ASSERT
(
first
<=
last
);
RAPIDJSON_ASSERT
(
first
<=
last
);
RAPIDJSON_ASSERT
(
last
<=
End
());
RAPIDJSON_ASSERT
(
last
<=
End
());
...
@@ -1471,21 +1473,21 @@ public:
...
@@ -1471,21 +1473,21 @@ public:
//!@name Number
//!@name Number
//@{
//@{
int
GetInt
()
const
{
RAPIDJSON_ASSERT
(
flags_
&
kIntFlag
);
return
data_
.
n
.
i
.
i
;
}
int
GetInt
()
const
{
RAPIDJSON_ASSERT
(
data_
.
f
.
flags
&
kIntFlag
);
return
data_
.
n
.
i
.
i
;
}
unsigned
GetUint
()
const
{
RAPIDJSON_ASSERT
(
flags_
&
kUintFlag
);
return
data_
.
n
.
u
.
u
;
}
unsigned
GetUint
()
const
{
RAPIDJSON_ASSERT
(
data_
.
f
.
flags
&
kUintFlag
);
return
data_
.
n
.
u
.
u
;
}
int64_t
GetInt64
()
const
{
RAPIDJSON_ASSERT
(
flags_
&
kInt64Flag
);
return
data_
.
n
.
i64
;
}
int64_t
GetInt64
()
const
{
RAPIDJSON_ASSERT
(
data_
.
f
.
flags
&
kInt64Flag
);
return
data_
.
n
.
i64
;
}
uint64_t
GetUint64
()
const
{
RAPIDJSON_ASSERT
(
flags_
&
kUint64Flag
);
return
data_
.
n
.
u64
;
}
uint64_t
GetUint64
()
const
{
RAPIDJSON_ASSERT
(
data_
.
f
.
flags
&
kUint64Flag
);
return
data_
.
n
.
u64
;
}
//! Get the value as double type.
//! Get the value as double type.
/*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessDouble() to check whether the converison is lossless.
/*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessDouble() to check whether the converison is lossless.
*/
*/
double
GetDouble
()
const
{
double
GetDouble
()
const
{
RAPIDJSON_ASSERT
(
IsNumber
());
RAPIDJSON_ASSERT
(
IsNumber
());
if
((
flags_
&
kDoubleFlag
)
!=
0
)
return
data_
.
n
.
d
;
// exact type, no conversion.
if
((
data_
.
f
.
flags
&
kDoubleFlag
)
!=
0
)
return
data_
.
n
.
d
;
// exact type, no conversion.
if
((
flags_
&
kIntFlag
)
!=
0
)
return
data_
.
n
.
i
.
i
;
// int -> double
if
((
data_
.
f
.
flags
&
kIntFlag
)
!=
0
)
return
data_
.
n
.
i
.
i
;
// int -> double
if
((
flags_
&
kUintFlag
)
!=
0
)
return
data_
.
n
.
u
.
u
;
// unsigned -> double
if
((
data_
.
f
.
flags
&
kUintFlag
)
!=
0
)
return
data_
.
n
.
u
.
u
;
// unsigned -> double
if
((
flags_
&
kInt64Flag
)
!=
0
)
return
static_cast
<
double
>
(
data_
.
n
.
i64
);
// int64_t -> double (may lose precision)
if
((
data_
.
f
.
flags
&
kInt64Flag
)
!=
0
)
return
static_cast
<
double
>
(
data_
.
n
.
i64
);
// int64_t -> double (may lose precision)
RAPIDJSON_ASSERT
((
flags_
&
kUint64Flag
)
!=
0
);
return
static_cast
<
double
>
(
data_
.
n
.
u64
);
// uint64_t -> double (may lose precision)
RAPIDJSON_ASSERT
((
data_
.
f
.
flags
&
kUint64Flag
)
!=
0
);
return
static_cast
<
double
>
(
data_
.
n
.
u64
);
// uint64_t -> double (may lose precision)
}
}
//! Get the value as float type.
//! Get the value as float type.
...
@@ -1508,12 +1510,12 @@ public:
...
@@ -1508,12 +1510,12 @@ public:
//!@name String
//!@name String
//@{
//@{
const
Ch
*
GetString
()
const
{
RAPIDJSON_ASSERT
(
IsString
());
return
(
(
flags_
&
kInlineStrFlag
)
?
data_
.
ss
.
str
:
data_
.
s
.
str
);
}
const
Ch
*
GetString
()
const
{
RAPIDJSON_ASSERT
(
IsString
());
return
(
data_
.
f
.
flags
&
kInlineStrFlag
)
?
data_
.
ss
.
str
:
GetStringPointer
(
);
}
//! Get the length of string.
//! Get the length of string.
/*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength().
/*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength().
*/
*/
SizeType
GetStringLength
()
const
{
RAPIDJSON_ASSERT
(
IsString
());
return
((
flags_
&
kInlineStrFlag
)
?
(
data_
.
ss
.
GetLength
())
:
data_
.
s
.
length
);
}
SizeType
GetStringLength
()
const
{
RAPIDJSON_ASSERT
(
IsString
());
return
((
data_
.
f
.
flags
&
kInlineStrFlag
)
?
(
data_
.
ss
.
GetLength
())
:
data_
.
s
.
length
);
}
//! Set this value as a string without copying source string.
//! 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.
/*! This version has better performance with supplied length, and also support string containing null character.
...
@@ -1582,7 +1584,7 @@ public:
...
@@ -1582,7 +1584,7 @@ public:
return
false
;
return
false
;
for
(
ConstMemberIterator
m
=
MemberBegin
();
m
!=
MemberEnd
();
++
m
)
{
for
(
ConstMemberIterator
m
=
MemberBegin
();
m
!=
MemberEnd
();
++
m
)
{
RAPIDJSON_ASSERT
(
m
->
name
.
IsString
());
// User may change the type of name by MemberIterator.
RAPIDJSON_ASSERT
(
m
->
name
.
IsString
());
// User may change the type of name by MemberIterator.
if
(
RAPIDJSON_UNLIKELY
(
!
handler
.
Key
(
m
->
name
.
GetString
(),
m
->
name
.
GetStringLength
(),
(
m
->
name
.
flags_
&
kCopyFlag
)
!=
0
)))
if
(
RAPIDJSON_UNLIKELY
(
!
handler
.
Key
(
m
->
name
.
GetString
(),
m
->
name
.
GetStringLength
(),
(
m
->
name
.
data_
.
f
.
flags
&
kCopyFlag
)
!=
0
)))
return
false
;
return
false
;
if
(
RAPIDJSON_UNLIKELY
(
!
m
->
value
.
Accept
(
handler
)))
if
(
RAPIDJSON_UNLIKELY
(
!
m
->
value
.
Accept
(
handler
)))
return
false
;
return
false
;
...
@@ -1592,13 +1594,13 @@ public:
...
@@ -1592,13 +1594,13 @@ public:
case
kArrayType
:
case
kArrayType
:
if
(
RAPIDJSON_UNLIKELY
(
!
handler
.
StartArray
()))
if
(
RAPIDJSON_UNLIKELY
(
!
handler
.
StartArray
()))
return
false
;
return
false
;
for
(
const
GenericValue
*
v
=
data_
.
a
.
elements
;
v
!=
data_
.
a
.
elements
+
data_
.
a
.
size
;
++
v
)
for
(
const
GenericValue
*
v
=
Begin
();
v
!=
End
()
;
++
v
)
if
(
RAPIDJSON_UNLIKELY
(
!
v
->
Accept
(
handler
)))
if
(
RAPIDJSON_UNLIKELY
(
!
v
->
Accept
(
handler
)))
return
false
;
return
false
;
return
handler
.
EndArray
(
data_
.
a
.
size
);
return
handler
.
EndArray
(
data_
.
a
.
size
);
case
kStringType
:
case
kStringType
:
return
handler
.
String
(
GetString
(),
GetStringLength
(),
(
flags_
&
kCopyFlag
)
!=
0
);
return
handler
.
String
(
GetString
(),
GetStringLength
(),
(
data_
.
f
.
flags
&
kCopyFlag
)
!=
0
);
default
:
default
:
RAPIDJSON_ASSERT
(
GetType
()
==
kNumberType
);
RAPIDJSON_ASSERT
(
GetType
()
==
kNumberType
);
...
@@ -1615,16 +1617,16 @@ private:
...
@@ -1615,16 +1617,16 @@ private:
template
<
typename
,
typename
,
typename
>
friend
class
GenericDocument
;
template
<
typename
,
typename
,
typename
>
friend
class
GenericDocument
;
enum
{
enum
{
kBoolFlag
=
0x100
,
kBoolFlag
=
0x0008
,
kNumberFlag
=
0x20
0
,
kNumberFlag
=
0x001
0
,
kIntFlag
=
0x40
0
,
kIntFlag
=
0x002
0
,
kUintFlag
=
0x80
0
,
kUintFlag
=
0x004
0
,
kInt64Flag
=
0x100
0
,
kInt64Flag
=
0x008
0
,
kUint64Flag
=
0x20
00
,
kUint64Flag
=
0x01
00
,
kDoubleFlag
=
0x40
00
,
kDoubleFlag
=
0x02
00
,
kStringFlag
=
0x1000
00
,
kStringFlag
=
0x04
00
,
kCopyFlag
=
0x2000
00
,
kCopyFlag
=
0x08
00
,
kInlineStrFlag
=
0x400
000
,
kInlineStrFlag
=
0x1
000
,
// Initial flags of different types.
// Initial flags of different types.
kNullFlag
=
kNullType
,
kNullFlag
=
kNullType
,
...
@@ -1642,16 +1644,27 @@ private:
...
@@ -1642,16 +1644,27 @@ private:
kObjectFlag
=
kObjectType
,
kObjectFlag
=
kObjectType
,
kArrayFlag
=
kArrayType
,
kArrayFlag
=
kArrayType
,
kTypeMask
=
0x
FF
// bitwise-and with mask of 0xFF can be optimized by compiler
kTypeMask
=
0x
07
};
};
static
const
SizeType
kDefaultArrayCapacity
=
16
;
static
const
SizeType
kDefaultArrayCapacity
=
16
;
static
const
SizeType
kDefaultObjectCapacity
=
16
;
static
const
SizeType
kDefaultObjectCapacity
=
16
;
struct
Flag
{
#if RAPIDJSON_48BITPOINTER_OPTIMIZATION
char
payload
[
sizeof
(
SizeType
)
*
2
+
6
];
// 2 x SizeType + lower 48-bit pointer
#elif RAPIDJSON_64BIT
char
payload
[
Sizeof
(
SizeType
)
*
2
+
sizeof
(
void
*
)
+
6
];
// 6 padding bytes
#else
char
payload
[
Sizeof
(
SizeType
)
*
2
+
sizeof
(
void
*
)
+
2
];
// 2 padding bytes
#endif
uint16_t
flags
;
};
struct
String
{
struct
String
{
const
Ch
*
str
;
SizeType
length
;
SizeType
length
;
unsigned
hashcode
;
//!< reserved
SizeType
hashcode
;
//!< reserved
const
Ch
*
str
;
};
// 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
};
// 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
// implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars
// implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars
...
@@ -1660,10 +1673,10 @@ private:
...
@@ -1660,10 +1673,10 @@ private:
// to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as
// 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
// the string terminator as well. For getting the string length back from that value just use
// "MaxSize - str[LenPos]".
// "MaxSize - str[LenPos]".
// This allows to store 1
1-chars strings in 32-bit mode and 15-chars strings in 64-bit mode
// This allows to store 1
3-chars strings in 32-bit mode, 21-chars strings in 64-bit mode,
// inline (for `UTF8`-encoded strings).
//
13-chars strings for RAPIDJSON_48BITPOINTER_OPTIMIZATION=1
inline (for `UTF8`-encoded strings).
struct
ShortString
{
struct
ShortString
{
enum
{
MaxChars
=
sizeof
(
String
)
/
sizeof
(
Ch
),
MaxSize
=
MaxChars
-
1
,
LenPos
=
MaxSize
};
enum
{
MaxChars
=
sizeof
(
Flag
::
payload
)
/
sizeof
(
Ch
),
MaxSize
=
MaxChars
-
1
,
LenPos
=
MaxSize
};
Ch
str
[
MaxChars
];
Ch
str
[
MaxChars
];
inline
static
bool
Usable
(
SizeType
len
)
{
return
(
MaxSize
>=
len
);
}
inline
static
bool
Usable
(
SizeType
len
)
{
return
(
MaxSize
>=
len
);
}
...
@@ -1698,15 +1711,15 @@ private:
...
@@ -1698,15 +1711,15 @@ private:
};
// 8 bytes
};
// 8 bytes
struct
Object
{
struct
Object
{
Member
*
members
;
SizeType
size
;
SizeType
size
;
SizeType
capacity
;
SizeType
capacity
;
Member
*
members
;
};
// 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
};
// 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
struct
Array
{
struct
Array
{
GenericValue
*
elements
;
SizeType
size
;
SizeType
size
;
SizeType
capacity
;
SizeType
capacity
;
GenericValue
*
elements
;
};
// 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
};
// 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
union
Data
{
union
Data
{
...
@@ -1715,51 +1728,61 @@ private:
...
@@ -1715,51 +1728,61 @@ private:
Number
n
;
Number
n
;
Object
o
;
Object
o
;
Array
a
;
Array
a
;
};
// 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
Flag
f
;
};
// 16 bytes in 32-bit mode, 24 bytes in 64-bit mode, 16 bytes in 64-bit with RAPIDJSON_48BITPOINTER_OPTIMIZATION
RAPIDJSON_FORCEINLINE
Ch
*
GetStringPointer
()
const
{
return
RAPIDJSON_GETPOINTER
(
Ch
,
data_
.
s
.
str
);
}
RAPIDJSON_FORCEINLINE
const
Ch
*
SetStringPointer
(
const
Ch
*
str
)
{
return
RAPIDJSON_SETPOINTER
(
Ch
,
data_
.
s
.
str
,
str
);
}
RAPIDJSON_FORCEINLINE
GenericValue
*
GetElementsPointer
()
const
{
return
RAPIDJSON_GETPOINTER
(
GenericValue
,
data_
.
a
.
elements
);
}
RAPIDJSON_FORCEINLINE
const
GenericValue
*
SetElementsPointer
(
const
GenericValue
*
elements
)
{
return
RAPIDJSON_SETPOINTER
(
GenericValue
,
data_
.
a
.
elements
,
elements
);
}
RAPIDJSON_FORCEINLINE
Member
*
GetMembersPointer
()
const
{
return
RAPIDJSON_GETPOINTER
(
Member
,
data_
.
o
.
members
);
}
RAPIDJSON_FORCEINLINE
const
Member
*
SetMembersPointer
(
const
Member
*
members
)
{
return
RAPIDJSON_SETPOINTER
(
Member
,
data_
.
o
.
members
,
members
);
}
// Initialize this value as array with initial data, without calling destructor.
// Initialize this value as array with initial data, without calling destructor.
void
SetArrayRaw
(
GenericValue
*
values
,
SizeType
count
,
Allocator
&
allocator
)
{
void
SetArrayRaw
(
GenericValue
*
values
,
SizeType
count
,
Allocator
&
allocator
)
{
flags_
=
kArrayFlag
;
data_
.
f
.
flags
=
kArrayFlag
;
if
(
count
)
{
if
(
count
)
{
data_
.
a
.
elements
=
static_cast
<
GenericValue
*>
(
allocator
.
Malloc
(
count
*
sizeof
(
GenericValue
)));
GenericValue
*
e
=
static_cast
<
GenericValue
*>
(
allocator
.
Malloc
(
count
*
sizeof
(
GenericValue
)));
std
::
memcpy
(
data_
.
a
.
elements
,
values
,
count
*
sizeof
(
GenericValue
));
SetElementsPointer
(
e
);
std
::
memcpy
(
e
,
values
,
count
*
sizeof
(
GenericValue
));
}
}
else
else
data_
.
a
.
elements
=
NULL
;
SetElementsPointer
(
0
)
;
data_
.
a
.
size
=
data_
.
a
.
capacity
=
count
;
data_
.
a
.
size
=
data_
.
a
.
capacity
=
count
;
}
}
//! Initialize this value as object with initial data, without calling destructor.
//! Initialize this value as object with initial data, without calling destructor.
void
SetObjectRaw
(
Member
*
members
,
SizeType
count
,
Allocator
&
allocator
)
{
void
SetObjectRaw
(
Member
*
members
,
SizeType
count
,
Allocator
&
allocator
)
{
flags_
=
kObjectFlag
;
data_
.
f
.
flags
=
kObjectFlag
;
if
(
count
)
{
if
(
count
)
{
data_
.
o
.
members
=
static_cast
<
Member
*>
(
allocator
.
Malloc
(
count
*
sizeof
(
Member
)));
Member
*
m
=
static_cast
<
Member
*>
(
allocator
.
Malloc
(
count
*
sizeof
(
Member
)));
std
::
memcpy
(
data_
.
o
.
members
,
members
,
count
*
sizeof
(
Member
));
SetMembersPointer
(
m
);
std
::
memcpy
(
m
,
members
,
count
*
sizeof
(
Member
));
}
}
else
else
data_
.
o
.
members
=
NULL
;
SetMembersPointer
(
0
)
;
data_
.
o
.
size
=
data_
.
o
.
capacity
=
count
;
data_
.
o
.
size
=
data_
.
o
.
capacity
=
count
;
}
}
//! Initialize this value as constant string, without calling destructor.
//! Initialize this value as constant string, without calling destructor.
void
SetStringRaw
(
StringRefType
s
)
RAPIDJSON_NOEXCEPT
{
void
SetStringRaw
(
StringRefType
s
)
RAPIDJSON_NOEXCEPT
{
flags_
=
kConstStringFlag
;
data_
.
f
.
flags
=
kConstStringFlag
;
data_
.
s
.
str
=
s
;
SetStringPointer
(
s
)
;
data_
.
s
.
length
=
s
.
length
;
data_
.
s
.
length
=
s
.
length
;
}
}
//! Initialize this value as copy string with initial data, without calling destructor.
//! Initialize this value as copy string with initial data, without calling destructor.
void
SetStringRaw
(
StringRefType
s
,
Allocator
&
allocator
)
{
void
SetStringRaw
(
StringRefType
s
,
Allocator
&
allocator
)
{
Ch
*
str
=
NULL
;
Ch
*
str
=
0
;
if
(
ShortString
::
Usable
(
s
.
length
))
{
if
(
ShortString
::
Usable
(
s
.
length
))
{
flags_
=
kShortStringFlag
;
data_
.
f
.
flags
=
kShortStringFlag
;
data_
.
ss
.
SetLength
(
s
.
length
);
data_
.
ss
.
SetLength
(
s
.
length
);
str
=
data_
.
ss
.
str
;
str
=
data_
.
ss
.
str
;
}
else
{
}
else
{
flags_
=
kCopyStringFlag
;
data_
.
f
.
flags
=
kCopyStringFlag
;
data_
.
s
.
length
=
s
.
length
;
data_
.
s
.
length
=
s
.
length
;
str
=
static_cast
<
Ch
*>
(
allocator
.
Malloc
((
s
.
length
+
1
)
*
sizeof
(
Ch
)));
str
=
static_cast
<
Ch
*>
(
allocator
.
Malloc
((
s
.
length
+
1
)
*
sizeof
(
Ch
)));
data_
.
s
.
str
=
str
;
SetStringPointer
(
str
)
;
}
}
std
::
memcpy
(
str
,
s
,
s
.
length
*
sizeof
(
Ch
));
std
::
memcpy
(
str
,
s
,
s
.
length
*
sizeof
(
Ch
));
str
[
s
.
length
]
=
'\0'
;
str
[
s
.
length
]
=
'\0'
;
...
@@ -1768,8 +1791,8 @@ private:
...
@@ -1768,8 +1791,8 @@ private:
//! Assignment without calling destructor
//! Assignment without calling destructor
void
RawAssign
(
GenericValue
&
rhs
)
RAPIDJSON_NOEXCEPT
{
void
RawAssign
(
GenericValue
&
rhs
)
RAPIDJSON_NOEXCEPT
{
data_
=
rhs
.
data_
;
data_
=
rhs
.
data_
;
flags_
=
rhs
.
flags_
;
// data_.f.flags = rhs.data_.f.flags
;
rhs
.
flags_
=
kNullFlag
;
rhs
.
data_
.
f
.
flags
=
kNullFlag
;
}
}
template
<
typename
SourceAllocator
>
template
<
typename
SourceAllocator
>
...
@@ -1789,7 +1812,6 @@ private:
...
@@ -1789,7 +1812,6 @@ private:
}
}
Data
data_
;
Data
data_
;
unsigned
flags_
;
};
};
//! GenericValue with UTF8 encoding
//! GenericValue with UTF8 encoding
...
@@ -2158,15 +2180,15 @@ GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,Sourc
...
@@ -2158,15 +2180,15 @@ GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,Sourc
}
}
break
;
break
;
case
kStringType
:
case
kStringType
:
if
(
rhs
.
flags_
==
kConstStringFlag
)
{
if
(
rhs
.
data_
.
f
.
flags
==
kConstStringFlag
)
{
flags_
=
rhs
.
flags_
;
data_
.
f
.
flags
=
rhs
.
data_
.
f
.
flags
;
data_
=
*
reinterpret_cast
<
const
Data
*>
(
&
rhs
.
data_
);
data_
=
*
reinterpret_cast
<
const
Data
*>
(
&
rhs
.
data_
);
}
else
{
}
else
{
SetStringRaw
(
StringRef
(
rhs
.
GetString
(),
rhs
.
GetStringLength
()),
allocator
);
SetStringRaw
(
StringRef
(
rhs
.
GetString
(),
rhs
.
GetStringLength
()),
allocator
);
}
}
break
;
break
;
default
:
default
:
flags_
=
rhs
.
flags_
;
data_
.
f
.
flags
=
rhs
.
data_
.
f
.
flags
;
data_
=
*
reinterpret_cast
<
const
Data
*>
(
&
rhs
.
data_
);
data_
=
*
reinterpret_cast
<
const
Data
*>
(
&
rhs
.
data_
);
break
;
break
;
}
}
...
...
include/rapidjson/rapidjson.h
View file @
e731726c
...
@@ -265,7 +265,8 @@
...
@@ -265,7 +265,8 @@
\param x pointer to align
\param x pointer to align
Some machines require strict data alignment. Currently the default uses 4 bytes
Some machines require strict data alignment. Currently the default uses 4 bytes
alignment. User can customize by defining the RAPIDJSON_ALIGN function macro.
alignment on 32-bit platforms and 8 bytes alignment for 64-bit platforms.
User can customize by defining the RAPIDJSON_ALIGN function macro.
*/
*/
#ifndef RAPIDJSON_ALIGN
#ifndef RAPIDJSON_ALIGN
#if RAPIDJSON_64BIT == 1
#if RAPIDJSON_64BIT == 1
...
@@ -288,6 +289,36 @@
...
@@ -288,6 +289,36 @@
#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
#endif
#endif
///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_48BITPOINTER_OPTIMIZATION
//! Use only lower 48-bit address for some pointers.
/*!
\ingroup RAPIDJSON_CONFIG
This optimization uses the fact that current X86-64 architecture only implement lower 48-bit virtual address.
The higher 16-bit can be used for storing other data.
\c GenericValue uses this optimization to reduce its size form 24 bytes to 16 bytes in 64-bit architecture.
*/
#ifndef RAPIDJSON_48BITPOINTER_OPTIMIZATION
#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)
#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 1
#else
#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 0
#endif
#endif // RAPIDJSON_48BITPOINTER_OPTIMIZATION
#if RAPIDJSON_48BITPOINTER_OPTIMIZATION == 1
#if RAPIDJSON_64BIT != 1
#error RAPIDJSON_48BITPOINTER_OPTIMIZATION can only be set to 1 when RAPIDJSON_64BIT=1
#endif
#define RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast<type *>((reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast<uintptr_t>(reinterpret_cast<const void*>(x))))
#define RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast<type *>(reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF))))
#else
#define RAPIDJSON_SETPOINTER(type, p, x) (p = (x))
#define RAPIDJSON_GETPOINTER(type, p) (p)
#endif
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD
// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD
...
...
test/unittest/valuetest.cpp
View file @
e731726c
...
@@ -23,6 +23,18 @@ RAPIDJSON_DIAG_OFF(c++98-compat)
...
@@ -23,6 +23,18 @@ RAPIDJSON_DIAG_OFF(c++98-compat)
using
namespace
rapidjson
;
using
namespace
rapidjson
;
TEST
(
Value
,
Size
)
{
if
(
sizeof
(
SizeType
)
==
4
)
{
#if RAPIDJSON_48BITPOINTER_OPTIMIZATION
EXPECT_EQ
(
16
,
sizeof
(
Value
));
#elif RAPIDJSON_64BIT
EXPECT_EQ
(
24
,
sizeof
(
Value
));
#else
EXPECT_EQ
(
16
,
sizeof
(
Value
));
#endif
}
}
TEST
(
Value
,
DefaultConstructor
)
{
TEST
(
Value
,
DefaultConstructor
)
{
Value
x
;
Value
x
;
EXPECT_EQ
(
kNullType
,
x
.
GetType
());
EXPECT_EQ
(
kNullType
,
x
.
GetType
());
...
...
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