Line data Source code
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 800 : UserDataAdapter( UserData & ud, Args && ... args ) :
121 800 : Archive( std::forward<Args>( args )... ),
122 1000 : userdata( ud )
123 800 : { }
124 200 :
125 200 : private:
126 200 : //! Overload the rtti function to enable dynamic_cast
127 200 : void rtti() {}
128 200 : friend UserData & get_user_data<UserData>( Archive & ar );
129 200 : UserData & userdata; //!< The actual user data
130 200 : };
131 200 :
132 200 : //! Retrieves user data from an archive wrapped by UserDataAdapter
133 200 : /*! This will attempt to retrieve the user data associated with
134 400 : some archive wrapped by UserDataAdapter. If this is used on
135 200 : an archive that is not wrapped, a run-time exception will occur.
136 200 :
137 200 : @note This feature is experimental and may be altered or removed in a future release. See issue #46.
138 200 :
139 200 : @note The correct use of this function cannot be enforced at compile
140 : time.
141 :
142 : @relates UserDataAdapter
143 0 : @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_
|