unit TagTable;

interface
uses
  Classes,
  Tags;

type
(*
  1. TagTable destroys tags which have been added into it
  2. Tagnames must be unique
  3. Tags can be replaced in list
*)

  TTagTable = class(TObject)
  private
    FTags: TStringList;
  public
    Constructor Create;
    destructor Destroy; override;

    function add(tag: TTag): TTag;

    procedure clear;
    procedure remove(index: integer);
    procedure removeDeleted;

    function getSize: integer;
    function getIndex(name: string): Integer;
    function get(index: integer): TTag; overload;
    function get(name: string): TTag; overload;

  end;

implementation


{ TTagTable }

constructor TTagTable.Create;
begin
  FTags := TStringList.Create;
  FTags.Sorted := True;
end;

destructor TTagTable.Destroy;
begin
  clear;
  FTags.Free;
end;

function TTagTable.add(tag: TTag): TTag;
var
  index: Integer;
begin
  Result := tag;
  if tag = nil then
    Exit;

  index := getIndex(tag.getName);
  if index < 0 then begin
    FTags.AddObject(tag.getName, tag);
  end else begin
    TTag(FTags.Objects[index]).Free;
    FTags.Objects[index] := tag;
  end;
end;

function TTagTable.getIndex(name: string): Integer;
var
  index: Integer;
begin
  if FTags.Find(name, index) then
    Result := index
  else
    Result := -1;
end;

function TTagTable.get(name: string): TTag;
var
  index: Integer;
begin
  if FTags.Find(name, index) then
    Result := TTag(FTags.Objects[index])
  else
    Result := nil;
end;

function TTagTable.get(index: integer): TTag;
begin
  Result := TTag(FTags.Objects[index]);
end;

procedure TTagTable.remove(index: integer);
begin
  if index < getSize then begin
    get(index).Free;
    FTags.Delete(index);
  end;
end;

procedure TTagTable.removeDeleted;
var
  i: integer;
begin
  i:=0;
  while i < getSize do begin
    if get(i).getStatus = tsDELETED then begin
      get(i).Free;
      FTags.Delete(i);
    end else
      Inc(i);
  end;
end;

function TTagTable.getSize: integer;
begin
  Result := FTags.Count;
end;


procedure TTagTable.clear;
var
  i: Integer;
begin
  for i:=0 to FTags.Count-1 do
    TTag(FTags.Objects[i]).Free;
  FTags.Clear;
end;

end.
