Represents information about a $variant declaration in the Xc++ language.
$struct+ ReflectedVariant
{
$ConstStringZ GetName() const { return m_name; }
$ssize_t GetSize() const { return m_size; }
$ssize_t GetNumFields() const { return m_numFields; }
$const ReflectedField& GetField(ssize_t i) const { return m_fields[i]; }
//////////////// State //////////////////
ConstStringZ m_name;
ssize_t m_size;
const octet_t* m_metaData;
const ReflectedField* m_fields;
ssize_t m_numFields;
ConstStringZ const* m_stringTable;
TypeOps m_ops;
};
ConstStringZ m_name
The fully qualified name of the variant represented as a pointer to a UTF-8 encoded null-terminated string (see ConstStringZ).
ssize_t m_size
The size of the variant in bytes.
const octet_t* m_metaData
Pointer to metadata byte code on the variant or null if no metadata declared.
const ReflectedField* m_fields
Pointer to an array of ReflectedField elements. These correspond to the member variables of the variant in the same order in which they appear in the definition.
ssize_t m_numFields
The number of elements in the m_fields array.
ConstStringZ const* m_stringTable
The address of an array of pointers to UTF-8 encoded null-terminated strings (see ConstStringZ), which is the string table associated with the byte code used to represent the types of the variant members and the metadata on the variant. May be null if no string table is required.
TypeOps m_ops
Records pointers to various functions to construct, destruct, copy construct, etc object instances (see TypeOps).
The following variant expressed in xc++
namespace ns
{
$variant+ X
{
void a;
int32 b;
float64 c;
string8 d;
};
}
causes the following C++ implementation to be generated:
namespace ns
{
class X
{
public:
struct a
{
enum { tag=0 };
typedef void Value;
};
struct b
{
enum { tag=1 };
typedef ceda::int32 Value;
b(const Value& _v) : value(_v) {}
Value value;
};
struct c
{
enum { tag=2 };
typedef ceda::float64 Value;
c(const Value& _v) : value(_v) {}
Value value;
};
struct d
{
enum { tag=3 };
typedef ceda::string8 Value;
d(const Value& _v) : value(_v) {}
Value value;
};
template<typename T> struct _mapvalue_ { enum { tag=T::tag }; typedef typename T::Value Value; };
X(a const& _rhs)
{
_tag = 0;
}
X(b const& _rhs)
{
_tag = 1;
new (_data) b(_rhs);
}
X(c const& _rhs)
{
_tag = 2;
new (_data) c(_rhs);
}
X(d const& _rhs)
{
_tag = 3;
new (_data) d(_rhs);
}
X(X const& _rhs);
~X();
X& operator=(X const& _rhs)
{
if (this != &_rhs) { this->~X(); new (this) X(_rhs); }
return *this;
}
void VisitObjects(ceda::IObjectVisitor&) const;
void VisitPrefs(ceda::IPrefVisitor&) const;
ceda::int32 GetTag() const { return _tag; }
bool operator==(X const& _rhs) const;
bool operator!=(X const& _rhs) const { return !operator==(_rhs); }
bool operator<(X const& _rhs) const;
template<typename T> bool is() const { return is((T*)0); }
template<typename T> const typename _mapvalue_<T>::Value& as() const { return as((T*)0); }
template<typename T> typename _mapvalue_<T>::Value& as() { return as((T*)0); }
void Write(ceda::xostream&) const;
void Serialise(ceda::Archive&) const;
ceda::InputArchive Deserialise(ceda::InputArchive);
private:
template<typename T> typename T::Value const& as(T*) const { cxAssert(is<T>()); return *(typename T::Value const*)_data; }
template<typename T> typename T::Value& as(T*) { cxAssert(is<T>()); return *(typename T::Value*)_data; }
bool is(a*) const { return _tag == 0; }
bool is(b*) const { return _tag == 1; }
bool is(c*) const { return _tag == 2; }
bool is(d*) const { return _tag == 3; }
ceda::int32 _tag;
ceda::octet_t _data[CEDA_MAX4(0,sizeof(b),sizeof(c),sizeof(d))];
};
inline ceda::IObjectVisitor& operator<<(ceda::IObjectVisitor& _v,X const& _x) { _x.VisitObjects(_v); return _v; }
inline ceda::IObjectVisitor& operator<<(ceda::IObjectVisitor& _v,X const*) { return _v; }
inline ceda::IPrefVisitor& operator<<(ceda::IPrefVisitor& _v,X const& _x) { _x.VisitPrefs(_v); return _v; }
inline ceda::xostream& operator<<(ceda::xostream& _os,X const& _x) { _x.Write(_os); return _os; }
ceda::ReflectedVariant const& _GetReflected(X const*);
ceda::TypeOps const& _GetTypeOps(X const*);
inline ceda::Archive& operator<<(ceda::Archive& _ar,X const& _x) { _x.Serialise(_ar); return _ar; }
inline ceda::InputArchive operator>>(ceda::InputArchive _ar, X& _x) { return _x.Deserialise(_ar); }
inline X::X(X const& _rhs)
{
_tag = _rhs._tag;
switch(_tag)
{
case 1 : new (_data) b(_rhs.as<b >()); break;
case 2 : new (_data) c(_rhs.as<c >()); break;
case 3 : new (_data) d(_rhs.as<d >()); break;
}
}
inline X::~X()
{
switch(_tag)
{
case 3 : as<d >().ceda::string8::~string8(); break;
}
}
inline bool X::operator==(X const& _rhs) const
{
if (_tag != _rhs._tag) return false;
switch(_tag)
{
case 1 : return as<b >() == _rhs.as<b >();
case 2 : return as<c >() == _rhs.as<c >();
case 3 : return as<d >() == _rhs.as<d >();
}
return true;
}
inline bool X::operator<(X const& _rhs) const
{
if (_tag < _rhs._tag) return true;
if (_tag > _rhs._tag) return false;
switch(_tag)
{
case 1 : return as<b >() < _rhs.as<b >();
case 2 : return as<c >() < _rhs.as<c >();
case 3 : return as<d >() < _rhs.as<d >();
}
return false;
}
inline void X::Write(ceda::xostream& _os) const
{
switch(_tag)
{
case 0 : _os << "a"; break;
case 1 : _os << "b(" << as<b >() << ')'; break;
case 2 : _os << "c(" << as<c >() << ')'; break;
case 3 : _os << "d(" << as<d >() << ')'; break;
default: cxAssert(0);
}
}
inline void X::VisitObjects(ceda::IObjectVisitor& _v) const
{
}
inline void X::VisitPrefs(ceda::IPrefVisitor& _v) const
{
}
inline void X::Serialise(ceda::Archive& _ar) const
{
ceda::SerialiseVariableLengthUint32(_ar,_tag);
switch(_tag)
{
case 1 : _ar << as<b >(); break;
case 2 : _ar << as<c >(); break;
case 3 : _ar << as<d >(); break;
}
}
inline ceda::InputArchive X::Deserialise(ceda::InputArchive _ar)
{
this->~X();
_ar = ceda::DeserialiseVariableLengthUint(_ar,_tag);
switch(_tag)
{
case 1 : new (_data) ceda::int32(); _ar = _ar >> as<b >(); break;
case 2 : new (_data) ceda::float64(); _ar = _ar >> as<c >(); break;
case 3 : new (_data) ceda::string8(); _ar = _ar >> as<d >(); break;
}
return _ar;
}
} //ns
namespace ceda
{
template<> struct TypeTraits<ns::X>
{
static const bool is_exported = 1;
static const bool is_reflected = 1;
static const bool is_registered = 1;
static const ceda::ETypeTraitKind kind = ceda::TTK_variant;
static const bool has_metadata = 0;
};
} // namespace ceda
and the following code to register a ReflectedVariant for variant X:
//### $variant+ ns::X
namespace ceda { XTarget* Ceda_Core_Object_exObject_GetXTarget(); }
namespace ns
{
ceda::ReflectedVariant const& _GetReflected(X const*)
{
static const ceda::octet_t X_tag_a[] =
{
0x00
};
static const ceda::octet_t X_tag_b[] =
{
0x04
};
static const ceda::octet_t X_tag_c[] =
{
0x0d
};
static const ceda::octet_t X_tag_d[] =
{
0x10
};
static const ceda::ReflectedField X_fields[] =
{
{ "a", 4, X_tag_a },
{ "b", 4, X_tag_b },
{ "c", 4, X_tag_c },
{ "d", 4, X_tag_d },
};
static const ceda::ReflectedVariant X_variant =
{
"ns::X",
sizeof(X),
0,
X_fields,4,
0,
{
sizeof(X),
(ceda::CompareVariableFn) (bool (*)(X const*, X const*)) ceda::VariableEqual<X>,
(ceda::CompareVariableFn) (bool (*)(X const*, X const*)) ceda::VariableLess<X>,
(ceda::PrintVariableFn) (void (*)(ceda::xostream&, X const*)) ceda::PrintVariable<X>,
0,
(ceda::CopyConstructArrayFn) (void (*)(X*, ceda::ssize_t, X const*, ceda::ssize_t, ceda::ssize_t)) ceda::CopyConstructArray<X>,
(ceda::AssignArrayFn) (void (*)(X*, ceda::ssize_t, X const*, ceda::ssize_t, ceda::ssize_t)) ceda::AssignArray<X>,
(ceda::DestructArrayFn) (void (*)( X*, ceda::ssize_t, ceda::ssize_t)) ceda::DestructArray<X>,
(ceda::SerialiseArrayFn) (void (*)(ceda::Archive&, X const*, ceda::ssize_t, ceda::ssize_t)) ceda::SerialiseArray<X>,
(ceda::DeserialiseArrayFn) (ceda::InputArchive (*)(ceda::InputArchive, X*, ceda::ssize_t, ceda::ssize_t)) ceda::DeserialiseArray<X>,
0,
0,
(ceda::FindInArrayFn) (ceda::ssize_t (*)(X const*, ceda::ssize_t, ceda::ssize_t, X const*)) ceda::BinaryLowerBound<X>,
(ceda::FindInArrayFn) (ceda::ssize_t (*)(X const*, ceda::ssize_t, ceda::ssize_t, X const*)) ceda::BinaryUpperBound<X>
}
};
return X_variant;
}
ceda::TypeOps const& _GetTypeOps(X const*)
{
return ceda::GetReflectedVariant<X>().m_ops;
}
// Registration of $variant+ ns::X
void _Register_X()
{
cxVerify(ceda::RegisterReflectedVariant(&_GetReflected( (X*) 0),ceda::Ceda_Core_Object_exObject_GetXTarget()) == ceda::NSE_OK);
}
} // ns