{$MODE FPC}
{$MODESWITCH ADVANCEDRECORDS}
{$MODESWITCH OUT}
{$MODESWITCH RESULT}
unit dhashmap_buckets;

interface

//
//  Notations:
//
//      K:    pointer to data of a key
//      KLen: length in bytes of a key
//      H:    a hash of specified key, computed externaly
//      V:    pointer to data of a value
//      VLen: length in bytes of a value
//

type
THashMap = record
public type
  TCursor = record
  public
    function H: SizeUInt; inline;
    function K: Pointer; inline;
    function KLen: SizeUInt; inline;
    function V: Pointer; inline;
    function VLen: SizeUInt; inline;
  private
    FPtr: Pointer;
  end;
  TFindCursor = record(TCursor)
  end;
  TGlobalCursor = record(TCursor)
  end;
  TStats = record
    Buckets: SizeUInt;
    Pairs: SizeUInt;
    Collisions: SizeUInt;
    Allocated: SizeUInt;
    Noncontiguous: SizeUInt;
  end;
  TGetMemFunc = function(Userdata: Pointer; Size: SizeUInt): Pointer;
  TReallocMemFunc = function(Userdata: Pointer; P: Pointer; NewSize: SizeUInt): Pointer;
  TFreeMemFunc = procedure(Userdata: Pointer; P: Pointer);
public
  procedure Init;
  procedure Done;
  procedure SetAllocator(GetMem: TGetMemFunc;
                         ReallocMem: TReallocMemFunc;
                         FreeMem: TFreeMemFunc;
                         Userdata: Pointer);
  function IsEmpty: Boolean;
  procedure Clear;
  function Add(H: PtrUInt;
               K: Pointer;
               KLen: SizeUInt;
               VLen: SizeUInt;
               out V: Pointer): Boolean;
  function Find(H: PtrUInt;
                K: Pointer;
                KLen: SizeUInt;
                out VLen: SizeUInt;
                out V: Pointer): Boolean; overload;
  function Delete(H: PtrUInt;
                  K: Pointer;
                  KLen: SizeUInt): Boolean;
  function DeleteMultiple(H: PtrUInt;
                          K: Pointer;
                          KLen: SizeUInt): LongInt;

  function Find(H: PtrUInt;
                K: Pointer;
                KLen: SizeUInt;
                out It: TFindCursor): Boolean; overload;
  function Next(var It: TFindCursor): Boolean; overload;
  function DeleteAndNext(var It: TFindCursor): Boolean; overload;

  function Find(out It: TGlobalCursor): Boolean; overload;
  function Next(var It: TGlobalCursor): Boolean; overload;
  function DeleteAndNext(var It: TGlobalCursor): Boolean; overload;

  procedure GetStats(out Stats: TStats);
private
  FPtr: Pointer;
end;

implementation

function THashMap.TCursor.H: SizeUInt;
begin
  Result := SizeUInt(FPtr^);
end;

function THashMap.TCursor.K: Pointer;
begin
  Result := Pointer(FPtr^);
end;

function THashMap.TCursor.KLen: SizeUInt;
begin
  Result := SizeUInt(FPtr^);
end;

function THashMap.TCursor.V: Pointer;
begin
  Result := Pointer(FPtr^);
end;

function THashMap.TCursor.VLen: SizeUInt;
begin
  Result := SizeUInt(FPtr^);
end;

end.
