176 lines
4.8 KiB
C++
176 lines
4.8 KiB
C++
|
|
||
|
namespace CNORXZ
|
||
|
{
|
||
|
|
||
|
template <class... Ranges>
|
||
|
using STP = std::tuple<std::shared_ptr<Ranges>...>;
|
||
|
|
||
|
typedef vector<std::shared_ptr<RangeBase> > RVEC;
|
||
|
|
||
|
template <class... Ranges>
|
||
|
inline bool compareSpaceTypes(const RVEC& rvec)
|
||
|
{
|
||
|
return RangeHelper::compareSpaceTypes<sizeof...(Ranges)-1,sizeof...(Ranges),Ranges...>(rvec);
|
||
|
}
|
||
|
|
||
|
template <class... Ranges>
|
||
|
inline bool setFactory(const RVEC& rvec, std::shared_ptr<RangeFactoryBase>& fptr)
|
||
|
{
|
||
|
if(compareSpaceTypes<Ranges...>(rvec)) {
|
||
|
STP<Ranges...> stp;
|
||
|
RangeHelper::setSpace<sizeof...(Ranges)-1>(rvec, stp);
|
||
|
fptr = std::make_shared<MultiRangeFactory<Ranges...> >(stp);
|
||
|
return true;
|
||
|
}
|
||
|
else {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
size_t indexId()
|
||
|
{
|
||
|
static size_t id = 0;
|
||
|
++id;
|
||
|
return id;
|
||
|
}
|
||
|
|
||
|
std::shared_ptr<RangeFactoryBase> mkMULTI(char const** dp, size_t metaSize)
|
||
|
{
|
||
|
std::shared_ptr<RangeFactoryBase> out = nullptr;
|
||
|
RVEC rvec(metaSize);
|
||
|
for(size_t i = 0; i != metaSize; ++i){
|
||
|
auto ff = createRangeFactory(dp);
|
||
|
rvec[i] = ff->create();
|
||
|
}
|
||
|
|
||
|
if(metaSize == 0){
|
||
|
assert(0);
|
||
|
}
|
||
|
else if(metaSize == 1) {
|
||
|
#define register_multi1(TT0) if(setFactory<TT0>(rvec, out)) {} else
|
||
|
#include "ranges/multi_range_register.h"
|
||
|
#undef register_multi1
|
||
|
assert(0);
|
||
|
}
|
||
|
else if(metaSize == 2) {
|
||
|
#define register_multi2(TT0,TT1) if(setFactory<TT0,TT1>(rvec, out)) {} else
|
||
|
#include "ranges/multi_range_register.h"
|
||
|
#undef register_multi2
|
||
|
assert(0);
|
||
|
}
|
||
|
else if(metaSize == 3) {
|
||
|
#define register_multi3(TT0,TT1,TT2) if(setFactory<TT0,TT1,TT2>(rvec, out)) {} else
|
||
|
#include "ranges/multi_range_register.h"
|
||
|
#undef register_multi3
|
||
|
assert(0);
|
||
|
}
|
||
|
else if(metaSize == 4) {
|
||
|
#define register_multi4(TT0,TT1,TT2,TT3) if(setFactory<TT0,TT1,TT2,TT3>(rvec, out)) {} else
|
||
|
#include "ranges/multi_range_register.h"
|
||
|
#undef register_multi4
|
||
|
assert(0);
|
||
|
}
|
||
|
else {
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
std::shared_ptr<RangeFactoryBase> mkANONYMOUS(char const** dp, size_t metaSize)
|
||
|
{
|
||
|
std::shared_ptr<RangeFactoryBase> out = nullptr;
|
||
|
auto arf = std::make_shared<AnonymousRangeFactory>();
|
||
|
for(size_t i = 0; i != metaSize; ++i){
|
||
|
auto ff = createRangeFactory(dp);
|
||
|
arf->append( ff->create() );
|
||
|
}
|
||
|
out = arf;
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
|
||
|
std::shared_ptr<RangeFactoryBase> mkANY(int metaType, size_t metaSize, char const** dp)
|
||
|
{
|
||
|
std::shared_ptr<RangeFactoryBase> out = nullptr;
|
||
|
if(metaType == -1){
|
||
|
assert(0);
|
||
|
}
|
||
|
#define register_type(x) else if(x == metaType) { \
|
||
|
vector<TypeMap<x>::type> vd; \
|
||
|
metaCat(vd, *dp, metaSize); \
|
||
|
out = std::make_shared<SingleRangeFactory<TypeMap<x>::type, \
|
||
|
SpaceType::ANY> >(vd); }
|
||
|
#include "ranges/type_map.h"
|
||
|
#undef register_type
|
||
|
else {
|
||
|
assert(0);
|
||
|
}
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
std::shared_ptr<RangeFactoryBase> createSingleRangeFactory(const vector<char>*& d, int metaType, size_t size)
|
||
|
{
|
||
|
std::shared_ptr<RangeFactoryBase> out = nullptr;
|
||
|
if(metaType == -1){
|
||
|
assert(0);
|
||
|
}
|
||
|
#define register_type(x) else if(x == metaType) { \
|
||
|
vector<TypeMap<x>::type> vd(size); \
|
||
|
std::transform(d,d+size,vd.begin(), \
|
||
|
[](const vector<char>& c) \
|
||
|
{ assert(c.size() == sizeof(TypeMap<x>::type)); \
|
||
|
return *reinterpret_cast<TypeMap<x>::type const*>(c.data()); }); \
|
||
|
out = std::make_shared<SingleRangeFactory<TypeMap<x>::type, \
|
||
|
SpaceType::ANY> >(vd); }
|
||
|
#include "ranges/type_map.h"
|
||
|
#undef register_type
|
||
|
else {
|
||
|
assert(0);
|
||
|
}
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
std::shared_ptr<RangeFactoryBase> createRangeFactory(char const** dp)
|
||
|
{
|
||
|
DataHeader h = *reinterpret_cast<const DataHeader*>(*dp);
|
||
|
*dp += sizeof(DataHeader);
|
||
|
|
||
|
std::shared_ptr<RangeFactoryBase> out = nullptr;
|
||
|
|
||
|
if(h.multiple != 0){
|
||
|
if(h.spaceType == static_cast<int>( SpaceType::ANY )) {
|
||
|
// multi range
|
||
|
out = mkMULTI(dp, h.metaSize);
|
||
|
}
|
||
|
else if(h.spaceType == static_cast<int>( SpaceType::ANON ) ) {
|
||
|
// anonymous range
|
||
|
out = mkANONYMOUS(dp, h.metaSize);
|
||
|
}
|
||
|
else {
|
||
|
assert(0);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if(h.spaceType == static_cast<int>( SpaceType::ANY ) ) {
|
||
|
// generic single range
|
||
|
out = mkANY(h.metaType, h.metaSize, dp);
|
||
|
}
|
||
|
else if(h.spaceType == static_cast<int>( SpaceType::NONE ) ) {
|
||
|
// classic range
|
||
|
size_t size = *reinterpret_cast<const size_t*>(*dp);
|
||
|
out = std::make_shared<SingleRangeFactory<size_t,SpaceType::NONE> >(size);
|
||
|
}
|
||
|
#define include_range_type(x,n) else if(h.spaceType == static_cast<int>( SpaceType::x ) ) { \
|
||
|
out = mk##x(*dp, h.metaSize); }
|
||
|
#include "ranges/range_types/header.h"
|
||
|
#undef inlcude_range_type
|
||
|
else {
|
||
|
assert(0);
|
||
|
}
|
||
|
*dp += h.metaSize;
|
||
|
}
|
||
|
return out;
|
||
|
}
|
||
|
}
|