FieldPathNavigator.h
// FieldPathNavigator.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2022
@import "cxObject.h"
@import "IObject.h"
@import "FieldPath.h"
@import "ReflectedType.h"
#include "Ceda/cxUtils/Stream.h"
namespace ceda
{
enum class EFieldPathAccess
{
Read,
Write,
};
class @api FieldPathNavigator
{
public:
// Prepare to navigate the field of a datasource located at address 'data'
// using the given path.
FieldPathNavigator(const FieldPath& path, void* data, EFieldPathAccess mode);
// Prepare to iterate through a given path starting from an instance
// of a reflected class of type rc, located at address 'data'.
FieldPathNavigator(const FieldPath& path, void* data, EFieldPathAccess mode, const ReflectedClass& rc);
// Navigate the datasource which is of type 'rc'.
// If a field of type set<Key> is encountered then stop there, even though the
// path may include a key into the set.
// Returns false if the field has been $dropped.
bool NavigateReflectedClassInstance(const ReflectedClass& rc);
inline bool AtEnd() const { return ar_ == ar_end_; }
// After navigating the path, gives the address of the field
inline void* GetFieldAddress() const { return data_; }
// After navigating the path, can be used to get at the type of the field
inline ReflectedType GetFieldType() const { return rtype_; }
// Must only be called after navigating the path and both the following hold:
//
// 1) The field type is a set; and
//
// 2) It can be assumed that the original path included a key into this set
// (which hasn't been read from the path yet).
//
// Reads the key from the path and either inserts or deletes the key depending
// on 'ins'.
void InsertOrDeleteKeyInSet(bool ins);
// Must only be called after navigating the path and both the following hold:
//
// 1) The field type is a set; and
//
// 2) It can be assumed that the original path included a key into this set
// (which hasn't been read from the path yet).
//
// Reads the key from the path and returns true if the key is currently a member
// of the set.
bool IsKeyInSet();
private:
// Returns false if the field has been $dropped.
bool NavigateReflectedVariable();
private:
// Archive used to to deserialise elements of the path
InputArchive ar_;
InputArchive ar_end_;
// If the purpose of the path navigation is to perform an operation on a set, then
// this flag indicates whether an insertion or deletion is to be performed.
EFieldPathAccess mode_;
ReflectedType rtype_;
octet_t* data_;
};
// Navigate the given path through obj. Returns address of field and sets rtype to
// the type of the field.
// Returns nullptr if the field has been $dropped
@api void* NavigatePathToField(ptr<IObject> obj, const FieldPath& path, ReflectedType& rtype, bool writeAccess);
} // namespace ceda