serialize_meta.cc 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #include "serialize_meta.hh"
  2. #include "serialize.hh"
  3. #include "MSXException.hh"
  4. #include "ranges.hh"
  5. #include "stl.hh"
  6. #include <cassert>
  7. #include <iostream>
  8. namespace openmsx {
  9. template<typename Archive>
  10. PolymorphicSaverRegistry<Archive>& PolymorphicSaverRegistry<Archive>::instance()
  11. {
  12. static PolymorphicSaverRegistry oneInstance;
  13. return oneInstance;
  14. }
  15. template<typename Archive>
  16. void PolymorphicSaverRegistry<Archive>::registerHelper(
  17. const std::type_info& type,
  18. std::unique_ptr<PolymorphicSaverBase<Archive>> saver)
  19. {
  20. assert(!initialized);
  21. assert(ranges::none_of(saverMap, EqualTupleValue<0>(type)));
  22. saverMap.emplace_back(type, std::move(saver));
  23. }
  24. template<typename Archive>
  25. void PolymorphicSaverRegistry<Archive>::save(
  26. Archive& ar, const void* t, const std::type_info& typeInfo)
  27. {
  28. auto& reg = PolymorphicSaverRegistry<Archive>::instance();
  29. if (unlikely(!reg.initialized)) {
  30. reg.initialized = true;
  31. ranges::sort(reg.saverMap, LessTupleElement<0>());
  32. }
  33. auto it = ranges::lower_bound(reg.saverMap, typeInfo, LessTupleElement<0>());
  34. if ((it == end(reg.saverMap)) || (it->first != typeInfo)) {
  35. std::cerr << "Trying to save an unregistered polymorphic type: "
  36. << typeInfo.name() << '\n';
  37. assert(false); return;
  38. }
  39. it->second->save(ar, t);
  40. }
  41. template<typename Archive>
  42. void PolymorphicSaverRegistry<Archive>::save(
  43. const char* tag, Archive& ar, const void* t, const std::type_info& typeInfo)
  44. {
  45. ar.beginTag(tag);
  46. save(ar, t, typeInfo);
  47. ar.endTag(tag);
  48. }
  49. template class PolymorphicSaverRegistry<MemOutputArchive>;
  50. template class PolymorphicSaverRegistry<XmlOutputArchive>;
  51. ////
  52. template<typename Archive>
  53. PolymorphicLoaderRegistry<Archive>& PolymorphicLoaderRegistry<Archive>::instance()
  54. {
  55. static PolymorphicLoaderRegistry oneInstance;
  56. return oneInstance;
  57. }
  58. template<typename Archive>
  59. void PolymorphicLoaderRegistry<Archive>::registerHelper(
  60. const char* name,
  61. std::unique_ptr<PolymorphicLoaderBase<Archive>> loader)
  62. {
  63. assert(!loaderMap.contains(name));
  64. loaderMap.emplace_noDuplicateCheck(name, std::move(loader));
  65. }
  66. template<typename Archive>
  67. void* PolymorphicLoaderRegistry<Archive>::load(
  68. Archive& ar, unsigned id, const void* args)
  69. {
  70. std::string type;
  71. ar.attribute("type", type);
  72. auto& reg = PolymorphicLoaderRegistry<Archive>::instance();
  73. auto v = lookup(reg.loaderMap, type);
  74. assert(v);
  75. return (*v)->load(ar, id, args);
  76. }
  77. template class PolymorphicLoaderRegistry<MemInputArchive>;
  78. template class PolymorphicLoaderRegistry<XmlInputArchive>;
  79. ////
  80. void polyInitError(const char* expected, const char* actual)
  81. {
  82. throw MSXException("Expected type: ", expected, " but got: ", actual, '.');
  83. }
  84. template<typename Archive>
  85. PolymorphicInitializerRegistry<Archive>& PolymorphicInitializerRegistry<Archive>::instance()
  86. {
  87. static PolymorphicInitializerRegistry oneInstance;
  88. return oneInstance;
  89. }
  90. template<typename Archive>
  91. void PolymorphicInitializerRegistry<Archive>::registerHelper(
  92. const char* name,
  93. std::unique_ptr<PolymorphicInitializerBase<Archive>> initializer)
  94. {
  95. assert(!initializerMap.contains(name));
  96. initializerMap.emplace_noDuplicateCheck(name, std::move(initializer));
  97. }
  98. template<typename Archive>
  99. void PolymorphicInitializerRegistry<Archive>::init(
  100. const char* tag, Archive& ar, void* t)
  101. {
  102. ar.beginTag(tag);
  103. unsigned id;
  104. ar.attribute("id", id);
  105. assert(id);
  106. std::string type;
  107. ar.attribute("type", type);
  108. auto& reg = PolymorphicInitializerRegistry<Archive>::instance();
  109. auto v = lookup(reg.initializerMap, type);
  110. if (!v) {
  111. throw MSXException("Deserialize unknown polymorphic type: '", type, "'.");
  112. }
  113. (*v)->init(ar, t, id);
  114. ar.endTag(tag);
  115. }
  116. template class PolymorphicInitializerRegistry<MemInputArchive>;
  117. template class PolymorphicInitializerRegistry<XmlInputArchive>;
  118. } // namespace openmsx