ReflectedField.h

// ReflectedField.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2022

@import "IObject.h"
@import "ReflectedType.h"
@import "ReflectedMap.h"
@import "ReflectedSet.h"

namespace ceda
{
///////////////////////////////////////////////////////////////////////////////////////////////////
// ReflectedField

$struct+ ReflectedField <<os>>
{
    $ConstStringZ GetName() const { return name; }
    $ssize_t GetOffset() const { return offset; }
    void Write(xostream& os) const;
    
    //////////////// State //////////////////

    ConstStringZ name;
    ssize_t offset;
    const octet_t* byteCode;
    ReflectedType rtype;
};

///////////////////////////////////////////////////////////////////////////////////////////////////
// ReflectedDepField

$struct+ ReflectedDepField <<os>>
{
    $ConstStringZ GetName() const { return name; }
    $ssize_t GetOffset() const { return offset; }
    void Write(xostream& os) const;
    
    //////////////// State //////////////////

    ConstStringZ name;
    ssize_t offset;           // 0 for an agent
    const octet_t* byteCode;
    ssize_t depNodeOffset;
    ReflectedType rtype;
};

// Collects together a set of function pointers that allow clients of the reflection
// system to make use of a given xmap<Key,Value>
typedef IXMap::FnTable XMapFns;

// Collects together a set of function pointers that allow clients of the reflection
// system to make use of a given xset<Key>
typedef IXSet::FnTable XSetFns;

union PtrMapOrSetFns
{
    const XMapFns* mapFns;
    const XSetFns* setFns;
};

///////////////////////////////////////////////////////////////////////////////////////////////////
// ReflectedModelField

$struct+ ReflectedModelField <<os>>
{
    $ConstStringZ GetName() const { return name; }
    $ssize_t GetOffset() const { return offset; }
    $bool Present() const { return rsn2 == -1; }
    $RSN GetRsn1() const { return rsn1; }
    $RSN GetRsn2() const { return rsn2; }
    void Write(xostream& os) const;
    
    //////////////// State //////////////////

    ConstStringZ name;
    ssize_t offset;         // -1 if dropped
    const octet_t* byteCode;
    RSN rsn1;             // RSN when field was added
    RSN rsn2;             // RSN when field was dropped, or -1 if still present

    // A CDM tuple uses a ReflectedModelField for each attribute in the model.
    // A datasource has the concept of a path down through the attributes, and this
    // recurses into nested maps, arrays and tuples.
    // For a given tuple attribute (i.e. ReflectedModelField) we have nested maps and 
    // arrays associated with the given byte code.  In particular for the nested maps
    // we need to record the XMapFns. 
    //
    // Maps can nest.  Eg   map<string, map<string, int> >.  Let 'n' denote the total
    // number of map nestings of the field.
    // m_mapFns is the address of an array XMapFns[n], or nullptr if n = 0.
    // As we navigate the path for a given field of a model, we step through the byte 
    // code as well as the array.
    const PtrMapOrSetFns* mapOrSetFns;

    ReflectedType rtype;
};

inline const ReflectedField& AsReflectedField(const ReflectedModelField& rf)
{
    // Assumes that the ReflectedModelField begins with all the members defined in ReflectedField
    return reinterpret_cast<const ReflectedField&>(rf);
}
} // namespace ceda