ReflectedArray.h
// ReflectedArray.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2022
@import "IObject.h"
@import "Array.h"
@import "ReflectedType.h"
namespace ceda
{
/*
Defines a base class suitable for some ModelAttribute_XXX (call it E) which wraps one of
the elements of an array of type std::array<T,N> wrapped with ModelAttribute_array<ArrayBase,E,T,N>
*/
template <typename ArrayBase, typename T, ssize_t N>
class ArrayElementBase
{
public:
ArrayElementBase(ArrayBase* a, ssize_t i) : a(a),i(i) {}
typedef typename ArrayBase::FinalClass FinalClass;
T& model() { return a->model()[i]; }
FieldPath path() const { return a->path() + i; }
FinalClass* self() { return a->self(); }
private:
ArrayBase* a; // Can't be by reference because this element class must be copiable
ssize_t i; // Index position
};
// Wraps std::array<T,N> where each element of type T is wrapped by E. i.e. E is some
// ModelAttribute_xxx parameterised on base ArrayElementBase<Base,T,N>
template <typename E, class Base, typename T, ssize_t N>
struct ModelAttribute_array : public Base
{
CEDA_MODEL_ATTRIBUTE_BOILERPLATE(`std::array<T,N>`, ModelAttribute_array)
static ssize_t size() { return N; }
E operator[](ceda::ssize_t i)
{
return (E&) ArrayElementBase<Base,T,N>(this,i);
}
// Element is returned by const value - still ends up prohibiting non-const method
// calls on Element!
const E operator[](ceda::ssize_t i) const
{
return const_cast<ModelAttribute_array*>(this)->operator[](i);
}
};
@if (false)
{
// Example
union
{
// xvector<char8> s
struct attribute_s
{
typedef FinalClass FinalClass;
FinalClass* self() { return ATTRIB_CAST(FinalClass,s); }
ceda::xvector<ceda::char8>& model() { return self()->_model_.s; }
static void path(ceda::FieldPath& _path) { octet_t* p=_path.InitLocalBuffer(1); p[0]=0; }
static ceda::FieldPath path() { ceda::FieldPath _path; path(_path); return _path; }
};
ModelAttribute_vector<attribute_s, ceda::char8> s;
// int32 A[10]
struct attribute_A
{
typedef FinalClass FinalClass;
FinalClass* self() { return ATTRIB_CAST(FinalClass,A); }
std::array<ceda::int32,10>& model() { return self()->_model_.A; }
static void path(ceda::FieldPath& _path) { octet_t* p=_path.InitLocalBuffer(1); p[0]=1; }
static ceda::FieldPath path() { ceda::FieldPath _path; path(_path); return _path; }
};
ModelAttribute_array<
ModelAttribute_assign<ArrayElementBase<attribute_A,ceda::int32,10>,ceda::int32>,
attribute_A,
ceda::int32,
10> A;
// int32 B[10][5]
struct attribute_B
{
typedef FinalClass FinalClass;
FinalClass* self() { return ATTRIB_CAST(FinalClass,B); }
std::array<std::array<ceda::int32,10>,5>& model() { return self()->_model_.B; }
static void path(ceda::FieldPath& _path) { octet_t* p=_path.InitLocalBuffer(1); p[0]=2; }
static ceda::FieldPath path() { ceda::FieldPath _path; path(_path); return _path; }
};
ModelAttribute_array<
ModelAttribute_array<
ModelAttribute_assign<ArrayElementBase<ArrayElementBase<attribute_B,std::array<ceda::int32,10>,5>,ceda::int32,10>,ceda::int32>,
ArrayElementBase<attribute_B,std::array<ceda::int32,10>,5>,
ceda::int32,
10>,
attribute_B,
std::array<ceda::int32,10>,
5> B;
};
}
struct ReflectedArray
{
inline void* GetArrayElement(void* data, ssize_t index) const
{
cxAssert(data);
cxAssert(count > 0);
cxAssert(0 <= index && index < count);
const TypeOps* elementOps = GetTypeOps(element);
cxAssert(elementOps);
cxAssert(elementOps->size > 0);
return (octet_t*) data + index * elementOps->size;
}
inline const void* GetArrayElement(const void* data, ssize_t index) const
{
return GetArrayElement(const_cast<void*>(data), index);
}
const TypeOps& ops;
ReflectedType element;
ssize_t count;
};
@api xostream& operator<<(xostream& os, const ReflectedArray& r);
template<typename T> struct is_array { constexpr static bool value = false; };
template<typename T, size_t N> struct is_array<std::array<T,N>> { constexpr static bool value = true; };
template<typename T, size_t N>
inline const ReflectedArray& GetReflectedArray()
{
static ReflectedArray s =
{
GetTypeOpsX<std::array<T,N>>(),
GetReflectedType<T>(),
N
};
return s;
}
template<typename T, size_t N>
struct GetReflectedType_class<std::array<T,N>>
{
static inline ReflectedType get()
{
ReflectedType r;
r.tag = EReflectedTypeTag::Array;
r.Array = &GetReflectedArray<T,N>();
return r;
}
};
} // namespace ceda