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
6043ad86
Unverified
Commit
6043ad86
authored
Jan 10, 2018
by
Milo Yip
Committed by
GitHub
Jan 10, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1138 from Tencent/archiver_example
Add archiver example
parents
83f149e7
f2a28ee4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
714 additions
and
0 deletions
+714
-0
CMakeLists.txt
example/CMakeLists.txt
+2
-0
archiver.cpp
example/archiver/archiver.cpp
+292
-0
archiver.h
example/archiver/archiver.h
+139
-0
archivertest.cpp
example/archiver/archivertest.cpp
+281
-0
No files found.
example/CMakeLists.txt
View file @
6043ad86
...
...
@@ -32,6 +32,8 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set
(
CMAKE_CXX_FLAGS
"
${
CMAKE_CXX_FLAGS
}
-pthread"
)
endif
()
add_executable
(
archivertest archiver/archiver.cpp archiver/archivertest.cpp
)
foreach
(
example
${
EXAMPLES
}
)
add_executable
(
${
example
}
${
example
}
/
${
example
}
.cpp
)
endforeach
()
...
...
example/archiver/archiver.cpp
0 → 100644
View file @
6043ad86
#include "archiver.h"
#include <cassert>
#include <stack>
#include "rapidjson/document.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/stringbuffer.h"
using
namespace
rapidjson
;
struct
JsonReaderStackItem
{
enum
State
{
BeforeStart
,
//!< An object/array is in the stack but it is not yet called by StartObject()/StartArray().
Started
,
//!< An object/array is called by StartObject()/StartArray().
Closed
//!< An array is closed after read all element, but before EndArray().
};
JsonReaderStackItem
(
const
Value
*
value
,
State
state
)
:
value
(
value
),
state
(
state
),
index
()
{}
const
Value
*
value
;
State
state
;
SizeType
index
;
// For array iteration
};
typedef
std
::
stack
<
JsonReaderStackItem
>
JsonReaderStack
;
#define DOCUMENT reinterpret_cast<Document*>(mDocument)
#define STACK (reinterpret_cast<JsonReaderStack*>(mStack))
#define TOP (STACK->top())
#define CURRENT (*TOP.value)
JsonReader
::
JsonReader
(
const
char
*
json
)
:
mDocument
(),
mStack
(),
mError
(
false
)
{
mDocument
=
new
Document
;
DOCUMENT
->
Parse
(
json
);
if
(
DOCUMENT
->
HasParseError
())
mError
=
true
;
else
{
mStack
=
new
JsonReaderStack
;
STACK
->
push
(
JsonReaderStackItem
(
DOCUMENT
,
JsonReaderStackItem
::
BeforeStart
));
}
}
JsonReader
::~
JsonReader
()
{
delete
DOCUMENT
;
delete
STACK
;
}
// Archive concept
JsonReader
&
JsonReader
::
StartObject
()
{
if
(
!
mError
)
{
if
(
CURRENT
.
IsObject
()
&&
TOP
.
state
==
JsonReaderStackItem
::
BeforeStart
)
TOP
.
state
=
JsonReaderStackItem
::
Started
;
else
mError
=
true
;
}
return
*
this
;
}
JsonReader
&
JsonReader
::
EndObject
()
{
if
(
!
mError
)
{
if
(
CURRENT
.
IsObject
()
&&
TOP
.
state
==
JsonReaderStackItem
::
Started
)
Next
();
else
mError
=
true
;
}
return
*
this
;
}
JsonReader
&
JsonReader
::
Member
(
const
char
*
name
)
{
if
(
!
mError
)
{
if
(
CURRENT
.
IsObject
()
&&
TOP
.
state
==
JsonReaderStackItem
::
Started
)
{
Value
::
ConstMemberIterator
memberItr
=
CURRENT
.
FindMember
(
name
);
if
(
memberItr
!=
CURRENT
.
MemberEnd
())
STACK
->
push
(
JsonReaderStackItem
(
&
memberItr
->
value
,
JsonReaderStackItem
::
BeforeStart
));
else
mError
=
true
;
}
else
mError
=
true
;
}
return
*
this
;
}
bool
JsonReader
::
HasMember
(
const
char
*
name
)
const
{
if
(
!
mError
&&
CURRENT
.
IsObject
()
&&
TOP
.
state
==
JsonReaderStackItem
::
Started
)
return
CURRENT
.
HasMember
(
name
);
return
false
;
}
JsonReader
&
JsonReader
::
StartArray
(
size_t
*
size
)
{
if
(
!
mError
)
{
if
(
CURRENT
.
IsArray
()
&&
TOP
.
state
==
JsonReaderStackItem
::
BeforeStart
)
{
TOP
.
state
=
JsonReaderStackItem
::
Started
;
if
(
size
)
*
size
=
CURRENT
.
Size
();
if
(
!
CURRENT
.
Empty
())
{
const
Value
*
value
=
&
CURRENT
[
TOP
.
index
];
STACK
->
push
(
JsonReaderStackItem
(
value
,
JsonReaderStackItem
::
BeforeStart
));
}
else
TOP
.
state
=
JsonReaderStackItem
::
Closed
;
}
else
mError
=
true
;
}
return
*
this
;
}
JsonReader
&
JsonReader
::
EndArray
()
{
if
(
!
mError
)
{
if
(
CURRENT
.
IsArray
()
&&
TOP
.
state
==
JsonReaderStackItem
::
Closed
)
Next
();
else
mError
=
true
;
}
return
*
this
;
}
JsonReader
&
JsonReader
::
operator
&
(
bool
&
b
)
{
if
(
!
mError
)
{
if
(
CURRENT
.
IsBool
())
{
b
=
CURRENT
.
GetBool
();
Next
();
}
else
mError
=
true
;
}
return
*
this
;
}
JsonReader
&
JsonReader
::
operator
&
(
unsigned
&
u
)
{
if
(
!
mError
)
{
if
(
CURRENT
.
IsUint
())
{
u
=
CURRENT
.
GetUint
();
Next
();
}
else
mError
=
true
;
}
return
*
this
;
}
JsonReader
&
JsonReader
::
operator
&
(
int
&
i
)
{
if
(
!
mError
)
{
if
(
CURRENT
.
IsInt
())
{
i
=
CURRENT
.
GetInt
();
Next
();
}
else
mError
=
true
;
}
return
*
this
;
}
JsonReader
&
JsonReader
::
operator
&
(
double
&
d
)
{
if
(
!
mError
)
{
if
(
CURRENT
.
IsNumber
())
{
d
=
CURRENT
.
GetDouble
();
Next
();
}
else
mError
=
true
;
}
return
*
this
;
}
JsonReader
&
JsonReader
::
operator
&
(
std
::
string
&
s
)
{
if
(
!
mError
)
{
if
(
CURRENT
.
IsString
())
{
s
=
CURRENT
.
GetString
();
Next
();
}
else
mError
=
true
;
}
return
*
this
;
}
JsonReader
&
JsonReader
::
SetNull
()
{
// This function is for JsonWriter only.
mError
=
true
;
return
*
this
;
}
void
JsonReader
::
Next
()
{
if
(
!
mError
)
{
assert
(
!
STACK
->
empty
());
STACK
->
pop
();
if
(
!
STACK
->
empty
()
&&
CURRENT
.
IsArray
())
{
if
(
TOP
.
state
==
JsonReaderStackItem
::
Started
)
{
// Otherwise means reading array item pass end
if
(
TOP
.
index
<
CURRENT
.
Size
()
-
1
)
{
const
Value
*
value
=
&
CURRENT
[
++
TOP
.
index
];
STACK
->
push
(
JsonReaderStackItem
(
value
,
JsonReaderStackItem
::
BeforeStart
));
}
else
TOP
.
state
=
JsonReaderStackItem
::
Closed
;
}
else
mError
=
true
;
}
}
}
#undef DOCUMENT
#undef STACK
#undef TOP
#undef CURRENT
////////////////////////////////////////////////////////////////////////////////
// JsonWriter
#define WRITER reinterpret_cast<PrettyWriter<StringBuffer>*>(mWriter)
#define STREAM reinterpret_cast<StringBuffer*>(mStream)
JsonWriter
::
JsonWriter
()
:
mWriter
(),
mStream
()
{
mStream
=
new
StringBuffer
;
mWriter
=
new
PrettyWriter
<
StringBuffer
>
(
*
STREAM
);
}
JsonWriter
::~
JsonWriter
()
{
delete
WRITER
;
delete
STREAM
;
}
const
char
*
JsonWriter
::
GetString
()
const
{
return
STREAM
->
GetString
();
}
JsonWriter
&
JsonWriter
::
StartObject
()
{
WRITER
->
StartObject
();
return
*
this
;
}
JsonWriter
&
JsonWriter
::
EndObject
()
{
WRITER
->
EndObject
();
return
*
this
;
}
JsonWriter
&
JsonWriter
::
Member
(
const
char
*
name
)
{
WRITER
->
String
(
name
,
static_cast
<
SizeType
>
(
strlen
(
name
)));
return
*
this
;
}
bool
JsonWriter
::
HasMember
(
const
char
*
)
const
{
// This function is for JsonReader only.
assert
(
false
);
return
false
;
}
JsonWriter
&
JsonWriter
::
StartArray
(
size_t
*
)
{
WRITER
->
StartArray
();
return
*
this
;
}
JsonWriter
&
JsonWriter
::
EndArray
()
{
WRITER
->
EndArray
();
return
*
this
;
}
JsonWriter
&
JsonWriter
::
operator
&
(
bool
&
b
)
{
WRITER
->
Bool
(
b
);
return
*
this
;
}
JsonWriter
&
JsonWriter
::
operator
&
(
unsigned
&
u
)
{
WRITER
->
Uint
(
u
);
return
*
this
;
}
JsonWriter
&
JsonWriter
::
operator
&
(
int
&
i
)
{
WRITER
->
Int
(
i
);
return
*
this
;
}
JsonWriter
&
JsonWriter
::
operator
&
(
double
&
d
)
{
WRITER
->
Double
(
d
);
return
*
this
;
}
JsonWriter
&
JsonWriter
::
operator
&
(
std
::
string
&
s
)
{
WRITER
->
String
(
s
.
c_str
(),
static_cast
<
SizeType
>
(
s
.
size
()));
return
*
this
;
}
JsonWriter
&
JsonWriter
::
SetNull
()
{
WRITER
->
Null
();
return
*
this
;
}
#undef STREAM
#undef WRITER
example/archiver/archiver.h
0 → 100644
View file @
6043ad86
#ifndef ARCHIVER_H_
#define ARCHIVER_H_
#include <cstddef>
#include <string>
/**
\class Archiver
\brief Archiver concept
Archiver can be a reader or writer for serialization or deserialization respectively.
class Archiver {
public:
/// \returns true if the archiver is in normal state. false if it has errors.
operator bool() const;
/// Starts an object
Archiver& StartObject();
/// After calling StartObject(), assign a member with a name
Archiver& Member(const char* name);
/// After calling StartObject(), check if a member presents
bool HasMember(const char* name) const;
/// Ends an object
Archiver& EndObject();
/// Starts an array
/// \param size If Archiver::IsReader is true, the size of array is written.
Archiver& StartArray(size_t* size = 0);
/// Ends an array
Archiver& EndArray();
/// Read/Write primitive types.
Archiver& operator&(bool& b);
Archiver& operator&(unsigned& u);
Archiver& operator&(int& i);
Archiver& operator&(double& d);
Archiver& operator&(std::string& s);
/// Write primitive types.
Archiver& SetNull();
//! Whether it is a reader.
static const bool IsReader;
//! Whether it is a writer.
static const bool IsWriter;
};
*/
/// Represents a JSON reader which implements Archiver concept.
class
JsonReader
{
public
:
/// Constructor.
/**
\param json A non-const source json string for in-situ parsing.
\note in-situ means the source JSON string will be modified after parsing.
*/
JsonReader
(
const
char
*
json
);
/// Destructor.
~
JsonReader
();
// Archive concept
operator
bool
()
const
{
return
!
mError
;
}
JsonReader
&
StartObject
();
JsonReader
&
Member
(
const
char
*
name
);
bool
HasMember
(
const
char
*
name
)
const
;
JsonReader
&
EndObject
();
JsonReader
&
StartArray
(
size_t
*
size
=
nullptr
);
JsonReader
&
EndArray
();
JsonReader
&
operator
&
(
bool
&
b
);
JsonReader
&
operator
&
(
unsigned
&
u
);
JsonReader
&
operator
&
(
int
&
i
);
JsonReader
&
operator
&
(
double
&
d
);
JsonReader
&
operator
&
(
std
::
string
&
s
);
JsonReader
&
SetNull
();
static
const
bool
IsReader
=
true
;
static
const
bool
IsWriter
=
!
IsReader
;
private
:
void
Next
();
// PIMPL
void
*
mDocument
;
///< DOM result of parsing.
void
*
mStack
;
///< Stack for iterating the DOM
bool
mError
;
///< Whether an error is occured.
};
class
JsonWriter
{
public
:
/// Constructor.
JsonWriter
();
/// Destructor.
~
JsonWriter
();
/// Obtains the serialized JSON string.
const
char
*
GetString
()
const
;
// Archive concept
operator
bool
()
const
{
return
true
;
}
JsonWriter
&
StartObject
();
JsonWriter
&
Member
(
const
char
*
name
);
bool
HasMember
(
const
char
*
name
)
const
;
JsonWriter
&
EndObject
();
JsonWriter
&
StartArray
(
size_t
*
size
=
0
);
JsonWriter
&
EndArray
();
JsonWriter
&
operator
&
(
bool
&
b
);
JsonWriter
&
operator
&
(
unsigned
&
u
);
JsonWriter
&
operator
&
(
int
&
i
);
JsonWriter
&
operator
&
(
double
&
d
);
JsonWriter
&
operator
&
(
std
::
string
&
s
);
JsonWriter
&
SetNull
();
static
const
bool
IsReader
=
false
;
static
const
bool
IsWriter
=
!
IsReader
;
private
:
// PIMPL idiom
void
*
mWriter
;
///< JSON writer.
void
*
mStream
;
///< Stream buffer.
};
#endif // ARCHIVER_H__
example/archiver/archivertest.cpp
0 → 100644
View file @
6043ad86
#include "archiver.h"
#include <iostream>
#include <vector>
//////////////////////////////////////////////////////////////////////////////
// Test1: simple object
struct
Student
{
std
::
string
name
;
unsigned
age
;
double
height
;
bool
canSwim
;
};
template
<
typename
Archiver
>
Archiver
&
operator
&
(
Archiver
&
ar
,
Student
&
s
)
{
ar
.
StartObject
();
ar
.
Member
(
"name"
)
&
s
.
name
;
ar
.
Member
(
"age"
)
&
s
.
age
;
ar
.
Member
(
"height"
)
&
s
.
height
;
ar
.
Member
(
"canSwim"
)
&
s
.
canSwim
;
return
ar
.
EndObject
();
}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
Student
&
s
)
{
return
os
<<
s
.
name
<<
" "
<<
s
.
age
<<
" "
<<
s
.
height
<<
" "
<<
s
.
canSwim
;
}
void
test1
()
{
std
::
string
json
;
// Serialize
{
Student
s
=
{
"Lua"
,
9
,
150.5
,
true
};
JsonWriter
writer
;
writer
&
s
;
json
=
writer
.
GetString
();
std
::
cout
<<
json
<<
std
::
endl
;
}
// Deserialize
{
Student
s
;
JsonReader
reader
(
json
.
c_str
());
reader
&
s
;
std
::
cout
<<
s
<<
std
::
endl
;
}
}
//////////////////////////////////////////////////////////////////////////////
// Test2: std::vector <=> JSON array
//
// You can map a JSON array to other data structures as well
struct
Group
{
std
::
string
groupName
;
std
::
vector
<
Student
>
students
;
};
template
<
typename
Archiver
>
Archiver
&
operator
&
(
Archiver
&
ar
,
Group
&
g
)
{
ar
.
StartObject
();
ar
.
Member
(
"groupName"
);
ar
&
g
.
groupName
;
ar
.
Member
(
"students"
);
size_t
studentCount
=
g
.
students
.
size
();
ar
.
StartArray
(
&
studentCount
);
if
(
ar
.
IsReader
)
g
.
students
.
resize
(
studentCount
);
for
(
size_t
i
=
0
;
i
<
studentCount
;
i
++
)
ar
&
g
.
students
[
i
];
ar
.
EndArray
();
return
ar
.
EndObject
();
}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
Group
&
g
)
{
os
<<
g
.
groupName
<<
std
::
endl
;
for
(
std
::
vector
<
Student
>::
const_iterator
itr
=
g
.
students
.
begin
();
itr
!=
g
.
students
.
end
();
++
itr
)
os
<<
*
itr
<<
std
::
endl
;
return
os
;
}
void
test2
()
{
std
::
string
json
;
// Serialize
{
Group
g
;
g
.
groupName
=
"Rainbow"
;
Student
s1
=
{
"Lua"
,
9
,
150.5
,
true
};
Student
s2
=
{
"Mio"
,
7
,
120.0
,
false
};
g
.
students
.
push_back
(
s1
);
g
.
students
.
push_back
(
s2
);
JsonWriter
writer
;
writer
&
g
;
json
=
writer
.
GetString
();
std
::
cout
<<
json
<<
std
::
endl
;
}
// Deserialize
{
Group
g
;
JsonReader
reader
(
json
.
c_str
());
reader
&
g
;
std
::
cout
<<
g
<<
std
::
endl
;
}
}
//////////////////////////////////////////////////////////////////////////////
// Test3: polymorphism & friend
//
// Note that friendship is not necessary but make things simpler.
class
Shape
{
public
:
virtual
~
Shape
()
{}
virtual
const
char
*
GetType
()
const
=
0
;
virtual
void
Print
(
std
::
ostream
&
os
)
const
=
0
;
protected
:
Shape
()
{}
Shape
(
double
x
,
double
y
)
:
x_
(
x
),
y_
(
y
)
{}
template
<
typename
Archiver
>
friend
Archiver
&
operator
&
(
Archiver
&
ar
,
Shape
&
s
);
double
x_
,
y_
;
};
template
<
typename
Archiver
>
Archiver
&
operator
&
(
Archiver
&
ar
,
Shape
&
s
)
{
ar
.
Member
(
"x"
)
&
s
.
x_
;
ar
.
Member
(
"y"
)
&
s
.
y_
;
return
ar
;
}
class
Circle
:
public
Shape
{
public
:
Circle
()
{}
Circle
(
double
x
,
double
y
,
double
radius
)
:
Shape
(
x
,
y
),
radius_
(
radius
)
{}
~
Circle
()
{}
const
char
*
GetType
()
const
{
return
"Circle"
;
}
void
Print
(
std
::
ostream
&
os
)
const
{
os
<<
"Circle ("
<<
x_
<<
", "
<<
y_
<<
")"
<<
" radius = "
<<
radius_
;
}
private
:
template
<
typename
Archiver
>
friend
Archiver
&
operator
&
(
Archiver
&
ar
,
Circle
&
c
);
double
radius_
;
};
template
<
typename
Archiver
>
Archiver
&
operator
&
(
Archiver
&
ar
,
Circle
&
c
)
{
ar
&
static_cast
<
Shape
&>
(
c
);
ar
.
Member
(
"radius"
)
&
c
.
radius_
;
return
ar
;
}
class
Box
:
public
Shape
{
public
:
Box
()
{}
Box
(
double
x
,
double
y
,
double
width
,
double
height
)
:
Shape
(
x
,
y
),
width_
(
width
),
height_
(
height
)
{}
~
Box
()
{}
const
char
*
GetType
()
const
{
return
"Box"
;
}
void
Print
(
std
::
ostream
&
os
)
const
{
os
<<
"Box ("
<<
x_
<<
", "
<<
y_
<<
")"
<<
" width = "
<<
width_
<<
" height = "
<<
height_
;
}
private
:
template
<
typename
Archiver
>
friend
Archiver
&
operator
&
(
Archiver
&
ar
,
Box
&
b
);
double
width_
,
height_
;
};
template
<
typename
Archiver
>
Archiver
&
operator
&
(
Archiver
&
ar
,
Box
&
b
)
{
ar
&
static_cast
<
Shape
&>
(
b
);
ar
.
Member
(
"width"
)
&
b
.
width_
;
ar
.
Member
(
"height"
)
&
b
.
height_
;
return
ar
;
}
class
Canvas
{
public
:
Canvas
()
{}
~
Canvas
()
{
Clear
();
}
void
Clear
()
{
for
(
std
::
vector
<
Shape
*>::
iterator
itr
=
shapes_
.
begin
();
itr
!=
shapes_
.
end
();
++
itr
)
delete
*
itr
;
}
void
AddShape
(
Shape
*
shape
)
{
shapes_
.
push_back
(
shape
);
}
void
Print
(
std
::
ostream
&
os
)
{
for
(
std
::
vector
<
Shape
*>::
iterator
itr
=
shapes_
.
begin
();
itr
!=
shapes_
.
end
();
++
itr
)
{
(
*
itr
)
->
Print
(
os
);
std
::
cout
<<
std
::
endl
;
}
}
private
:
template
<
typename
Archiver
>
friend
Archiver
&
operator
&
(
Archiver
&
ar
,
Canvas
&
c
);
std
::
vector
<
Shape
*>
shapes_
;
};
template
<
typename
Archiver
>
Archiver
&
operator
&
(
Archiver
&
ar
,
Shape
*&
shape
)
{
std
::
string
type
=
ar
.
IsReader
?
""
:
shape
->
GetType
();
ar
.
StartObject
();
ar
.
Member
(
"type"
)
&
type
;
if
(
type
==
"Circle"
)
{
if
(
ar
.
IsReader
)
shape
=
new
Circle
;
ar
&
static_cast
<
Circle
&>
(
*
shape
);
}
else
if
(
type
==
"Box"
)
{
if
(
ar
.
IsReader
)
shape
=
new
Box
;
ar
&
static_cast
<
Box
&>
(
*
shape
);
}
return
ar
.
EndObject
();
}
template
<
typename
Archiver
>
Archiver
&
operator
&
(
Archiver
&
ar
,
Canvas
&
c
)
{
size_t
shapeCount
=
c
.
shapes_
.
size
();
ar
.
StartArray
(
&
shapeCount
);
if
(
ar
.
IsReader
)
{
c
.
Clear
();
c
.
shapes_
.
resize
(
shapeCount
);
}
for
(
size_t
i
=
0
;
i
<
shapeCount
;
i
++
)
ar
&
c
.
shapes_
[
i
];
return
ar
.
EndArray
();
}
void
test3
()
{
std
::
string
json
;
// Serialize
{
Canvas
c
;
c
.
AddShape
(
new
Circle
(
1.0
,
2.0
,
3.0
));
c
.
AddShape
(
new
Box
(
4.0
,
5.0
,
6.0
,
7.0
));
JsonWriter
writer
;
writer
&
c
;
json
=
writer
.
GetString
();
std
::
cout
<<
json
<<
std
::
endl
;
}
// Deserialize
{
Canvas
c
;
JsonReader
reader
(
json
.
c_str
());
reader
&
c
;
c
.
Print
(
std
::
cout
);
}
}
//////////////////////////////////////////////////////////////////////////////
int
main
()
{
test1
();
test2
();
test3
();
}
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