unit RyuLibBase;

// Note :
// * 여기 저기서 사용하는 공용 루틴이나 타입을 정의 한다.

interface

uses
  MemoryPool, MemoryRing,
  Windows, Classes, SysUtils;

type
  TNewDataEvent = procedure(Sender:TObject; const AData:pointer; const ASize:integer) of object;
  TFileNameEvent = procedure(Sender:TObject; const AFileName:string) of object;

  TPacket = packed record
    Size : DWORD;
    DataStart : byte;
    class function HeaderSize:integer; static;  // SizeOf(Size:DWord)
    function PacketSize:integer;
  end;
  PPacket = ^TPacket;

  TObjectClass = class of TObject;

  // 참조 카운트에 의해서 메모리 해제를 허용하지 않음
  TInterfaceBase = class (TObject)
  private
  protected
    function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
    function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;
  public
  end;

procedure CreateObject(AInstanceClass: TObjectClass; var AReference);

function CreatePacket(AMemoryPool:TMemoryPool; AData:pointer; ASize:integer):PPacket;
function CreatePacketMemoryPage(AMemoryPool:TMemoryPool; AData:pointer; ASize:integer):TMemoryPage;

implementation

procedure CreateObject(AInstanceClass: TObjectClass; var AReference);
begin
  {$IF DEFINED(CLR)}
    TObject(AReference) := AInstanceClass.Create;
  {$ELSE}
    TObject(AReference) := AInstanceClass.NewInstance;
    TObject(AReference).Create;
  {$IFEND}
end;

function CreatePacket(AMemoryPool:TMemoryPool; AData:pointer; ASize:integer):PPacket;
var
  MemoryPage : TMemoryPage;
begin
  MemoryPage := AMemoryPool.GetMem(ASize + SizeOf(DWord));

  Result := MemoryPage.Data;
  Result^.Size := ASize;

  Move(AData^, Result^.DataStart, ASize);
end;

function CreatePacketMemoryPage(AMemoryPool:TMemoryPool; AData:pointer; ASize:integer):TMemoryPage;
var
  pPacket : ^RyuLibBase.TPacket;
begin
  Result := AMemoryPool.GetMem(ASize + SizeOf(DWord));

  pPacket := Result.Data;
  pPacket^.Size := ASize;

  Move(AData^, pPacket^.DataStart, ASize);
end;

{ TPacket }

class function TPacket.HeaderSize: integer;
begin
  Result := SizeOf(DWord);
end;

function TPacket.PacketSize: integer;
begin
  Result := SizeOf(Size) + Size;
end;

{ TInterfaceBase }

function TInterfaceBase.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
  if GetInterface(IID, Obj) then
    Result := 0
  else
    Result := E_NOINTERFACE;
end;

function TInterfaceBase._AddRef: Integer;
begin
  Result := -1;
end;

function TInterfaceBase._Release: Integer;
begin
  Result := -1;
end;

end.

