| 7a956470 |
sago007 |
2016-02-14 17:09 |
1 |
/*! \file json.hpp |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
2 |
\brief JSON input and output archives */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
3 |
/* |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
4 |
Copyright (c) 2014, Randolph Voorhies, Shane Grant |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
5 |
All rights reserved. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
6 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
7 |
Redistribution and use in source and binary forms, with or without |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
8 |
modification, are permitted provided that the following conditions are met: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
9 |
* Redistributions of source code must retain the above copyright |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
10 |
notice, this list of conditions and the following disclaimer. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
11 |
* Redistributions in binary form must reproduce the above copyright |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
12 |
notice, this list of conditions and the following disclaimer in the |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
13 |
documentation and/or other materials provided with the distribution. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
14 |
* Neither the name of cereal nor the |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
15 |
names of its contributors may be used to endorse or promote products |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
16 |
derived from this software without specific prior written permission. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
17 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
18 |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
19 |
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
20 |
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
21 |
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
22 |
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
23 |
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
24 |
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
25 |
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
26 |
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
27 |
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
28 |
*/ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
29 |
#ifndef CEREAL_ARCHIVES_JSON_HPP_ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
30 |
#define CEREAL_ARCHIVES_JSON_HPP_ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
31 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
32 |
#include <cereal/cereal.hpp> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
33 |
#include <cereal/details/util.hpp> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
34 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
35 |
namespace cereal |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
36 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
37 |
//! An exception thrown when rapidjson fails an internal assertion |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
38 |
/*! @ingroup Utility */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
39 |
struct RapidJSONException : Exception |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
40 |
{ RapidJSONException( const char * what_ ) : Exception( what_ ) {} }; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
41 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
42 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
43 |
// Override rapidjson assertions to throw exceptions by default |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
44 |
#ifndef RAPIDJSON_ASSERT |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
45 |
#define RAPIDJSON_ASSERT(x) if(!(x)){ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
46 |
throw ::cereal::RapidJSONException("rapidjson internal assertion failure: " #x); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
47 |
#endif // RAPIDJSON_ASSERT |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
48 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
49 |
#include <cereal/external/rapidjson/prettywriter.h> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
50 |
#include <cereal/external/rapidjson/genericstream.h> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
51 |
#include <cereal/external/rapidjson/reader.h> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
52 |
#include <cereal/external/rapidjson/document.h> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
53 |
#include <cereal/external/base64.hpp> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
54 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
55 |
#include <limits> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
56 |
#include <sstream> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
57 |
#include <stack> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
58 |
#include <vector> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
59 |
#include <string> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
60 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
61 |
namespace cereal |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
62 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
63 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
64 |
//! An output archive designed to save data to JSON |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
65 |
/*! This archive uses RapidJSON to build serialie data to JSON. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
66 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
67 |
JSON archives provides a human readable output but at decreased |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
68 |
performance (both in time and space) compared to binary archives. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
69 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
70 |
JSON benefits greatly from name-value pairs, which if present, will |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
71 |
name the nodes in the output. If these are not present, each level |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
72 |
of the output will be given an automatically generated delimited name. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
73 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
74 |
The precision of the output archive controls the number of decimals output |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
75 |
for floating point numbers and should be sufficiently large (i.e. at least 20) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
76 |
if there is a desire to have binary equality between the numbers output and |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
77 |
those read in. In general you should expect a loss of precision when going |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
78 |
from floating point to text and back. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
79 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
80 |
JSON archives do not output the size information for any dynamically sized structure |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
81 |
and instead infer it from the number of children for a node. This means that data |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
82 |
can be hand edited for dynamic sized structures and will still be readable. This |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
83 |
is accomplished through the cereal::SizeTag object, which will cause the archive |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
84 |
to output the data as a JSON array (e.g. marked by [] instead of {}), which indicates |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
85 |
that the container is variable sized and may be edited. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
86 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
87 |
\ingroup Archives */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
88 |
class JSONOutputArchive : public OutputArchive<JSONOutputArchive>, public traits::TextArchive |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
89 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
90 |
enum class NodeType { StartObject, InObject, StartArray, InArray }; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
91 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
92 |
typedef rapidjson::GenericWriteStream WriteStream; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
93 |
typedef rapidjson::PrettyWriter<WriteStream> JSONWriter; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
94 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
95 |
public: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
96 |
/*! @name Common Functionality |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
97 |
Common use cases for directly interacting with an JSONOutputArchive */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
98 |
//! @{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
99 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
100 |
//! A class containing various advanced options for the JSON archive |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
101 |
class Options |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
102 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
103 |
public: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
104 |
//! Default options |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
105 |
static Options Default(){ return Options(); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
106 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
107 |
//! Default options with no indentation |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
108 |
static Options NoIndent(){ return Options( std::numeric_limits<double>::max_digits10, IndentChar::space, 0 ); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
109 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
110 |
//! The character to use for indenting |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
111 |
enum class IndentChar : char |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
112 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
113 |
space = ' ', |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
114 |
tab = '\t', |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
115 |
newline = '\n', |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
116 |
carriage_return = '\r' |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
117 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
118 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
119 |
//! Specify specific options for the JSONOutputArchive |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
120 |
/*! @param precision The precision used for floating point numbers |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
121 |
@param indentChar The type of character to indent with |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
122 |
@param indentLength The number of indentChar to use for indentation |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
123 |
(0 corresponds to no indentation) */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
124 |
explicit Options( int precision = std::numeric_limits<double>::max_digits10, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
125 |
IndentChar indentChar = IndentChar::space, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
126 |
unsigned int indentLength = 4 ) : |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
127 |
itsPrecision( precision ), |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
128 |
itsIndentChar( static_cast<char>(indentChar) ), |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
129 |
itsIndentLength( indentLength ) { } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
130 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
131 |
private: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
132 |
friend class JSONOutputArchive; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
133 |
int itsPrecision; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
134 |
char itsIndentChar; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
135 |
unsigned int itsIndentLength; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
136 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
137 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
138 |
//! Construct, outputting to the provided stream |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
139 |
/*! @param stream The stream to output to. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
140 |
@param options The JSON specific options to use. See the Options struct |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
141 |
for the values of default parameters */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
142 |
JSONOutputArchive(std::ostream & stream, Options const & options = Options::Default() ) : |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
143 |
OutputArchive<JSONOutputArchive>(this), |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
144 |
itsWriteStream(stream), |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
145 |
itsWriter(itsWriteStream, options.itsPrecision), |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
146 |
itsNextName(nullptr) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
147 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
148 |
itsWriter.SetIndent( options.itsIndentChar, options.itsIndentLength ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
149 |
itsNameCounter.push(0); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
150 |
itsNodeStack.push(NodeType::StartObject); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
151 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
152 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
153 |
//! Destructor, flushes the JSON |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
154 |
~JSONOutputArchive() |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
155 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
156 |
if (itsNodeStack.top() == NodeType::InObject) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
157 |
itsWriter.EndObject(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
158 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
159 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
160 |
//! Saves some binary data, encoded as a base64 string, with an optional name |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
161 |
/*! This will create a new node, optionally named, and insert a value that consists of |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
162 |
the data encoded as a base64 string */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
163 |
void saveBinaryValue( const void * data, size_t size, const char * name = nullptr ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
164 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
165 |
setNextName( name ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
166 |
writeName(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
167 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
168 |
auto base64string = base64::encode( reinterpret_cast<const unsigned char *>( data ), size ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
169 |
saveValue( base64string ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
170 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
171 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
172 |
//! @} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
173 |
/*! @name Internal Functionality |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
174 |
Functionality designed for use by those requiring control over the inner mechanisms of |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
175 |
the JSONOutputArchive */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
176 |
//! @{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
177 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
178 |
//! Starts a new node in the JSON output |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
179 |
/*! The node can optionally be given a name by calling setNextName prior |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
180 |
to creating the node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
181 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
182 |
Nodes only need to be started for types that are themselves objects or arrays */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
183 |
void startNode() |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
184 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
185 |
writeName(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
186 |
itsNodeStack.push(NodeType::StartObject); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
187 |
itsNameCounter.push(0); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
188 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
189 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
190 |
//! Designates the most recently added node as finished |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
191 |
void finishNode() |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
192 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
193 |
// if we ended up serializing an empty object or array, writeName |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
194 |
// will never have been called - so start and then immediately end |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
195 |
// the object/array. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
196 |
// |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
197 |
// We'll also end any object/arrays we happen to be in |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
198 |
switch(itsNodeStack.top()) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
199 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
200 |
case NodeType::StartArray: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
201 |
itsWriter.StartArray(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
202 |
case NodeType::InArray: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
203 |
itsWriter.EndArray(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
204 |
break; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
205 |
case NodeType::StartObject: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
206 |
itsWriter.StartObject(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
207 |
case NodeType::InObject: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
208 |
itsWriter.EndObject(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
209 |
break; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
210 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
211 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
212 |
itsNodeStack.pop(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
213 |
itsNameCounter.pop(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
214 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
215 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
216 |
//! Sets the name for the next node created with startNode |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
217 |
void setNextName( const char * name ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
218 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
219 |
itsNextName = name; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
220 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
221 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
222 |
//! Saves a bool to the current node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
223 |
void saveValue(bool b) { itsWriter.Bool_(b); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
224 |
//! Saves an int to the current node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
225 |
void saveValue(int i) { itsWriter.Int(i); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
226 |
//! Saves a uint to the current node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
227 |
void saveValue(unsigned u) { itsWriter.Uint(u); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
228 |
//! Saves an int64 to the current node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
229 |
void saveValue(int64_t i64) { itsWriter.Int64(i64); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
230 |
//! Saves a uint64 to the current node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
231 |
void saveValue(uint64_t u64) { itsWriter.Uint64(u64); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
232 |
//! Saves a double to the current node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
233 |
void saveValue(double d) { itsWriter.Double(d); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
234 |
//! Saves a string to the current node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
235 |
void saveValue(std::string const & s) { itsWriter.String(s.c_str(), static_cast<rapidjson::SizeType>( s.size() )); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
236 |
//! Saves a const char * to the current node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
237 |
void saveValue(char const * s) { itsWriter.String(s); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
238 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
239 |
private: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
240 |
// Some compilers/OS have difficulty disambiguating the above for various flavors of longs, so we provide |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
241 |
// special overloads to handle these cases. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
242 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
243 |
//! 32 bit signed long saving to current node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
244 |
template <class T, traits::EnableIf<sizeof(T) == sizeof(std::int32_t), |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
245 |
std::is_signed<T>::value> = traits::sfinae> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
246 |
void saveLong(T l){ saveValue( static_cast<std::int32_t>( l ) ); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
247 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
248 |
//! non 32 bit signed long saving to current node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
249 |
template <class T, traits::EnableIf<sizeof(T) != sizeof(std::int32_t), |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
250 |
std::is_signed<T>::value> = traits::sfinae> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
251 |
void saveLong(T l){ saveValue( static_cast<std::int64_t>( l ) ); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
252 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
253 |
//! 32 bit unsigned long saving to current node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
254 |
template <class T, traits::EnableIf<sizeof(T) == sizeof(std::int32_t), |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
255 |
std::is_unsigned<T>::value> = traits::sfinae> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
256 |
void saveLong(T lu){ saveValue( static_cast<std::uint32_t>( lu ) ); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
257 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
258 |
//! non 32 bit unsigned long saving to current node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
259 |
template <class T, traits::EnableIf<sizeof(T) != sizeof(std::int32_t), |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
260 |
std::is_unsigned<T>::value> = traits::sfinae> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
261 |
void saveLong(T lu){ saveValue( static_cast<std::uint64_t>( lu ) ); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
262 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
263 |
public: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
264 |
#ifdef _MSC_VER |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
265 |
//! MSVC only long overload to current node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
266 |
void saveValue( unsigned long lu ){ saveLong( lu ); }; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
267 |
#else // _MSC_VER |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
268 |
//! Serialize a long if it would not be caught otherwise |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
269 |
template <class T, traits::EnableIf<std::is_same<T, long>::value, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
270 |
!std::is_same<T, std::int32_t>::value, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
271 |
!std::is_same<T, std::int64_t>::value> = traits::sfinae> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
272 |
void saveValue( T t ){ saveLong( t ); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
273 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
274 |
//! Serialize an unsigned long if it would not be caught otherwise |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
275 |
template <class T, traits::EnableIf<std::is_same<T, unsigned long>::value, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
276 |
!std::is_same<T, std::uint32_t>::value, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
277 |
!std::is_same<T, std::uint64_t>::value> = traits::sfinae> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
278 |
void saveValue( T t ){ saveLong( t ); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
279 |
#endif // _MSC_VER |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
280 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
281 |
//! Save exotic arithmetic as strings to current node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
282 |
/*! Handles long long (if distinct from other types), unsigned long (if distinct), and long double */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
283 |
template <class T, traits::EnableIf<std::is_arithmetic<T>::value, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
284 |
!std::is_same<T, long>::value, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
285 |
!std::is_same<T, unsigned long>::value, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
286 |
!std::is_same<T, std::int64_t>::value, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
287 |
!std::is_same<T, std::uint64_t>::value, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
288 |
(sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long))> = traits::sfinae> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
289 |
void saveValue(T const & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
290 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
291 |
std::stringstream ss; ss.precision( std::numeric_limits<long double>::max_digits10 ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
292 |
ss << t; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
293 |
saveValue( ss.str() ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
294 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
295 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
296 |
//! Write the name of the upcoming node and prepare object/array state |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
297 |
/*! Since writeName is called for every value that is output, regardless of |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
298 |
whether it has a name or not, it is the place where we will do a deferred |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
299 |
check of our node state and decide whether we are in an array or an object. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
300 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
301 |
The general workflow of saving to the JSON archive is: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
302 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
303 |
1. (optional) Set the name for the next node to be created, usually done by an NVP |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
304 |
2. Start the node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
305 |
3. (if there is data to save) Write the name of the node (this function) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
306 |
4. (if there is data to save) Save the data (with saveValue) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
307 |
5. Finish the node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
308 |
*/ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
309 |
void writeName() |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
310 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
311 |
NodeType const & nodeType = itsNodeStack.top(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
312 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
313 |
// Start up either an object or an array, depending on state |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
314 |
if(nodeType == NodeType::StartArray) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
315 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
316 |
itsWriter.StartArray(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
317 |
itsNodeStack.top() = NodeType::InArray; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
318 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
319 |
else if(nodeType == NodeType::StartObject) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
320 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
321 |
itsNodeStack.top() = NodeType::InObject; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
322 |
itsWriter.StartObject(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
323 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
324 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
325 |
// Array types do not output names |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
326 |
if(nodeType == NodeType::InArray) return; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
327 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
328 |
if(itsNextName == nullptr) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
329 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
330 |
std::string name = "value" + std::to_string( itsNameCounter.top()++ ) + "\0"; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
331 |
saveValue(name); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
332 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
333 |
else |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
334 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
335 |
saveValue(itsNextName); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
336 |
itsNextName = nullptr; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
337 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
338 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
339 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
340 |
//! Designates that the current node should be output as an array, not an object |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
341 |
void makeArray() |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
342 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
343 |
itsNodeStack.top() = NodeType::StartArray; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
344 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
345 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
346 |
//! @} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
347 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
348 |
private: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
349 |
WriteStream itsWriteStream; //!< Rapidjson write stream |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
350 |
JSONWriter itsWriter; //!< Rapidjson writer |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
351 |
char const * itsNextName; //!< The next name |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
352 |
std::stack<uint32_t> itsNameCounter; //!< Counter for creating unique names for unnamed nodes |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
353 |
std::stack<NodeType> itsNodeStack; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
354 |
}; // JSONOutputArchive |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
355 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
356 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
357 |
//! An input archive designed to load data from JSON |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
358 |
/*! This archive uses RapidJSON to read in a JSON archive. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
359 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
360 |
Input JSON should have been produced by the JSONOutputArchive. Data can |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
361 |
only be added to dynamically sized containers (marked by JSON arrays) - |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
362 |
the input archive will determine their size by looking at the number of child nodes. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
363 |
Only JSON originating from a JSONOutputArchive is officially supported, but data |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
364 |
from other sources may work if properly formatted. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
365 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
366 |
The JSONInputArchive does not require that nodes are loaded in the same |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
367 |
order they were saved by JSONOutputArchive. Using name value pairs (NVPs), |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
368 |
it is possible to load in an out of order fashion or otherwise skip/select |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
369 |
specific nodes to load. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
370 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
371 |
The default behavior of the input archive is to read sequentially starting |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
372 |
with the first node and exploring its children. When a given NVP does |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
373 |
not match the read in name for a node, the archive will search for that |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
374 |
node at the current level and load it if it exists. After loading an out of |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
375 |
order node, the archive will then proceed back to loading sequentially from |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
376 |
its new position. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
377 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
378 |
Consider this simple example where loading of some data is skipped: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
379 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
380 |
@code{cpp} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
381 |
// imagine the input file has someData(1-9) saved in order at the top level node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
382 |
ar( someData1, someData2, someData3 ); // XML loads in the order it sees in the file |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
383 |
ar( cereal::make_nvp( "hello", someData6 ) ); // NVP given does not |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
384 |
// match expected NVP name, so we search |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
385 |
// for the given NVP and load that value |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
386 |
ar( someData7, someData8, someData9 ); // with no NVP given, loading resumes at its |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
387 |
// current location, proceeding sequentially |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
388 |
@endcode |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
389 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
390 |
\ingroup Archives */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
391 |
class JSONInputArchive : public InputArchive<JSONInputArchive>, public traits::TextArchive |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
392 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
393 |
private: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
394 |
typedef rapidjson::GenericReadStream ReadStream; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
395 |
typedef rapidjson::GenericValue<rapidjson::UTF8<>> JSONValue; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
396 |
typedef JSONValue::ConstMemberIterator MemberIterator; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
397 |
typedef JSONValue::ConstValueIterator ValueIterator; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
398 |
typedef rapidjson::Document::GenericValue GenericValue; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
399 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
400 |
public: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
401 |
/*! @name Common Functionality |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
402 |
Common use cases for directly interacting with an JSONInputArchive */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
403 |
//! @{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
404 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
405 |
//! Construct, reading from the provided stream |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
406 |
/*! @param stream The stream to read from */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
407 |
JSONInputArchive(std::istream & stream) : |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
408 |
InputArchive<JSONInputArchive>(this), |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
409 |
itsNextName( nullptr ), |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
410 |
itsReadStream(stream) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
411 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
412 |
itsDocument.ParseStream<0>(itsReadStream); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
413 |
itsIteratorStack.emplace_back(itsDocument.MemberBegin(), itsDocument.MemberEnd()); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
414 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
415 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
416 |
//! Loads some binary data, encoded as a base64 string |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
417 |
/*! This will automatically start and finish a node to load the data, and can be called directly by |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
418 |
users. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
419 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
420 |
Note that this follows the same ordering rules specified in the class description in regards |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
421 |
to loading in/out of order */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
422 |
void loadBinaryValue( void * data, size_t size, const char * name = nullptr ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
423 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
424 |
itsNextName = name; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
425 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
426 |
std::string encoded; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
427 |
loadValue( encoded ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
428 |
auto decoded = base64::decode( encoded ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
429 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
430 |
if( size != decoded.size() ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
431 |
throw Exception("Decoded binary data size does not match specified size"); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
432 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
433 |
std::memcpy( data, decoded.data(), decoded.size() ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
434 |
itsNextName = nullptr; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
435 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
436 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
437 |
private: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
438 |
//! @} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
439 |
/*! @name Internal Functionality |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
440 |
Functionality designed for use by those requiring control over the inner mechanisms of |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
441 |
the JSONInputArchive */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
442 |
//! @{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
443 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
444 |
//! An internal iterator that handles both array and object types |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
445 |
/*! This class is a variant and holds both types of iterators that |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
446 |
rapidJSON supports - one for arrays and one for objects. */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
447 |
class Iterator |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
448 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
449 |
public: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
450 |
Iterator() : itsIndex( 0 ), itsType(Null_) {} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
451 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
452 |
Iterator(MemberIterator begin, MemberIterator end) : |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
453 |
itsMemberItBegin(begin), itsMemberItEnd(end), itsIndex(0), itsType(Member) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
454 |
{ } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
455 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
456 |
Iterator(ValueIterator begin, ValueIterator end) : |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
457 |
itsValueItBegin(begin), itsValueItEnd(end), itsIndex(0), itsType(Value) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
458 |
{ } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
459 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
460 |
//! Advance to the next node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
461 |
Iterator & operator++() |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
462 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
463 |
++itsIndex; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
464 |
return *this; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
465 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
466 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
467 |
//! Get the value of the current node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
468 |
GenericValue const & value() |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
469 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
470 |
switch(itsType) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
471 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
472 |
case Value : return itsValueItBegin[itsIndex]; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
473 |
case Member: return itsMemberItBegin[itsIndex].value; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
474 |
default: throw cereal::Exception("Invalid Iterator Type!"); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
475 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
476 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
477 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
478 |
//! Get the name of the current node, or nullptr if it has no name |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
479 |
const char * name() const |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
480 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
481 |
if( itsType == Member && (itsMemberItBegin + itsIndex) != itsMemberItEnd ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
482 |
return itsMemberItBegin[itsIndex].name.GetString(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
483 |
else |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
484 |
return nullptr; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
485 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
486 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
487 |
//! Adjust our position such that we are at the node with the given name |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
488 |
/*! @throws Exception if no such named node exists */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
489 |
inline void search( const char * searchName ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
490 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
491 |
const auto len = std::strlen( searchName ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
492 |
size_t index = 0; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
493 |
for( auto it = itsMemberItBegin; it != itsMemberItEnd; ++it, ++index ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
494 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
495 |
const auto currentName = it->name.GetString(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
496 |
if( ( std::strncmp( searchName, currentName, len ) == 0 ) && |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
497 |
( std::strlen( currentName ) == len ) ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
498 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
499 |
itsIndex = index; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
500 |
return; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
501 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
502 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
503 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
504 |
throw Exception("JSON Parsing failed - provided NVP not found"); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
505 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
506 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
507 |
private: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
508 |
MemberIterator itsMemberItBegin, itsMemberItEnd; //!< The member iterator (object) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
509 |
ValueIterator itsValueItBegin, itsValueItEnd; //!< The value iterator (array) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
510 |
size_t itsIndex; //!< The current index of this iterator |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
511 |
enum Type {Value, Member, Null_} itsType; //!< Whether this holds values (array) or members (objects) or nothing |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
512 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
513 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
514 |
//! Searches for the expectedName node if it doesn't match the actualName |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
515 |
/*! This needs to be called before every load or node start occurs. This function will |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
516 |
check to see if an NVP has been provided (with setNextName) and if so, see if that name matches the actual |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
517 |
next name given. If the names do not match, it will search in the current level of the JSON for that name. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
518 |
If the name is not found, an exception will be thrown. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
519 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
520 |
Resets the NVP name after called. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
521 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
522 |
@throws Exception if an expectedName is given and not found */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
523 |
inline void search() |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
524 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
525 |
// The name an NVP provided with setNextName() |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
526 |
if( itsNextName ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
527 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
528 |
// The actual name of the current node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
529 |
auto const actualName = itsIteratorStack.back().name(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
530 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
531 |
// Do a search if we don't see a name coming up, or if the names don't match |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
532 |
if( !actualName || std::strcmp( itsNextName, actualName ) != 0 ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
533 |
itsIteratorStack.back().search( itsNextName ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
534 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
535 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
536 |
itsNextName = nullptr; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
537 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
538 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
539 |
public: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
540 |
//! Starts a new node, going into its proper iterator |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
541 |
/*! This places an iterator for the next node to be parsed onto the iterator stack. If the next |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
542 |
node is an array, this will be a value iterator, otherwise it will be a member iterator. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
543 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
544 |
By default our strategy is to start with the document root node and then recursively iterate through |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
545 |
all children in the order they show up in the document. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
546 |
We don't need to know NVPs to do this; we'll just blindly load in the order things appear in. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
547 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
548 |
If we were given an NVP, we will search for it if it does not match our the name of the next node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
549 |
that would normally be loaded. This functionality is provided by search(). */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
550 |
void startNode() |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
551 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
552 |
search(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
553 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
554 |
if(itsIteratorStack.back().value().IsArray()) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
555 |
itsIteratorStack.emplace_back(itsIteratorStack.back().value().Begin(), itsIteratorStack.back().value().End()); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
556 |
else |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
557 |
itsIteratorStack.emplace_back(itsIteratorStack.back().value().MemberBegin(), itsIteratorStack.back().value().MemberEnd()); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
558 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
559 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
560 |
//! Finishes the most recently started node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
561 |
void finishNode() |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
562 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
563 |
itsIteratorStack.pop_back(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
564 |
++itsIteratorStack.back(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
565 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
566 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
567 |
//! Retrieves the current node name |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
568 |
/*! @return nullptr if no name exists */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
569 |
const char * getNodeName() const |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
570 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
571 |
return itsIteratorStack.back().name(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
572 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
573 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
574 |
//! Sets the name for the next node created with startNode |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
575 |
void setNextName( const char * name ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
576 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
577 |
itsNextName = name; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
578 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
579 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
580 |
//! Loads a value from the current node - small signed overload |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
581 |
template <class T, traits::EnableIf<std::is_signed<T>::value, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
582 |
sizeof(T) < sizeof(int64_t)> = traits::sfinae> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
583 |
void loadValue(T & val) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
584 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
585 |
search(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
586 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
587 |
val = static_cast<T>( itsIteratorStack.back().value().GetInt() ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
588 |
++itsIteratorStack.back(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
589 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
590 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
591 |
//! Loads a value from the current node - small unsigned overload |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
592 |
template <class T, traits::EnableIf<std::is_unsigned<T>::value, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
593 |
sizeof(T) < sizeof(uint64_t), |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
594 |
!std::is_same<bool, T>::value> = traits::sfinae> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
595 |
void loadValue(T & val) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
596 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
597 |
search(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
598 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
599 |
val = static_cast<T>( itsIteratorStack.back().value().GetUint() ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
600 |
++itsIteratorStack.back(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
601 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
602 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
603 |
//! Loads a value from the current node - bool overload |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
604 |
void loadValue(bool & val) { search(); val = itsIteratorStack.back().value().GetBool_(); ++itsIteratorStack.back(); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
605 |
//! Loads a value from the current node - int64 overload |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
606 |
void loadValue(int64_t & val) { search(); val = itsIteratorStack.back().value().GetInt64(); ++itsIteratorStack.back(); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
607 |
//! Loads a value from the current node - uint64 overload |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
608 |
void loadValue(uint64_t & val) { search(); val = itsIteratorStack.back().value().GetUint64(); ++itsIteratorStack.back(); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
609 |
//! Loads a value from the current node - float overload |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
610 |
void loadValue(float & val) { search(); val = static_cast<float>(itsIteratorStack.back().value().GetDouble()); ++itsIteratorStack.back(); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
611 |
//! Loads a value from the current node - double overload |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
612 |
void loadValue(double & val) { search(); val = itsIteratorStack.back().value().GetDouble(); ++itsIteratorStack.back(); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
613 |
//! Loads a value from the current node - string overload |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
614 |
void loadValue(std::string & val) { search(); val = itsIteratorStack.back().value().GetString(); ++itsIteratorStack.back(); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
615 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
616 |
// Special cases to handle various flavors of long, which tend to conflict with |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
617 |
// the int32_t or int64_t on various compiler/OS combinations. MSVC doesn't need any of this. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
618 |
#ifndef _MSC_VER |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
619 |
private: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
620 |
//! 32 bit signed long loading from current node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
621 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
622 |
typename std::enable_if<sizeof(T) == sizeof(std::int32_t) && std::is_signed<T>::value, void>::type |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
623 |
loadLong(T & l){ loadValue( reinterpret_cast<std::int32_t&>( l ) ); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
624 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
625 |
//! non 32 bit signed long loading from current node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
626 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
627 |
typename std::enable_if<sizeof(T) == sizeof(std::int64_t) && std::is_signed<T>::value, void>::type |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
628 |
loadLong(T & l){ loadValue( reinterpret_cast<std::int64_t&>( l ) ); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
629 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
630 |
//! 32 bit unsigned long loading from current node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
631 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
632 |
typename std::enable_if<sizeof(T) == sizeof(std::uint32_t) && !std::is_signed<T>::value, void>::type |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
633 |
loadLong(T & lu){ loadValue( reinterpret_cast<std::uint32_t&>( lu ) ); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
634 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
635 |
//! non 32 bit unsigned long loading from current node |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
636 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
637 |
typename std::enable_if<sizeof(T) == sizeof(std::uint64_t) && !std::is_signed<T>::value, void>::type |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
638 |
loadLong(T & lu){ loadValue( reinterpret_cast<std::uint64_t&>( lu ) ); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
639 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
640 |
public: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
641 |
//! Serialize a long if it would not be caught otherwise |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
642 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
643 |
typename std::enable_if<std::is_same<T, long>::value && |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
644 |
!std::is_same<T, std::int32_t>::value && |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
645 |
!std::is_same<T, std::int64_t>::value, void>::type |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
646 |
loadValue( T & t ){ loadLong(t); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
647 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
648 |
//! Serialize an unsigned long if it would not be caught otherwise |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
649 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
650 |
typename std::enable_if<std::is_same<T, unsigned long>::value && |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
651 |
!std::is_same<T, std::uint32_t>::value && |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
652 |
!std::is_same<T, std::uint64_t>::value, void>::type |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
653 |
loadValue( T & t ){ loadLong(t); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
654 |
#endif // _MSC_VER |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
655 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
656 |
private: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
657 |
//! Convert a string to a long long |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
658 |
void stringToNumber( std::string const & str, long long & val ) { val = std::stoll( str ); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
659 |
//! Convert a string to an unsigned long long |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
660 |
void stringToNumber( std::string const & str, unsigned long long & val ) { val = std::stoull( str ); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
661 |
//! Convert a string to a long double |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
662 |
void stringToNumber( std::string const & str, long double & val ) { val = std::stold( str ); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
663 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
664 |
public: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
665 |
//! Loads a value from the current node - long double and long long overloads |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
666 |
template <class T, traits::EnableIf<std::is_arithmetic<T>::value, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
667 |
!std::is_same<T, long>::value, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
668 |
!std::is_same<T, unsigned long>::value, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
669 |
!std::is_same<T, std::int64_t>::value, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
670 |
!std::is_same<T, std::uint64_t>::value, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
671 |
(sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long))> = traits::sfinae> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
672 |
inline void loadValue(T & val) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
673 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
674 |
std::string encoded; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
675 |
loadValue( encoded ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
676 |
stringToNumber( encoded, val ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
677 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
678 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
679 |
//! Loads the size for a SizeTag |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
680 |
void loadSize(size_type & size) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
681 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
682 |
size = (itsIteratorStack.rbegin() + 1)->value().Size(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
683 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
684 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
685 |
//! @} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
686 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
687 |
private: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
688 |
const char * itsNextName; //!< Next name set by NVP |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
689 |
ReadStream itsReadStream; //!< Rapidjson write stream |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
690 |
std::vector<Iterator> itsIteratorStack; //!< 'Stack' of rapidJSON iterators |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
691 |
rapidjson::Document itsDocument; //!< Rapidjson document |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
692 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
693 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
694 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
695 |
// JSONArchive prologue and epilogue functions |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
696 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
697 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
698 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
699 |
//! Prologue for NVPs for JSON archives |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
700 |
/*! NVPs do not start or finish nodes - they just set up the names */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
701 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
702 |
void prologue( JSONOutputArchive &, NameValuePair<T> const & ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
703 |
{ } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
704 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
705 |
//! Prologue for NVPs for JSON archives |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
706 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
707 |
void prologue( JSONInputArchive &, NameValuePair<T> const & ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
708 |
{ } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
709 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
710 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
711 |
//! Epilogue for NVPs for JSON archives |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
712 |
/*! NVPs do not start or finish nodes - they just set up the names */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
713 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
714 |
void epilogue( JSONOutputArchive &, NameValuePair<T> const & ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
715 |
{ } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
716 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
717 |
//! Epilogue for NVPs for JSON archives |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
718 |
/*! NVPs do not start or finish nodes - they just set up the names */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
719 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
720 |
void epilogue( JSONInputArchive &, NameValuePair<T> const & ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
721 |
{ } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
722 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
723 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
724 |
//! Prologue for SizeTags for JSON archives |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
725 |
/*! SizeTags are strictly ignored for JSON, they just indicate |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
726 |
that the current node should be made into an array */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
727 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
728 |
void prologue( JSONOutputArchive & ar, SizeTag<T> const & ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
729 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
730 |
ar.makeArray(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
731 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
732 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
733 |
//! Prologue for SizeTags for JSON archives |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
734 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
735 |
void prologue( JSONInputArchive &, SizeTag<T> const & ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
736 |
{ } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
737 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
738 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
739 |
//! Epilogue for SizeTags for JSON archives |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
740 |
/*! SizeTags are strictly ignored for JSON */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
741 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
742 |
void epilogue( JSONOutputArchive &, SizeTag<T> const & ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
743 |
{ } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
744 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
745 |
//! Epilogue for SizeTags for JSON archives |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
746 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
747 |
void epilogue( JSONInputArchive &, SizeTag<T> const & ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
748 |
{ } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
749 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
750 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
751 |
//! Prologue for all other types for JSON archives (except minimal types) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
752 |
/*! Starts a new node, named either automatically or by some NVP, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
753 |
that may be given data by the type about to be archived |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
754 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
755 |
Minimal types do not start or finish nodes */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
756 |
template <class T, traits::DisableIf<std::is_arithmetic<T>::value || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
757 |
traits::has_minimal_base_class_serialization<T, traits::has_minimal_output_serialization, JSONOutputArchive>::value || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
758 |
traits::has_minimal_output_serialization<T, JSONOutputArchive>::value> = traits::sfinae> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
759 |
inline void prologue( JSONOutputArchive & ar, T const & ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
760 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
761 |
ar.startNode(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
762 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
763 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
764 |
//! Prologue for all other types for JSON archives |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
765 |
template <class T, traits::DisableIf<std::is_arithmetic<T>::value || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
766 |
traits::has_minimal_base_class_serialization<T, traits::has_minimal_input_serialization, JSONInputArchive>::value || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
767 |
traits::has_minimal_input_serialization<T, JSONInputArchive>::value> = traits::sfinae> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
768 |
inline void prologue( JSONInputArchive & ar, T const & ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
769 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
770 |
ar.startNode(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
771 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
772 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
773 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
774 |
//! Epilogue for all other types other for JSON archives (except minimal types |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
775 |
/*! Finishes the node created in the prologue |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
776 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
777 |
Minimal types do not start or finish nodes */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
778 |
template <class T, traits::DisableIf<std::is_arithmetic<T>::value || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
779 |
traits::has_minimal_base_class_serialization<T, traits::has_minimal_output_serialization, JSONOutputArchive>::value || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
780 |
traits::has_minimal_output_serialization<T, JSONOutputArchive>::value> = traits::sfinae> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
781 |
inline void epilogue( JSONOutputArchive & ar, T const & ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
782 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
783 |
ar.finishNode(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
784 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
785 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
786 |
//! Epilogue for all other types other for JSON archives |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
787 |
template <class T, traits::DisableIf<std::is_arithmetic<T>::value || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
788 |
traits::has_minimal_base_class_serialization<T, traits::has_minimal_input_serialization, JSONInputArchive>::value || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
789 |
traits::has_minimal_input_serialization<T, JSONInputArchive>::value> = traits::sfinae> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
790 |
inline void epilogue( JSONInputArchive & ar, T const & ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
791 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
792 |
ar.finishNode(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
793 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
794 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
795 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
796 |
//! Prologue for arithmetic types for JSON archives |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
797 |
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
798 |
void prologue( JSONOutputArchive & ar, T const & ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
799 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
800 |
ar.writeName(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
801 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
802 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
803 |
//! Prologue for arithmetic types for JSON archives |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
804 |
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
805 |
void prologue( JSONInputArchive &, T const & ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
806 |
{ } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
807 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
808 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
809 |
//! Epilogue for arithmetic types for JSON archives |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
810 |
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
811 |
void epilogue( JSONOutputArchive &, T const & ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
812 |
{ } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
813 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
814 |
//! Epilogue for arithmetic types for JSON archives |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
815 |
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
816 |
void epilogue( JSONInputArchive &, T const & ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
817 |
{ } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
818 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
819 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
820 |
//! Prologue for strings for JSON archives |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
821 |
template<class CharT, class Traits, class Alloc> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
822 |
void prologue(JSONOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const &) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
823 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
824 |
ar.writeName(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
825 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
826 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
827 |
//! Prologue for strings for JSON archives |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
828 |
template<class CharT, class Traits, class Alloc> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
829 |
void prologue(JSONInputArchive &, std::basic_string<CharT, Traits, Alloc> const &) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
830 |
{ } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
831 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
832 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
833 |
//! Epilogue for strings for JSON archives |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
834 |
template<class CharT, class Traits, class Alloc> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
835 |
void epilogue(JSONOutputArchive &, std::basic_string<CharT, Traits, Alloc> const &) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
836 |
{ } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
837 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
838 |
//! Epilogue for strings for JSON archives |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
839 |
template<class CharT, class Traits, class Alloc> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
840 |
void epilogue(JSONInputArchive &, std::basic_string<CharT, Traits, Alloc> const &) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
841 |
{ } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
842 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
843 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
844 |
// Common JSONArchive serialization functions |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
845 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
846 |
//! Serializing NVP types to JSON |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
847 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
848 |
void CEREAL_SAVE_FUNCTION_NAME( JSONOutputArchive & ar, NameValuePair<T> const & t ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
849 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
850 |
ar.setNextName( t.name ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
851 |
ar( t.value ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
852 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
853 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
854 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
855 |
void CEREAL_LOAD_FUNCTION_NAME( JSONInputArchive & ar, NameValuePair<T> & t ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
856 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
857 |
ar.setNextName( t.name ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
858 |
ar( t.value ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
859 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
860 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
861 |
//! Saving for arithmetic to JSON |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
862 |
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
863 |
void CEREAL_SAVE_FUNCTION_NAME(JSONOutputArchive & ar, T const & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
864 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
865 |
ar.saveValue( t ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
866 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
867 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
868 |
//! Loading arithmetic from JSON |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
869 |
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
870 |
void CEREAL_LOAD_FUNCTION_NAME(JSONInputArchive & ar, T & t) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
871 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
872 |
ar.loadValue( t ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
873 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
874 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
875 |
//! saving string to JSON |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
876 |
template<class CharT, class Traits, class Alloc> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
877 |
void CEREAL_SAVE_FUNCTION_NAME(JSONOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const & str) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
878 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
879 |
ar.saveValue( str ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
880 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
881 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
882 |
//! loading string from JSON |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
883 |
template<class CharT, class Traits, class Alloc> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
884 |
void CEREAL_LOAD_FUNCTION_NAME(JSONInputArchive & ar, std::basic_string<CharT, Traits, Alloc> & str) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
885 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
886 |
ar.loadValue( str ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
887 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
888 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
889 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
890 |
//! Saving SizeTags to JSON |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
891 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
892 |
void CEREAL_SAVE_FUNCTION_NAME( JSONOutputArchive &, SizeTag<T> const & ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
893 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
894 |
// nothing to do here, we don't explicitly save the size |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
895 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
896 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
897 |
//! Loading SizeTags from JSON |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
898 |
template <class T> inline |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
899 |
void CEREAL_LOAD_FUNCTION_NAME( JSONInputArchive & ar, SizeTag<T> & st ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
900 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
901 |
ar.loadSize( st.size ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
902 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
903 |
} // namespace cereal |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
904 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
905 |
// register archives for polymorphic support |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
906 |
CEREAL_REGISTER_ARCHIVE(cereal::JSONInputArchive) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
907 |
CEREAL_REGISTER_ARCHIVE(cereal::JSONOutputArchive) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
908 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
909 |
// tie input and output archives together |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
910 |
CEREAL_SETUP_ARCHIVE_TRAITS(cereal::JSONInputArchive, cereal::JSONOutputArchive) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
911 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
912 |
#endif // CEREAL_ARCHIVES_JSON_HPP_ |
|
|
1970-01-01 00:00 |
913 |
|