// TJP COPYRIGHT HEADER #pragma once #include "Initializer.h" #include #include #include #include #include #include #include #include namespace tjp { namespace core { namespace initializer { typedef std::string ID; typedef std::function InitializerFunction; typedef std::pair KeyedInitializerFunction; typedef std::map> InitializersMap; struct Initializers { InitializersMap map; Initializers(InitializersMap &&map_) : map(map_) {} Initializers merge(const Initializers &base) { auto result = Initializers(InitializersMap(map)); for (auto &[fromI, fromV] : base.map) { auto &toV = result.map[fromI]; for (auto &fromKF: fromV) { auto contains = false; auto &fromK = fromKF.first; for (auto &toKF : toV) { auto &toK = toKF.first; if (fromK == toK) { contains = true; break; } } if (!contains) toV.push_back(fromKF); } } return result; } Initializers replace(const Initializers &base) { auto result = Initializers(InitializersMap(map)); for (auto &[fromI, fromV] : base.map) { auto &toV = result.map[fromI]; for (auto &fromKF: fromV) { auto &fromK = fromKF.first; vector_erase_if_value(toV, [&](auto &v) { return v.first == fromK; }); toV.push_back(fromKF); } } return result; } } ; struct Token {}; struct Initializer; struct InitializerChain; // SFINAE test template class has_setInitializer { private: typedef char true_type; typedef long false_type; template static false_type& test(...); template static true_type& test( decltype(&C::setInitializer) ) ; public: enum { value = sizeof(test(0)) == sizeof(true_type) }; }; template::value, T>::type* = nullptr> void chain_initializer(Initializer *initializer, T *t); template::value, T>::type* = nullptr> void chain_initializer(Initializer *initializer, T *t) { } struct Initializer; //void deallocate(Initializer *); struct Catalog : StrongThis { std::map> initializerById; StrongPtr get(const ID &id); void put(const ID &id, const StrongPtr &initializer); template StrongPtr construct_with(const U &id, Args&& ...args); } ; struct Initializer : StrongThis { WeakPtr catalog; std::string id; Initializers initializers; Initializer(Initializers &&initializers_); StrongPtr getInitializer(const ID &id); template void initialize(R *r) { chain_initializer(this, r); auto type = type_id(); auto i = initializers.map.find(type); if (i != initializers.map.end()) { for (auto &[key, initializer]: i->second) { initializer(r); } } } template void initialize_reflect(R *r) { r->initialize_with(this); } template StrongPtr construct(Args&& ...args) { auto p = strong(Token{}, std::forward(args)...); initialize_reflect(ptr_of(p)); return p; } template StrongPtr construct_with(const U &id, Args&& ...args) { auto initializer = getInitializer(ID(id)); debug_assert(initializer); return initializer->construct(std::forward(args)...); } } ; struct InitializerChain { StrongPtr initializer; template void initialize(T *t) { debug_assert(initializer); initializer->initialize_reflect(t); } template void initialize(const StrongPtr &t) { debug_assert(initializer); initializer->initialize_reflect(ptr_of(t)); } void setInitializer(const StrongPtr &initializer_) { initializer = initializer_; } template StrongPtr construct(Args&& ...args) { return initializer->construct(std::forward(args)...); } template StrongPtr construct_with(const U &id, Args&& ...args) { return initializer->construct_with(id, std::forward(args)...); } std::string &initializer_id() { return initializer->id; } } ; template StrongPtr Catalog::construct_with(const U &id, Args&& ...args) { auto initializer = get(ID(id)); debug_assert(initializer); return initializer->construct(std::forward(args)...); } template::value, T>::type*> void chain_initializer(Initializer *initializer, T *t) { t->setInitializer(strong_this(initializer)); } } // namespace } // namespace } // namespace