{********************************************************

 SlavaNap source code.

 Copyright 2001,2002 by SlavaNap development team
 Released under GNU General Public License

 Latest version is available at
 http://www.slavanap.org

**********************************************************

 Unit: class_cmdexlist

 TNapCmdEx and TNapCmdExList declarations

*********************************************************}
unit class_cmdexlist;

interface

uses
 Windows, Classes2, SysUtils;

type
  TNapCmdEx      = record
       id        : Integer;
       cmd       : String;
       data      : String;
  end;
  PNapCmdEx       = ^TNapCmdEx;
  TNapCmdExList     = class(TMyList)
    function  Add(Value: TNapCmdEx):Integer;
    procedure Insert(Index:Integer; Value: TNapCmdEx);
    procedure Clear; override;
    procedure Delete(Index: Integer);
    procedure AddCmd(id: Integer; cmd:String; data: String);
    function  CmdEx(index :Integer): TNapCmdEx;
    function  FindByCmd(cmd: String): Integer;
    constructor Create;
    destructor Destroy; override;
  end;

function  CreateCmdExList: TNapCmdExList;
procedure FreeCmdExList(list: TNapCmdExList);
{$IFNDEF DISABLE_MEMORY_MANAGER}
procedure ExpireCmdExLists;
{$ENDIF}

var
 count_napcmdexlist,
 count_napcmdexlist_max: Integer;
 count_napcmdexlist_items,
 count_napcmdexlist_items_max: Integer;

implementation

uses vars, thread, stypes, memory_manager;

{$IFNDEF DISABLE_MEMORY_MANAGER}
var
 lists, items: TMyList; 
{$ENDIF}

function  CreateCmdExList: TNapCmdExList;
begin
{$IFNDEF DISABLE_MEMORY_MANAGER}
 if lists.count>0 then
 begin
  Result:=lists.Items[lists.count-1];
  lists.Delete(lists.count-1);
 end
 else
{$ENDIF}
  Result:=TNapCmdExList.Create;
end;

procedure FreeCmdExList(list: TNapCmdExList);
begin
 list.Clear;
{$IFDEF DISABLE_MEMORY_MANAGER}
 list.Free;
{$ELSE}
 lists.Add(list);
{$ENDIF}
end;

function CreateItem: PNapCmdEx;
var
 data: PNapCmdEx;
begin
{$IFNDEF DISABLE_MEMORY_MANAGER}
 if items.count>0 then
 begin
  data:=items.Items[items.count-1];
  items.Delete(items.count-1);
 end
 else
 begin
{$ENDIF}
  data:=AllocMem(sizeof(TNapCmdEx));
  Pointer(data^.cmd):=nil;
  Pointer(data^.data):=nil;
  inc(count_napcmdexlist_items);
  if count_napcmdexlist_items>count_napcmdexlist_items_max then count_napcmdexlist_items_max:=count_napcmdexlist_items;
{$IFNDEF DISABLE_MEMORY_MANAGER}
 end;  
{$ENDIF}
 Result:=data;
end;

procedure FreeItem(item: PNapCmdEx);
begin
 if Pointer(item^.data)<>nil then SetLength(item^.data,0);
 if Pointer(item^.cmd)<>nil then SetLength(item^.cmd,0);
 Finalize(item^);
 FreeMem(item,sizeof(TNapCmdEx));
 dec(count_napcmdexlist_items);
end;

procedure DeleteItem(item: PNapCmdEx);
begin
{$IFDEF DISABLE_MEMORY_MANAGER}
 FreeItem(item);
{$ELSE}
 if Pointer(item^.data)<>nil then SetLength(item^.data,0);
 if Pointer(item^.cmd)<>nil then SetLength(item^.cmd,0);
 items.Add(item);
{$ENDIF}
end;

{$IFNDEF DISABLE_MEMORY_MANAGER}
procedure ExpireCmdExLists;
var
 list: TNapCmdExList;
 item: PNapCmdEx;
