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 the copyright holder 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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 400 : UserDataAdapter( UserData & ud, Args && ... args ) : 121 400 : Archive( std::forward<Args>( args )... ), 122 500 : userdata( ud ) 123 400 : { } 124 : 125 : private: 126 : //! Overload the rtti function to enable dynamic_cast 127 0 : 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 800 : UserData & get_user_data( Archive & ar ) 150 : { 151 : try 152 : { 153 800 : return dynamic_cast<UserDataAdapter<UserData, Archive> &>( ar ).userdata; 154 : } 155 800 : catch( std::bad_cast const & ) 156 : { 157 400 : 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_