/* Copyright 2023 Joaquin M Lopez Munoz. * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) * * See https://www.boost.org/libs/unordered for library home page. */ #ifndef BOOST_UNORDERED_DETAIL_SERIALIZE_CONTAINER_HPP #define BOOST_UNORDERED_DETAIL_SERIALIZE_CONTAINER_HPP #include #include #include #include #include #include namespace boost{ namespace unordered{ namespace detail{ /* serialize_container(ar,x,v) serializes any of the unordered associative * containers in Boost.Unordered. Iterator serialization is also supported * through the following protocol: * - At saving time, for each iterator it in [x.begin(),x.end()), * serialization_track(ar,it) is ADL-called to instruct the archive to * track the positions internally pointed to by the iterator via * track_address(). * - At loading time, these addresses are mapped to those of the equivalent * reconstructed positions using again serialization_track(ar,it). * - Serializing an iterator reduces to serializing pointers to previously * tracked addresses via serialize_address(). */ template std::pair adapt_insert_return_type(Iterator it) { return std::pair(it,true); } template std::pair adapt_insert_return_type(std::pair p) { return p; } template struct load_or_save_unordered_set; template struct load_or_save_unordered_set /* save */ { template void operator()(Archive& ar,const Set& x,unsigned int)const { typedef typename Set::value_type value_type; typedef typename Set::const_iterator const_iterator; const std::size_t s=x.size(); const serialization_version value_version; ar< struct load_or_save_unordered_set /* load */ { template void operator()(Archive& ar,Set& x,unsigned int)const { typedef typename Set::value_type value_type; typedef typename Set::iterator iterator; std::size_t s; serialization_version value_version; ar>>core::make_nvp("count",s); ar>>core::make_nvp("value_version",value_version); x.clear(); x.reserve(s); /* critical so that iterator tracking is stable */ for(std::size_t n=0;n value("item",ar,value_version); std::pair p=adapt_insert_return_type( x.insert(std::move(value.get()))); if(!p.second)throw_exception(bad_archive_exception()); ar.reset_object_address( std::addressof(*p.first),std::addressof(value.get())); serialization_track(ar,p.first); } } }; template struct load_or_save_unordered_map; template struct load_or_save_unordered_map /* save */ { template void operator()(Archive& ar,const Map& x,unsigned int)const { typedef typename std::remove_const< typename Map::key_type>::type key_type; typedef typename std::remove_const< typename Map::mapped_type>::type mapped_type; typedef typename Map::const_iterator const_iterator; const std::size_t s=x.size(); const serialization_version key_version; const serialization_version mapped_version; ar<first),key_version); ar<first); core::save_construct_data_adl( ar,std::addressof(first->second),mapped_version); ar<second); serialization_track(ar,first); } } }; template struct load_or_save_unordered_map /* load */ { template void operator()(Archive& ar,Map& x,unsigned int)const { typedef typename std::remove_const< typename Map::key_type>::type key_type; typedef typename std::remove_const< typename Map::mapped_type>::type mapped_type; typedef typename Map::iterator iterator; std::size_t s; serialization_version key_version; serialization_version mapped_version; ar>>core::make_nvp("count",s); ar>>core::make_nvp("key_version",key_version); ar>>core::make_nvp("mapped_version",mapped_version); x.clear(); x.reserve(s); /* critical so that iterator tracking is stable */ for(std::size_t n=0;n key("key",ar,key_version); archive_constructed mapped("mapped",ar,mapped_version); std::pair p=adapt_insert_return_type( x.emplace(std::move(key.get()),std::move(mapped.get()))); if(!p.second)throw_exception(bad_archive_exception()); ar.reset_object_address( std::addressof(p.first->first),std::addressof(key.get())); ar.reset_object_address( std::addressof(p.first->second),std::addressof(mapped.get())); serialization_track(ar,p.first); } } }; template struct load_or_save_container; template struct load_or_save_container: load_or_save_unordered_set{}; template struct load_or_save_container: load_or_save_unordered_map{}; template void serialize_container(Archive& ar,Container& x,unsigned int version) { load_or_save_container< Container, std::is_same< typename Container::key_type,typename Container::value_type>::value, Archive::is_saving::value>()(ar,x,version); } } /* namespace detail */ } /* namespace unordered */ } /* namespace boost */ #endif