begin
 if lists.count>1000 then
 while (lists.count * 3) > count_napcmdexlist do
 try
   list:=lists.items[lists.count-1];
   lists.Delete(lists.count-1);
   list.Free;
  except
 end;
 if items.count>10000 then
 while (items.count * 3) > count_napcmdexlist_items do
 try
   item:=items.Items[items.count-1];
   items.Delete(items.count-1);
   FreeItem(item);
  except
 end;
end;
{$ENDIF}

{* * * * *  TNapCmdExList  * * * * *}

function TNapCmdExList.Add(Value: TNapCmdEx):Integer;
var
 item:PNapCmdEx;
begin
 item:=CreateItem;
 with item^ do
 begin
  cmd:=Value.cmd;
  data:=Value.data;
  id:=Value.id;
 end;
 Result:=inherited Add(item);
end;

procedure TNapCmdExList.Insert(Index:Integer; Value: TNapCmdEx);
var
 item:PNapCmdEx;
begin
 item:=CreateItem;
 with item^ do
 begin
  cmd:=Value.cmd;
  data:=Value.data;
  id:=Value.id;
 end;
 inherited Insert(Index,item);
end;

procedure TNapCmdExList.Clear;
begin
 while count>0 do
  Delete(count-1);
 inherited Clear;
end;

procedure TNapCmdExList.Delete(Index: Integer);
begin
 if (Index<0) or (Index>=Count) then exit;
 if Items[Index]<>nil then
  DeleteItem(Items[Index]);
 Inherited Delete(index);
end;

procedure TNapCmdExList.AddCmd(id: Integer; cmd:String; data: String);
var
 item: TNapCmdEx;
begin
 item.id:=id;
 item.cmd:=cmd;
 item.data:=data;
 Add(item);
end;

function TNapCmdExList.CmdEx(index :Integer): TNapCmdEx;
var
 data:TNapCmdEx;
begin
 if (index>=0) and (index<count) then
 begin
  data:=TNapCmdEx(Items[index]^);
  Result:=data;
  exit;
 end;
 data.id:=-1;
 data.cmd:='';
 data.data:='';
 Result:=data;
end;

function  TNapCmdExList.FindByCmd(cmd: String): Integer;
var
 i: Integer;
 p: PNapCmdEx;
begin
 for i:=0 to count-1 do
 begin
   p:=Items[i];
   if p^.cmd=cmd then
   begin
     Result:=i;
     exit;
   end;
 end;
 Result:=-1;
end;

constructor TNapCmdExList.Create;
begin
 inc(count_napcmdexlist);
 if count_napcmdexlist>count_napcmdexlist_max then count_napcmdexlist_max:=count_napcmdexlist;
 inherited Create;
end;

destructor TNapCmdExList.Destroy;
begin
 Clear;
 dec(count_napcmdexlist);
 inherited Destroy;
end;

{$IFNDEF DISABLE_MEMORY_MANAGER}
procedure ClearCmdExLists;
var
 i: Integer;
 p: PNapCmdEx;
begin
 for i:=0 to lists.count-1 do
  TNapCmdExList(lists.items[i]).Free;
 lists.Clear;
 for i:=0 to items.count-1 do
 begin
   p:=items.Items[i];
   FreeItem(p);
 end;
 items.Clear;
end;
{$ENDIF}

initialization
begin
 count_napcmdexlist:=0;
 count_napcmdexlist_max:=0;
 count_napcmdexlist_items:=0;
 count_napcmdexlist_items_max:=0;
{$IFNDEF DISABLE_MEMORY_MANAGER}
 lists:=TMyList.Create;
 items:=TMyList.Create;
{$ENDIF}
end;

{$IFNDEF DISABLE_MEMORY_MANAGER}
finalization
begin
 ClearCmdExLists;
 lists.Free;
 items.Free;
end;
{$ENDIF}
end.
