////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2001-2026 Alexey Kuryakin daqgroup@mail.ru under MIT license //
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// This file is part of the CRW-DAQ project by DaqGroup - component CRWLIB.   //
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Purpose:                                                                   //
// This unit implement dereference - resolve object references.               //
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// History:                                                                   //
// 20241116 - Created by A.K.                                                 //
////////////////////////////////////////////////////////////////////////////////

unit _crw_deref; //  DeReference - resolve object references.

{$I _crw_sysdef.inc}

{$I _crw_sysmode.inc}

interface

uses
 //////////////////////////////////////////////////////
 {$I _crw_uses_first.inc} // NB: MUST BE FIRST USES !!!
 //////////////////////////////////////////////////////
 sysutils, classes, math,
 _crw_alloc, _crw_task, _crw_daqtags;

////////////////////////////////////////////////////////////////////////////////
// crwdaq uses integer references to identify objects safely.                 //
// It's is more safe because references can be checked (but not pointers).    //
// Tasks reference is tid (task id) in range [task_ref_min..task_ref_max].    //
// DAQ system data tags has reference in range [tag_ref_min..tag_ref_max].    //
// All objects inherited from TMasterObject has reference in ObjectRegistry.  //
////////////////////////////////////////////////////////////////////////////////

const           // Reference type:
 rt_Empty  = 0; // Zero reference (not assigned).
 rt_TaskId = 1; // Task reference [task_ref_min..task_ref_max].
 rt_DaqTag = 2; // DAQ tag refer. [tag_ref_min..tag_ref_max].
 rt_Object = 3; // ObjectRegistry [ObjectRegistry.ref_min..ref_max].
 rt_BadRef = 4; // Invalid reference (the object does not exist).

type
 TReferenceType = rt_Empty..rt_BadRef;

 {
 Get object reference.
 It's TTask.Tid or TMasterObject.Ref.
 }
function GetObjectReference(aObject:TObject):Integer;

 {
 Find object by reference in Task table or in ObjectRegistry.
 }
function ResolveObjectReference(ref:Integer):TObject;

 {
 Get actual reference type.
 }
function GetReferenceType(ref:Integer):TReferenceType;

 {
 Get possible reference type (by range).
 Refer Object may not exist
 }
function GetReferenceRange(ref:Integer):TReferenceType;

implementation

function GetObjectReference(aObject:TObject):Integer;
begin
 Result:=0;
 if (aObject is TTask) then Result:=TTask(aObject).Tid else
 if (aObject is TMasterObject) then Result:=TMasterObject(aObject).Ref;
end;

function ResolveObjectReference(ref:Integer):TObject;
begin
 Result:=nil;
 if (ref=0) then Exit;
 Result:=task_ref(ref);
 if Assigned(Result) then Exit;
 Result:=ObjectRegistry[ref];
end;

function GetReferenceType(ref:Integer):TReferenceType;
begin
 if (ref=0) then Result:=rt_Empty else
 if (task_ref(ref) is TTask) then Result:=rt_TaskId else
 if (TypeTag(ref)>0) then Result:=rt_DaqTag else
 if (ObjectRegistry[ref] is TMasterObject) then Result:=rt_Object else
 Result:=rt_BadRef;
end;

function GetReferenceRange(ref:Integer):TReferenceType;
begin
 if (ref=0) then Result:=rt_Empty else
 if InRange(ref,task_ref_min,task_ref_max) then Result:=rt_TaskId else
 if InRange(ref,tag_ref_min,tag_ref_max) then Result:=rt_DaqTag else
 if InRange(ref,ObjectRegistry.ref_min,ObjectRegistry.ref_max) then Result:=rt_Object else
 Result:=rt_BadRef;
end;

///////////////////////////////////////
// Unit initialization and finalization
///////////////////////////////////////

procedure Init_crw_deref;
begin
end;

procedure Free_crw_deref;
begin
end;

initialization

 Init_crw_deref;

finalization

 Free_crw_deref;

end.

//////////////
// END OF FILE
//////////////

