RV_type.h
// RV_type.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2022
@import "Object.h"
@import "ConstructDestructCopyAssignReflectedVariable.h"
#include "Ceda/cxUtils/StringExt.h"
namespace ceda
{
class RV_Class;
class RR_Class;
/*
$mixin RVmixin
{
void Write(xostream& os) const
{
if (ops().HasPrint())
{
ops().PrintVariable(os, data());
}
else
{
os << "instance of " << typeName();
}
}
};
*/
/*
class RV_base
{
public:
RV_base(ssize_t size) : data_(size) {}
inline void* data() { return data_.data(); }
inline const void* data() const { return data_.data(); }
inline ssize_t size() const { return data_.size(); }
private:
VectorOfByte data_;
};
*/
/*
class @api RV_Type
{
public:
RV_Type(const ReflectedType& type);
RV_Type(const RV_Type& rhs);
RV_Type& operator=(const RV_Type& rhs);
~RV_Type();
inline void* data() { return data_.data(); }
inline const void* data() const { return data_.data(); }
inline const char* TypeName() const { return rc_.name; }
inline const ReflectedClass& rc() const { return rc_; }
inline const TypeOps& ops() const { return rc_.ops; }
inline ssize_t size() const { return data_.size(); }
bool assign(const RV_Class& rhs, bool allowExplicitConversions);
bool assign(const RR_Class& rhs, bool allowExplicitConversions);
void Write(xostream& os) const;
private:
VectorOfByte data_;
const TypeOps& ops_;
ReflectedType type_;
};
*/
class @api RV_Class
{
public:
RV_Class(const ReflectedClass& rc);
RV_Class(const RV_Class& rhs);
RV_Class(const RR_Class& rhs);
RV_Class& operator=(const RV_Class& rhs);
RV_Class& operator=(const RR_Class& rhs);
~RV_Class();
inline void* data() { return data_.data(); }
inline const void* data() const { return data_.data(); }
inline const char* TypeName() const { return rc_.name; }
inline const ReflectedClass& rc() const { return rc_; }
inline const TypeOps& ops() const { return rc_.ops; }
inline ssize_t size() const { return data_.size(); }
bool assign(const RV_Class& rhs, bool allowExplicitConversions);
bool assign(const RR_Class& rhs, bool allowExplicitConversions);
void Write(xostream& os) const;
private:
const ReflectedClass& rc_;
VectorOfByte data_;
};
class @api RR_Class
{
public:
RR_Class(const ReflectedClass& rc, void* data);
RR_Class(RV_Class& rhs);
RR_Class(RR_Class& rhs);
RR_Class& operator=(const RV_Class& rhs);
RR_Class& operator=(const RR_Class& rhs);
inline void* data() { return data_; }
inline const void* data() const { return data_; }
inline const char* TypeName() const { return rc_.name; }
inline const ReflectedClass& rc() const { return rc_; }
inline const TypeOps& ops() const { return rc_.ops; }
ssize_t size() const { return ops().GetSize(); }
bool assign(const RV_Class& rhs, bool allowExplicitConversions);
bool assign(const RR_Class& rhs, bool allowExplicitConversions);
void Write(xostream& os) const;
private:
const ReflectedClass& rc_;
void* data_;
};
#if 0
/*
It might be a bad idea to have the bool flags 'owned' and 'readOnly'.
It prevents us from writing copy assignment and copy constructors.
Instead it might be better to
1) Ignore constness - that falls outside the scope
2) Have two kinds of reflected variables - one for owned and one for aliases
RV_Class - reflected variable which owns the object
RR_Class - reference to a reflected variable
*/
struct RV_base
{
void* data; // Ptr to the variable. Never NULL
bool owned; // Does this object own the (heap allocated) variable?
bool readOnly; // Do we impose read-only access to the variable?
};
struct RV_Type : RV_base
{
const ReflectedType* r;
};
struct RV_Leaf : RV_base
{
const ReflectedLeafType* r;
};
struct RV_Class : RV_base
{
const ReflectedClass& r;
// Create mutable owned instance
RV_Class(const ReflectedClass& r) :
r(r),
data( new octet_t[r.size] ),
owned(true),
readOnly(false)
{
ConstructReflectedClassVariable(r,data);
}
// Create mutable aliased instance
RV_Class(const ReflectedClass& r, void* data) :
r(r),
data(data),
owned(false),
readOnly(false)
{
}
// Create immutable aliased instance
RV_Class(const ReflectedClass& r, const void* data) :
r(r),
data(const_cast<void*>(data)),
owned(false),
readOnly(true)
{
}
RV_Class(const RV_Class& rhs) :
r(r)
{
if (rhs.owned)
{
// Create a copy
data = new octet_t[r.size];
owned = true;
readOnly = false;
}
}
/*
static RV_Class Create(const ReflectedClass& rc)
{
RV_Class rv;
rv.data = new octet_t[rc.size];
ConstructReflectedClassVariable(rc, rv.data);
rv.r = &rc;
rv.owned = true;
rv.readOnly = false;
return rv;
}
*/
static std::optional<RV_Class> CreateCopy(const ReflectedClass& rc, const RV_Class& rhs, bool allowExplicitConversions)
{
RV_Class rv;
rv.data = new octet_t[rc.size];
if (CopyConstructReflectedClassVariable(rc, rv.data, *rhs.r, rhs.data, allowExplicitConversions))
{
rv.r = &rc;
rv.owned = true;
rv.readOnly = false;
return rv;
}
else
{
delete [] (octet_t*) rv.data;
return nullptr;
}
}
~RV_Class()
{
if (owned)
{
DestructReflectedClassVariable(*r, data);
delete [] (octet_t*)data;
}
}
void assign(const RV_Class& rhs)
{
if (rhs.r == r)
{
AssignReflectedClassVariable(*r, data, rhs.data);
}
}
bool assign(const RV_Class& rhs, bool allowExplicitConversions)
{
return AssignReflectedClassVariable(*r, data, *rhs.r, rhs.data, allowExplicitConversions);
}
};
struct RV_Variant : RV_base
{
const ReflectedVariant* r;
};
struct RV_Enum : RV_base
{
const ReflectedEnum* r;
};
struct RV_Array : RV_base
{
const ReflectedArray* r;
};
struct RV_DynArray : RV_base
{
const ReflectedDynArray* r;
};
struct RV_Vector : RV_base
{
const ReflectedVector* r;
};
struct RV_Map : RV_base
{
const ReflectedMap* r;
};
struct RV_Set : RV_base
{
const ReflectedSet* r;
};
struct RV_Pointer : RV_base
{
const ReflectedPointer* r;
};
struct RV_Ptr : RV_base
{
const ReflectedInterfacePtr* r;
};
struct RV_Pref : RV_base
{
const ReflectedPref* r;
};
struct RV_OpenVariant : RV_base
{
const ReflectedOpenVariant* r;
};
#endif
} // namespace ceda