flatten 20260225
This commit is contained in:
51
tjp/core/initializer/Initializer.cpp
Normal file
51
tjp/core/initializer/Initializer.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
// TJP COPYRIGHT HEADER
|
||||
|
||||
#include "Initializer.hpp"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace initializer {
|
||||
|
||||
//void deallocate(Initializer *v)
|
||||
//{
|
||||
// delete v;
|
||||
//}
|
||||
|
||||
Initializer::Initializer(Initializers &&initializers_) :
|
||||
initializers(initializers_)
|
||||
{
|
||||
}
|
||||
|
||||
StrongPtr<Initializer> Catalog::get(const std::string &id)
|
||||
{
|
||||
auto i = initializerById.find(id);
|
||||
if (i != initializerById.end())
|
||||
return i->second;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Catalog::put(const std::string &id, const StrongPtr<Initializer> &initializer)
|
||||
{
|
||||
initializerById[id] = initializer;
|
||||
initializer->catalog = weak_this(this);
|
||||
initializer->id = id;
|
||||
}
|
||||
|
||||
|
||||
StrongPtr<Initializer> Initializer::getInitializer(const std::string &id)
|
||||
{
|
||||
if (id.empty())
|
||||
return strong_this(this);
|
||||
|
||||
if (auto catalog_ = strong(catalog))
|
||||
{
|
||||
return catalog_->get(id);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
17
tjp/core/initializer/Initializer.h
Normal file
17
tjp/core/initializer/Initializer.h
Normal file
@@ -0,0 +1,17 @@
|
||||
// TJP COPYRIGHT HEADER
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace initializer {
|
||||
|
||||
struct Token;
|
||||
struct Initializer;
|
||||
struct Globals;
|
||||
struct InitializerChain;
|
||||
struct Catalog;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
238
tjp/core/initializer/Initializer.hpp
Normal file
238
tjp/core/initializer/Initializer.hpp
Normal file
@@ -0,0 +1,238 @@
|
||||
// TJP COPYRIGHT HEADER
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Initializer.h"
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <tjp/core/assert/debug_assert.h>
|
||||
#include <tjp/core/algorithm/vector_erase_if_value.hpp>
|
||||
#include <tjp/core/ptr/Ptr.hpp>
|
||||
#include <tjp/core/rtti/RTTI.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace initializer {
|
||||
|
||||
typedef std::string ID;
|
||||
|
||||
typedef std::function<void(void *)> InitializerFunction;
|
||||
typedef std::pair<type_index, InitializerFunction> KeyedInitializerFunction;
|
||||
typedef std::map<type_index, std::vector<KeyedInitializerFunction>> 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 <typename T>
|
||||
class has_setInitializer
|
||||
{
|
||||
private:
|
||||
typedef char true_type;
|
||||
typedef long false_type;
|
||||
|
||||
template <typename C> static false_type& test(...);
|
||||
template <typename C> static true_type& test( decltype(&C::setInitializer) ) ;
|
||||
|
||||
|
||||
public:
|
||||
enum { value = sizeof(test<T>(0)) == sizeof(true_type) };
|
||||
};
|
||||
|
||||
template<typename T, typename std::enable_if<has_setInitializer<T>::value, T>::type* = nullptr>
|
||||
void chain_initializer(Initializer *initializer, T *t);
|
||||
|
||||
template<typename T, typename std::enable_if<!has_setInitializer<T>::value, T>::type* = nullptr>
|
||||
void chain_initializer(Initializer *initializer, T *t) { }
|
||||
|
||||
struct Initializer;
|
||||
|
||||
//void deallocate(Initializer *);
|
||||
|
||||
struct Catalog : StrongThis<Catalog>
|
||||
{
|
||||
std::map<ID, StrongPtr<Initializer>> initializerById;
|
||||
|
||||
StrongPtr<Initializer> get(const ID &id);
|
||||
|
||||
void put(const ID &id, const StrongPtr<Initializer> &initializer);
|
||||
|
||||
template<typename T, typename U, typename ... Args>
|
||||
StrongPtr<T> construct_with(const U &id, Args&& ...args);
|
||||
} ;
|
||||
|
||||
|
||||
struct Initializer : StrongThis<Initializer>
|
||||
{
|
||||
WeakPtr<Catalog> catalog;
|
||||
std::string id;
|
||||
Initializers initializers;
|
||||
|
||||
Initializer(Initializers &&initializers_);
|
||||
|
||||
StrongPtr<Initializer> getInitializer(const ID &id);
|
||||
|
||||
template<typename R>
|
||||
void initialize(R *r)
|
||||
{
|
||||
chain_initializer(this, r);
|
||||
|
||||
auto type = type_id<R>();
|
||||
|
||||
auto i = initializers.map.find(type);
|
||||
if (i != initializers.map.end())
|
||||
{
|
||||
for (auto &[key, initializer]: i->second)
|
||||
{
|
||||
initializer(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
void initialize_reflect(R *r)
|
||||
{
|
||||
r->initialize_with(this);
|
||||
}
|
||||
|
||||
template<typename T, typename ... Args>
|
||||
StrongPtr<T> construct(Args&& ...args)
|
||||
{
|
||||
auto p = strong<T>(Token{}, std::forward<Args>(args)...);
|
||||
initialize_reflect(ptr_of(p));
|
||||
return p;
|
||||
}
|
||||
|
||||
template<typename T, typename U, typename ... Args>
|
||||
StrongPtr<T> construct_with(const U &id, Args&& ...args)
|
||||
{
|
||||
auto initializer = getInitializer(ID(id));
|
||||
debug_assert(initializer);
|
||||
return initializer->construct<T>(std::forward<Args>(args)...);
|
||||
}
|
||||
} ;
|
||||
|
||||
struct InitializerChain
|
||||
{
|
||||
StrongPtr<Initializer> initializer;
|
||||
|
||||
template<typename T>
|
||||
void initialize(T *t)
|
||||
{
|
||||
debug_assert(initializer);
|
||||
initializer->initialize_reflect(t);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void initialize(const StrongPtr<T> &t)
|
||||
{
|
||||
debug_assert(initializer);
|
||||
initializer->initialize_reflect(ptr_of(t));
|
||||
}
|
||||
|
||||
void setInitializer(const StrongPtr<Initializer> &initializer_)
|
||||
{
|
||||
initializer = initializer_;
|
||||
}
|
||||
|
||||
template<typename T, typename ... Args>
|
||||
StrongPtr<T> construct(Args&& ...args)
|
||||
{
|
||||
return initializer->construct<T>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename T, typename U, typename ... Args>
|
||||
StrongPtr<T> construct_with(const U &id, Args&& ...args)
|
||||
{
|
||||
return initializer->construct_with<T>(id, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
std::string &initializer_id()
|
||||
{
|
||||
return initializer->id;
|
||||
}
|
||||
} ;
|
||||
|
||||
template<typename T, typename U, typename ... Args>
|
||||
StrongPtr<T> Catalog::construct_with(const U &id, Args&& ...args)
|
||||
{
|
||||
auto initializer = get(ID(id));
|
||||
debug_assert(initializer);
|
||||
return initializer->construct<T>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename T, typename std::enable_if<has_setInitializer<T>::value, T>::type*>
|
||||
void chain_initializer(Initializer *initializer, T *t)
|
||||
{
|
||||
t->setInitializer(strong_this(initializer));
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user