boss: Implement Spotpass service (part 1) (#7232)
* boss: Implement Spotpass service (part 1) * boss: Fix save state (de)serialization. * boss: Fix casing of SpotPass in log messages. * boss: Minor logging improvements. * common: Add boost serialization support for std::variant. --------- Co-authored-by: Rokkubro <lachlanb03@gmail.com> Co-authored-by: FearlessTobi <thm.frey@gmail.com>
This commit is contained in:
parent
4d9eedd0d8
commit
24b5ffbfca
7 changed files with 1018 additions and 129 deletions
|
@ -127,6 +127,7 @@ add_library(citra_common STATIC
|
|||
serialization/boost_discrete_interval.hpp
|
||||
serialization/boost_flat_set.h
|
||||
serialization/boost_small_vector.hpp
|
||||
serialization/boost_std_variant.hpp
|
||||
serialization/boost_vector.hpp
|
||||
static_lru_cache.h
|
||||
string_literal.h
|
||||
|
|
204
src/common/serialization/boost_std_variant.hpp
Normal file
204
src/common/serialization/boost_std_variant.hpp
Normal file
|
@ -0,0 +1,204 @@
|
|||
#ifndef BOOST_SERIALIZATION_STD_VARIANT_HPP
|
||||
#define BOOST_SERIALIZATION_STD_VARIANT_HPP
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
#if defined(_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
||||
// variant.hpp - non-intrusive serialization of variant types
|
||||
//
|
||||
// copyright (c) 2019 Samuel Debionne, ESRF
|
||||
//
|
||||
// Use, modification and distribution is subject to 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 http://www.boost.org for updates, documentation, and revision history.
|
||||
//
|
||||
// Widely inspired form boost::variant serialization
|
||||
//
|
||||
|
||||
#include <boost/serialization/throw_exception.hpp>
|
||||
|
||||
#include <variant>
|
||||
|
||||
#include <boost/archive/archive_exception.hpp>
|
||||
|
||||
#include <boost/serialization/split_free.hpp>
|
||||
#include <boost/serialization/serialization.hpp>
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace serialization {
|
||||
|
||||
template<class Archive>
|
||||
struct std_variant_save_visitor
|
||||
{
|
||||
std_variant_save_visitor(Archive& ar) :
|
||||
m_ar(ar)
|
||||
{}
|
||||
template<class T>
|
||||
void operator()(T const & value) const
|
||||
{
|
||||
m_ar << BOOST_SERIALIZATION_NVP(value);
|
||||
}
|
||||
private:
|
||||
Archive & m_ar;
|
||||
};
|
||||
|
||||
|
||||
template<class Archive>
|
||||
struct std_variant_load_visitor
|
||||
{
|
||||
std_variant_load_visitor(Archive& ar) :
|
||||
m_ar(ar)
|
||||
{}
|
||||
template<class T>
|
||||
void operator()(T & value) const
|
||||
{
|
||||
m_ar >> BOOST_SERIALIZATION_NVP(value);
|
||||
}
|
||||
private:
|
||||
Archive & m_ar;
|
||||
};
|
||||
|
||||
template<class Archive, class ...Types>
|
||||
void save(
|
||||
Archive & ar,
|
||||
std::variant<Types...> const & v,
|
||||
unsigned int /*version*/
|
||||
){
|
||||
const std::size_t which = v.index();
|
||||
ar << BOOST_SERIALIZATION_NVP(which);
|
||||
std_variant_save_visitor<Archive> visitor(ar);
|
||||
std::visit(visitor, v);
|
||||
}
|
||||
|
||||
// Minimalist metaprogramming for handling parameter pack
|
||||
namespace mp {
|
||||
namespace detail {
|
||||
template <typename Seq>
|
||||
struct front_impl;
|
||||
|
||||
template <template <typename...> class Seq, typename T, typename... Ts>
|
||||
struct front_impl<Seq<T, Ts...>> {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename Seq>
|
||||
struct pop_front_impl;
|
||||
|
||||
template <template <typename...> class Seq, typename T, typename... Ts>
|
||||
struct pop_front_impl<Seq<T, Ts...>> {
|
||||
using type = Seq<Ts...>;
|
||||
};
|
||||
} //namespace detail
|
||||
|
||||
template <typename... Ts>
|
||||
struct typelist {};
|
||||
|
||||
template <typename Seq>
|
||||
using front = typename detail::front_impl<Seq>::type;
|
||||
|
||||
template <typename Seq>
|
||||
using pop_front = typename detail::pop_front_impl<Seq>::type;
|
||||
} // namespace mp
|
||||
|
||||
template<std::size_t N, class Seq>
|
||||
struct variant_impl
|
||||
{
|
||||
template<class Archive, class V>
|
||||
static void load (
|
||||
Archive & ar,
|
||||
std::size_t which,
|
||||
V & v,
|
||||
const unsigned int version
|
||||
){
|
||||
if(which == 0){
|
||||
// note: A non-intrusive implementation (such as this one)
|
||||
// necessary has to copy the value. This wouldn't be necessary
|
||||
// with an implementation that de-serialized to the address of the
|
||||
// aligned storage included in the variant.
|
||||
using type = mp::front<Seq>;
|
||||
type value;
|
||||
ar >> BOOST_SERIALIZATION_NVP(value);
|
||||
v = std::move(value);
|
||||
type * new_address = & std::get<type>(v);
|
||||
ar.reset_object_address(new_address, & value);
|
||||
return;
|
||||
}
|
||||
//typedef typename mpl::pop_front<S>::type type;
|
||||
using types = mp::pop_front<Seq>;
|
||||
variant_impl<N - 1, types>::load(ar, which - 1, v, version);
|
||||
}
|
||||
};
|
||||
|
||||
template<class Seq>
|
||||
struct variant_impl<0, Seq>
|
||||
{
|
||||
template<class Archive, class V>
|
||||
static void load (
|
||||
Archive & /*ar*/,
|
||||
std::size_t /*which*/,
|
||||
V & /*v*/,
|
||||
const unsigned int /*version*/
|
||||
){}
|
||||
};
|
||||
|
||||
template<class Archive, class... Types>
|
||||
void load(
|
||||
Archive & ar,
|
||||
std::variant<Types...>& v,
|
||||
const unsigned int version
|
||||
){
|
||||
std::size_t which;
|
||||
ar >> BOOST_SERIALIZATION_NVP(which);
|
||||
if(which >= sizeof...(Types))
|
||||
// this might happen if a type was removed from the list of variant types
|
||||
boost::serialization::throw_exception(
|
||||
boost::archive::archive_exception(
|
||||
boost::archive::archive_exception::unsupported_version
|
||||
)
|
||||
);
|
||||
variant_impl<sizeof...(Types), mp::typelist<Types...>>::load(ar, which, v, version);
|
||||
}
|
||||
|
||||
template<class Archive,class... Types>
|
||||
inline void serialize(
|
||||
Archive & ar,
|
||||
std::variant<Types...> & v,
|
||||
const unsigned int file_version
|
||||
){
|
||||
split_free(ar,v,file_version);
|
||||
}
|
||||
|
||||
// Specialization for std::monostate
|
||||
template<class Archive>
|
||||
void serialize(Archive &ar, std::monostate &, const unsigned int /*version*/)
|
||||
{}
|
||||
|
||||
} // namespace serialization
|
||||
} // namespace boost
|
||||
|
||||
//template<typename T0_, BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T)>
|
||||
|
||||
#include <boost/serialization/tracking.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace serialization {
|
||||
|
||||
template<class... Types>
|
||||
struct tracking_level<
|
||||
std::variant<Types...>
|
||||
>{
|
||||
typedef mpl::integral_c_tag tag;
|
||||
typedef mpl::int_< ::boost::serialization::track_always> type;
|
||||
BOOST_STATIC_CONSTANT(int, value = type::value);
|
||||
};
|
||||
|
||||
} // namespace serialization
|
||||
} // namespace boost
|
||||
|
||||
#endif //BOOST_SERIALIZATION_VARIANT_HPP
|
Loading…
Add table
Add a link
Reference in a new issue