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
5dee3940
Commit
5dee3940
authored
May 08, 2015
by
Milo Yip
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add Pointer::Append() and fixed bugs in assignment and Parse()
parent
f4e357f6
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
167 additions
and
24 deletions
+167
-24
pointer.h
include/rapidjson/pointer.h
+127
-24
pointertest.cpp
test/unittest/pointertest.cpp
+40
-0
No files found.
include/rapidjson/pointer.h
View file @
5dee3940
...
...
@@ -16,6 +16,7 @@
#define RAPIDJSON_POINTER_H_
#include "document.h"
#include "internal/itoa.h"
RAPIDJSON_NAMESPACE_BEGIN
...
...
@@ -169,37 +170,108 @@ public:
//! Assignment operator.
GenericPointer
&
operator
=
(
const
GenericPointer
&
rhs
)
{
this
->~
GenericPointer
();
if
(
this
!=
&
rhs
)
{
// Do not delete ownAllcator
if
(
nameBuffer_
)
{
Allocator
::
Free
(
nameBuffer_
);
Allocator
::
Free
(
tokens_
);
}
tokenCount_
=
rhs
.
tokenCount_
;
parseErrorOffset_
=
rhs
.
parseErrorOffset_
;
parseErrorCode_
=
rhs
.
parseErrorCode_
;
tokenCount_
=
rhs
.
tokenCount_
;
parseErrorOffset_
=
rhs
.
parseErrorOffset_
;
parseErrorCode_
=
rhs
.
parseErrorCode_
;
if
(
rhs
.
nameBuffer_
)
{
// Normally parsed tokens.
if
(
!
allocator_
)
// allocator is independently owned.
ownAllocator_
=
allocator_
=
RAPIDJSON_NEW
(
Allocator
());
if
(
rhs
.
nameBuffer_
)
CopyFromRaw
(
rhs
);
// Normally parsed tokens.
else
{
tokens_
=
rhs
.
tokens_
;
// User supplied const tokens.
nameBuffer_
=
0
;
}
}
return
*
this
;
}
size_t
nameBufferSize
=
tokenCount_
;
// null terminators for tokens
for
(
Token
*
t
=
rhs
.
tokens_
;
t
!=
rhs
.
tokens_
+
tokenCount_
;
++
t
)
nameBufferSize
+=
t
->
length
;
nameBuffer_
=
(
Ch
*
)
allocator_
->
Malloc
(
nameBufferSize
*
sizeof
(
Ch
));
std
::
memcpy
(
nameBuffer_
,
rhs
.
nameBuffer_
,
nameBufferSize
*
sizeof
(
Ch
));
//@}
tokens_
=
(
Token
*
)
allocator_
->
Malloc
(
tokenCount_
*
sizeof
(
Token
));
std
::
memcpy
(
tokens_
,
rhs
.
tokens_
,
tokenCount_
*
sizeof
(
Token
));
//!@name Append token
//@{
// Adjust pointers to name buffer
std
::
ptrdiff_t
diff
=
nameBuffer_
-
rhs
.
nameBuffer_
;
for
(
Token
*
t
=
rhs
.
tokens_
;
t
!=
rhs
.
tokens_
+
tokenCount_
;
++
t
)
t
->
name
+=
diff
;
}
else
tokens_
=
rhs
.
tokens_
;
// User supplied const tokens.
//! Append a token and return a new Pointer
/*!
\param token Token to be appended.
\param allocator Allocator for the newly return Pointer.
\return A new Pointer with appended token.
*/
GenericPointer
Append
(
const
Token
&
token
,
Allocator
*
allocator
=
0
)
const
{
GenericPointer
r
;
r
.
allocator_
=
allocator
;
Ch
*
p
=
r
.
CopyFromRaw
(
*
this
,
1
,
(
token
.
length
+
1
)
*
sizeof
(
Ch
));
std
::
memcpy
(
p
,
token
.
name
,
(
token
.
length
+
1
)
*
sizeof
(
Ch
));
r
.
tokens_
[
tokenCount_
].
name
=
p
;
r
.
tokens_
[
tokenCount_
].
length
=
token
.
length
;
r
.
tokens_
[
tokenCount_
].
index
=
token
.
index
;
return
r
;
}
return
*
this
;
//! Append a name token with length, and return a new Pointer
/*!
\param name Name to be appended.
\param length Length of name.
\param allocator Allocator for the newly return Pointer.
\return A new Pointer with appended token.
*/
GenericPointer
Append
(
const
Ch
*
name
,
SizeType
length
,
Allocator
*
allocator
=
0
)
const
{
Token
token
=
{
name
,
length
,
kPointerInvalidIndex
};
return
Append
(
token
,
allocator
);
}
//@}
//! Append a name token without length, and return a new Pointer
/*!
\param name Name (const Ch*) to be appended.
\param allocator Allocator for the newly return Pointer.
\return A new Pointer with appended token.
*/
template
<
typename
T
>
RAPIDJSON_DISABLEIF_RETURN
((
internal
::
NotExpr
<
internal
::
IsSame
<
typename
internal
::
RemoveConst
<
T
>::
Type
,
Ch
>
>
),
(
GenericPointer
))
Append
(
T
*
name
,
Allocator
*
allocator
=
0
)
const
{
return
Append
(
name
,
StrLen
(
name
),
allocator
);
}
#if RAPIDJSON_HAS_STDSTRING
//! Append a name token, and return a new Pointer
/*!
\param name Name to be appended.
\param allocator Allocator for the newly return Pointer.
\return A new Pointer with appended token.
*/
GenericPointer
Append
(
const
std
::
basic_string
<
Ch
>&
name
,
Allocator
*
allocator
=
0
)
const
{
return
Append
(
name
.
c_str
(),
static_cast
<
SizeType
>
(
name
.
size
()),
allocator
);
}
#endif
//! Append a index token, and return a new Pointer
/*!
\param index Index to be appended.
\param allocator Allocator for the newly return Pointer.
\return A new Pointer with appended token.
*/
GenericPointer
Append
(
SizeType
index
,
Allocator
*
allocator
=
0
)
const
{
char
buffer
[
21
];
SizeType
length
=
(
sizeof
(
SizeType
)
==
4
?
internal
::
u32toa
(
index
,
buffer
)
:
internal
::
u64toa
(
index
,
buffer
))
-
buffer
;
buffer
[
length
]
=
'\0'
;
if
(
sizeof
(
Ch
)
==
1
)
{
Token
token
=
{
(
Ch
*
)
buffer
,
length
,
index
};
return
Append
(
token
,
allocator
);
}
else
{
Ch
name
[
21
];
for
(
size_t
i
=
0
;
i
<=
length
;
i
++
)
name
[
i
]
=
buffer
[
i
];
Token
token
=
{
name
,
length
,
index
};
return
Append
(
token
,
allocator
);
}
}
//!@name Handling Parse Error
//@{
...
...
@@ -240,7 +312,7 @@ public:
for
(
size_t
i
=
0
;
i
<
tokenCount_
;
i
++
)
{
if
(
tokens_
[
i
].
index
!=
rhs
.
tokens_
[
i
].
index
||
tokens_
[
i
].
length
!=
rhs
.
tokens_
[
i
].
length
||
std
::
memcmp
(
tokens_
[
i
].
name
,
rhs
.
tokens_
[
i
].
name
,
sizeof
(
Ch
)
*
tokens_
[
i
].
length
)
!=
0
)
(
tokens_
[
i
].
length
!=
0
&&
std
::
memcmp
(
tokens_
[
i
].
name
,
rhs
.
tokens_
[
i
].
name
,
sizeof
(
Ch
)
*
tokens_
[
i
].
length
)
!=
0
)
)
{
return
false
;
}
...
...
@@ -633,6 +705,35 @@ public:
}
private
:
//! Clone the content from rhs to this.
/*!
\param rhs Source pointer.
\param extraToken Extra tokens to be allocated.
\param extraNameBufferSize Extra name buffer size to be allocated.
\return Start of non-occupied name buffer, for storing extra names.
*/
Ch
*
CopyFromRaw
(
const
GenericPointer
&
rhs
,
size_t
extraToken
=
0
,
size_t
extraNameBufferSize
=
0
)
{
if
(
!
allocator_
)
// allocator is independently owned.
ownAllocator_
=
allocator_
=
RAPIDJSON_NEW
(
Allocator
());
size_t
nameBufferSize
=
rhs
.
tokenCount_
;
// null terminators for tokens
for
(
Token
*
t
=
rhs
.
tokens_
;
t
!=
rhs
.
tokens_
+
rhs
.
tokenCount_
;
++
t
)
nameBufferSize
+=
t
->
length
;
nameBuffer_
=
(
Ch
*
)
allocator_
->
Malloc
(
nameBufferSize
*
sizeof
(
Ch
)
+
extraNameBufferSize
);
std
::
memcpy
(
nameBuffer_
,
rhs
.
nameBuffer_
,
nameBufferSize
*
sizeof
(
Ch
));
tokenCount_
=
rhs
.
tokenCount_
+
extraToken
;
tokens_
=
(
Token
*
)
allocator_
->
Malloc
(
tokenCount_
*
sizeof
(
Token
));
std
::
memcpy
(
tokens_
,
rhs
.
tokens_
,
rhs
.
tokenCount_
*
sizeof
(
Token
));
// Adjust pointers to name buffer
std
::
ptrdiff_t
diff
=
nameBuffer_
-
rhs
.
nameBuffer_
;
for
(
Token
*
t
=
tokens_
;
t
!=
tokens_
+
rhs
.
tokenCount_
;
++
t
)
t
->
name
+=
diff
;
return
nameBuffer_
+
nameBufferSize
*
sizeof
(
Ch
);
}
//! Check whether a character should be percent-encoded.
/*!
According to RFC 3986 2.3 Unreserved Characters.
...
...
@@ -740,6 +841,8 @@ private:
*
name
++
=
c
;
}
token
.
length
=
name
-
token
.
name
;
if
(
token
.
length
==
0
)
isNumber
=
false
;
*
name
++
=
'\0'
;
// Null terminator
// Second check for index: more than one digit cannot have leading zero
...
...
test/unittest/pointertest.cpp
View file @
5dee3940
...
...
@@ -39,12 +39,22 @@ TEST(Pointer, Parse) {
EXPECT_EQ
(
0u
,
p
.
GetTokenCount
());
}
{
Pointer
p
(
"/"
);
EXPECT_TRUE
(
p
.
IsValid
());
EXPECT_EQ
(
1u
,
p
.
GetTokenCount
());
EXPECT_EQ
(
0u
,
p
.
GetTokens
()[
0
].
length
);
EXPECT_STREQ
(
""
,
p
.
GetTokens
()[
0
].
name
);
EXPECT_EQ
(
kPointerInvalidIndex
,
p
.
GetTokens
()[
0
].
index
);
}
{
Pointer
p
(
"/foo"
);
EXPECT_TRUE
(
p
.
IsValid
());
EXPECT_EQ
(
1u
,
p
.
GetTokenCount
());
EXPECT_EQ
(
3u
,
p
.
GetTokens
()[
0
].
length
);
EXPECT_STREQ
(
"foo"
,
p
.
GetTokens
()[
0
].
name
);
EXPECT_EQ
(
kPointerInvalidIndex
,
p
.
GetTokens
()[
0
].
index
);
}
#if RAPIDJSON_HAS_STDSTRING
...
...
@@ -54,6 +64,7 @@ TEST(Pointer, Parse) {
EXPECT_EQ
(
1u
,
p
.
GetTokenCount
());
EXPECT_EQ
(
3u
,
p
.
GetTokens
()[
0
].
length
);
EXPECT_STREQ
(
"foo"
,
p
.
GetTokens
()[
0
].
name
);
EXPECT_EQ
(
kPointerInvalidIndex
,
p
.
GetTokens
()[
0
].
index
);
}
#endif
...
...
@@ -63,6 +74,7 @@ TEST(Pointer, Parse) {
EXPECT_EQ
(
2u
,
p
.
GetTokenCount
());
EXPECT_EQ
(
3u
,
p
.
GetTokens
()[
0
].
length
);
EXPECT_STREQ
(
"foo"
,
p
.
GetTokens
()[
0
].
name
);
EXPECT_EQ
(
kPointerInvalidIndex
,
p
.
GetTokens
()[
0
].
index
);
EXPECT_EQ
(
1u
,
p
.
GetTokens
()[
1
].
length
);
EXPECT_STREQ
(
"0"
,
p
.
GetTokens
()[
1
].
name
);
EXPECT_EQ
(
0u
,
p
.
GetTokens
()[
1
].
index
);
...
...
@@ -481,6 +493,14 @@ TEST(Pointer, Assignment) {
EXPECT_EQ
(
1u
,
q
.
GetTokens
()[
1
].
length
);
EXPECT_STREQ
(
"0"
,
q
.
GetTokens
()[
1
].
name
);
EXPECT_EQ
(
0u
,
q
.
GetTokens
()[
1
].
index
);
q
=
q
;
EXPECT_TRUE
(
q
.
IsValid
());
EXPECT_EQ
(
2u
,
q
.
GetTokenCount
());
EXPECT_EQ
(
3u
,
q
.
GetTokens
()[
0
].
length
);
EXPECT_STREQ
(
"foo"
,
q
.
GetTokens
()[
0
].
name
);
EXPECT_EQ
(
1u
,
q
.
GetTokens
()[
1
].
length
);
EXPECT_STREQ
(
"0"
,
q
.
GetTokens
()[
1
].
name
);
EXPECT_EQ
(
0u
,
q
.
GetTokens
()[
1
].
index
);
}
// Static tokens
...
...
@@ -498,6 +518,26 @@ TEST(Pointer, Assignment) {
}
}
TEST
(
Pointer
,
Append
)
{
{
Pointer
p
;
Pointer
q
=
p
.
Append
(
"foo"
);
EXPECT_TRUE
(
Pointer
(
"/foo"
)
==
q
);
q
=
q
.
Append
(
0
);
EXPECT_TRUE
(
Pointer
(
"/foo/0"
)
==
q
);
q
=
q
.
Append
(
""
);
EXPECT_TRUE
(
Pointer
(
"/foo/0/"
)
==
q
);
}
#if RAPIDJSON_HAS_STDSTRING
{
Pointer
p
;
Pointer
q
=
p
.
Append
(
std
::
string
(
"foo"
));
EXPECT_TRUE
(
Pointer
(
"/foo"
)
==
q
);
}
#endif
}
TEST
(
Pointer
,
Equality
)
{
EXPECT_TRUE
(
Pointer
(
"/foo/0"
)
==
Pointer
(
"/foo/0"
));
EXPECT_FALSE
(
Pointer
(
"/foo/0"
)
==
Pointer
(
"/foo/1"
));
...
...
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