ReflectedVectorBC.h
// ReflectedVectorBC.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2007
@import "IObject.h"
@import "ReflectionByteCode.h"
namespace ceda
{
enum EReflectedVectorCode
{
RVC_OK,
RVC_BAD_INDEX,
RVC_TYPE_ERROR
};
// Returns the current number of elements in a xvector<T> variable at address 'vec'.
// rbc describes the element type T.
@api ssize_t GetReflectedVectorSize(ReflectionByteCode rbc, const void* vec);
// Returns address of the element that was inserted
@api void* PushBackDefaultConstructedElementOntoReflectedVector(ReflectionByteCode rbc, void* vec);
// Concatenate array of T of size 'array_rhs_size' at address 'array_rhs' onto vector<T> at address 'vec_lhs'
// rbc describes the element type T.
@api void ConcatReflectedVectorFromArray(ReflectionByteCode rbc, void* vec_lhs, const void* array_rhs, ssize_t array_rhs_size);
// Concatenate vector<T> at address 'vec_rhs' onto vector<T> at address 'vec_lhs'
// rbc describes the element type T.
@api void ConcatReflectedVector(ReflectionByteCode rbc, void* vec_lhs, const void* vec_rhs);
@api bool ConcatReflectedVector(
ReflectionByteCode rbc_lhs, void* vec_lhs,
ReflectionByteCode rbc_rhs, const void* vec_rhs,
bool allowExplicitConversions);
// Insert elements copied from the range [s1,s2) from array in T of size src_n at address src into the xvector<T> at
// address dst at position d
// rbc describes the element type T.
// Returns false if any of d,s1 or s2 are invalid.
@api bool InsertFromArrayIntoReflectedVector(ReflectionByteCode rbc, void* dst, ssize_t d, const void* src, ssize_t src_n, ssize_t s1, ssize_t s2);
// Insert elements copied from the range [s1,s2) from xvector<T> at address src into the xvector<T> at
// address dst at position d
// rbc describes the element type T.
// Returns false if any of d,s1 or s2 are invalid.
@api bool InsertIntoReflectedVector(ReflectionByteCode rbc, void* dst, ssize_t d, const void* src, ssize_t s1, ssize_t s2);
// Returns RVC_OK, RVC_BAD_INDEX or RVC_TYPE_ERROR
@api EReflectedVectorCode InsertIntoReflectedVector(
ReflectionByteCode rbc_dst, void* dst, ssize_t d,
ReflectionByteCode rbc_src, const void* src, ssize_t s1, ssize_t s2,
bool allowExplicitConversions);
// Construct the xvector<T> at address dst from a copy of the slice [s1,s2) from the array in T of size src_n at
// src.
// rbc describes the element type T.
// Return false if [s1,s2) out of range
@api bool ConstructReflectedVectorFromSliceOfArray(ReflectionByteCode rbc, void* dst, const void* src, ssize_t src_n, ssize_t s1, ssize_t s2);
// Construct the xvector<T> at address dst from a copy of the slice [s1,s2) from the vector<T> at
// src.
// rbc describes the element type T.
// Return false if [s1,s2) out of range
@api bool ConstructFromSliceOfReflectedVector(ReflectionByteCode rbc, void* dst, const void* src, ssize_t s1, ssize_t s2);
// Perform push_back of the value of type T at address 'x' on the vector<T> at address 'vec'
// rbc describes the element type T.
@api void PushBackOntoReflectedVector(ReflectionByteCode rbc, void* vec, const void* x);
// Insert value of type T at address 'x' into the vector<T> at address 'vec', at index position i
// rbc describes the element type T.
// Returns false if i is out of range.
@api bool InsertElementIntoReflectedVector(ReflectionByteCode rbc, void* vec, ssize_t i, const void* x);
// Returns the address of the ith element of the array of T of size n at address 'array'
// rbc describes the element type T.
// Returns nullptr if i is invalid.
@api void* GetElementOfReflectedArray(ReflectionByteCode rbc, void* array, ssize_t n, ssize_t i);
// Returns the address of the ith element of the xvector<T> at address 'vec'
// rbc describes the element type T.
// Returns nullptr if i is invalid.
@api void* GetElementOfReflectedVector(ReflectionByteCode rbc, void* vec, ssize_t i);
// Erase the elements in the range [i1,i2) from the xvector<T> at address vec
// rbc describes the element type T.
// Returns false if [i1,i2) is an invalid range.
@api bool EraseSliceInReflectedVector(ReflectionByteCode rbc, void* vec, ssize_t i1, ssize_t i2);
// Reverse the elements of the xvector<T> as address vec
// rbc describes the element type T.
// Assumes that vector elements are relocatable
@api void ReverseReflectedVector(ReflectionByteCode rbc, void* vec);
// Returns the index of the first element in the array in T of size 'size' at address
// 'array' that is equivalent in value to the variable of type T at address 'elt'.
// 'rbc' describes the element type T.
@api ssize_t FindFirstElementInReflectedArray(ReflectionByteCode rbc, const void* array, ssize_t size, const void* elt);
// Returns the index of the first element in the xvector<T> at address 'vec' that is equivalent in
// value to the variable of type T at address 'elt'.
// 'rbc' describes the element type T.
@api ssize_t FindFirstElementInReflectedVector(ReflectionByteCode rbc, const void* vec, const void* val);
// Returns the number of elements in the array in T of size 'size' at address 'array' that
// are equivalent in value to the variable of type T at address 'elt'.
// 'rbc' describes the element type T.
@api ssize_t GetElementFrequencyInReflectedArray(ReflectionByteCode rbc, const void* array, ssize_t size, const void* elt);
// Returns the number of elements in the xvector<T> at address vec that are equivalent in value to
// the variable of type T at address val.
// rbc describes the element type T.
@api ssize_t GetElementFrequencyInReflectedVector(ReflectionByteCode rbc, const void* vec, const void* val);
// Sort the xvector<T> as address vec. rbc describes the element type T.
// Assumes that vector elements are relocatable
@api void SortReflectedVector(ReflectionByteCode rbc, void* vec);
///////////////////////////////////////////////////////////////////////////////////////////////////
// Methods that generate operations on vector models
/*
It is currently assumed that the elements are simple types without need for constructors
and destructors. Therefore (for example), copying an element only requires a memcpy.
*/
// Concatenate vector<T> at address 'vec_rhs' onto vector<T> at address 'vec_lhs'
// rbc describes the element type T.
@api void genop_ConcatVector(ptr<IObject> ds, const FieldPath& path,
ReflectionByteCode rbc, void* vec_lhs, const void* vec_rhs);
@api bool genop_ConcatVector(
ptr<IObject> ds, const FieldPath& path,
ReflectionByteCode rbc_lhs, void* vec_lhs,
ReflectionByteCode rbc_rhs, const void* vec_rhs,
bool allowExplicitConversions);
@api bool genop_InsertIntoVector(ptr<IObject> ds, const FieldPath& path,
ReflectionByteCode rbc, void* dst, ssize_t d, const void* src, ssize_t s1, ssize_t s2);
@api EReflectedVectorCode genop_InsertIntoVector(
ptr<IObject> ds, const FieldPath& path,
ReflectionByteCode rbc_dst, void* dst, ssize_t d,
ReflectionByteCode rbc_src, const void* src, ssize_t s1, ssize_t s2,
bool allowExplicitConversions);
@api void genop_PushBackOntoVector(
ptr<IObject> ds, const FieldPath& path,
ReflectionByteCode rbc, void* vec, const void* x);
@api bool genop_InsertElementIntoVector(
ptr<IObject> ds, const FieldPath& path,
ReflectionByteCode rbc, void* vec, ssize_t i, const void* x);
@api bool genop_EraseSliceInVector(
ptr<IObject> ds, const FieldPath& path,
ReflectionByteCode rbc, void* vec, ssize_t i1, ssize_t i2);
///////////////////////////////////////////////////////////////////////////////////////////////////
// ReflectedVectorBC
struct @api ReflectedVectorBC
{
void Init(ReflectionByteCode rbcElement);
void clear(VectorOfByte& vf) const;
void resize(VectorOfByte& vf, ssize_t size) const;
// Serialise the elements of vf in the index range [p,p+n) to the given archive
void SerialiseElements(Archive& ar, const VectorOfByte& vf, ssize_t p, ssize_t n);
void Serialise(Archive& ar, const VectorOfByte& vf) const;
void Deserialise(InputArchive& ar, VectorOfByte& vf) const;
void ScanOver(InputArchive& ar) const;
void EraseRange(VectorOfByte& vf, ssize_t p1, ssize_t p2) const;
void DestructElements(VectorOfByte& vf, ssize_t p1, ssize_t p2) const;
inline const octet_t* MoveFrom(VectorOfByte& vf, ssize_t d, const octet_t* src, ssize_t count)
{
const octet_t* src_end = src + count * elementSize;
vf.insert(d*elementSize, src, src_end);
return src_end;
}
ReflectionByteCode rbcElement;
ssize_t elementSize = 0;
bool isPOD = false;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
// ReflectedVectorBCVariable
struct ReflectedVectorBCVariable
{
ReflectedVectorBCVariable(const ReflectedVectorBC& rv) : rv(rv) {}
inline ssize_t size() const
{
cxAssert(data->size() % rv.elementSize == 0);
ssize_t size = data->size() / rv.elementSize;
cxAssert(size >= 0);
return size;
// Much slower because the elementSize is calculated from the byte code every time
//return GetReflectedVectorSize(rv.rbcElement,data);
}
inline void clear()
{
rv.clear(*data);
}
inline void resize(ssize_t newSize)
{
rv.resize(*data, newSize);
}
inline void reverse()
{
ReverseReflectedVector(rv.rbcElement, data);
}
inline void sort()
{
SortReflectedVector(rv.rbcElement, data);
}
inline void Serialise(Archive& ar) const
{
rv.Serialise(ar, *data);
}
inline void Deserialise(InputArchive& ar)
{
rv.Deserialise(ar, *data);
}
inline void EraseRange(ssize_t p1, ssize_t p2)
{
rv.EraseRange(*data, p1, p2);
}
inline void erase(ssize_t pos, ssize_t count)
{
EraseRange(pos, pos+count);
}
bool Insert(ssize_t d, const void* src, ssize_t s1, ssize_t s2)
{
return InsertIntoReflectedVector(rv.rbcElement, data, d, src, s1, s2);
}
inline bool insert(ssize_t i, const void* x)
{
return InsertElementIntoReflectedVector(rv.rbcElement, data, i, x);
}
inline void* GetElement(ssize_t i)
{
ssize_t s = data->size();
cxAssert(s % rv.elementSize == 0);
ssize_t n = s / rv.elementSize;
if (0 <= i && i < n)
{
return &(*data)[i * rv.elementSize];
}
else
{
return nullptr;
}
// Much slower because the elementSize is calculated from the byte code every time
//return GetElementOfReflectedVector(rv.rbcElement, data, i);
}
inline const void* GetElement(ssize_t i) const
{
return GetElementOfReflectedVector(rv.rbcElement, data, i);
}
inline void* PushBackDefaultConstructedElement()
{
return PushBackDefaultConstructedElementOntoReflectedVector(rv.rbcElement, data);
}
inline void AppendDefaultConstructed(ssize_t count)
{
for (int i=0 ; i < count ; ++i)
{
PushBackDefaultConstructedElement();
}
}
inline void ScanOver(InputArchive& ar) const { rv.ScanOver(ar); }
const ReflectedVectorBC& rv;
VectorOfByte* data = nullptr;
};
} // namespace ceda