isotree 0.1.4 → 0.1.5

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