1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360 |
- {
- This file is part of the Free Pascal run time library.
- Copyright (c) 2006 by Micha Nelissen
- member of the Free Pascal development team
- It contains the Free Pascal generics library
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- {$mode objfpc}
- { be aware, this unit is a prototype and subject to be changed heavily }
- unit fgl;
- interface
- uses
- types, sysutils;
- const
- MaxListSize = Maxint div 16;
- type
- EListError = class(Exception);
- TFPSList = class;
- TFPSListCompareFunc = function(Key1, Key2: Pointer): Integer of object;
- TFPSList = class(TObject)
- protected
- FList: PByte;
- FCount: Integer;
- FCapacity: Integer; { list is one longer than capacity, for temp }
- FItemSize: Integer;
- procedure CopyItem(Src, Dest: Pointer); virtual;
- procedure Deref(Item: Pointer); virtual; overload;
- procedure Deref(FromIndex, ToIndex: Integer); overload;
- function Get(Index: Integer): Pointer;
- procedure InternalExchange(Index1, Index2: Integer);
- function InternalGet(Index: Integer): Pointer; {$ifdef CLASSESINLINE} inline; {$endif}
- procedure InternalPut(Index: Integer; NewItem: Pointer);
- procedure Put(Index: Integer; Item: Pointer);
- procedure QuickSort(L, R: Integer; Compare: TFPSListCompareFunc);
- procedure SetCapacity(NewCapacity: Integer);
- procedure SetCount(NewCount: Integer);
- procedure RaiseIndexError(Index : Integer);
- property InternalItems[Index: Integer]: Pointer read InternalGet write InternalPut;
- public
- constructor Create(AItemSize: Integer = sizeof(Pointer));
- destructor Destroy; override;
- function Add(Item: Pointer): Integer;
- procedure Clear;
- procedure Delete(Index: Integer);
- class procedure Error(const Msg: string; Data: PtrInt);
- procedure Exchange(Index1, Index2: Integer);
- function Expand: TFPSList;
- function Extract(Item: Pointer): Pointer;
- function First: Pointer;
- function IndexOf(Item: Pointer): Integer;
- procedure Insert(Index: Integer; Item: Pointer);
- function Insert(Index: Integer): Pointer;
- function Last: Pointer;
- procedure Move(CurIndex, NewIndex: Integer);
- procedure Assign(Obj: TFPSList);
- function Remove(Item: Pointer): Integer;
- procedure Pack;
- procedure Sort(Compare: TFPSListCompareFunc);
- property Capacity: Integer read FCapacity write SetCapacity;
- property Count: Integer read FCount write SetCount;
- property Items[Index: Integer]: Pointer read Get write Put; default;
- property ItemSize: Integer read FItemSize;
- property List: PByte read FList;
- end;
- {$ifndef VER2_0}
- const
- MaxGListSize = MaxInt div 1024;
- type
- generic TFPGListEnumerator<T> = class(TObject)
- protected
- FList: TFPSList;
- FPosition: Integer;
- function GetCurrent: T;
- public
- constructor Create(AList: TFPSList);
- function MoveNext: Boolean;
- property Current: T read GetCurrent;
- end;
- generic TFPGList<T> = class(TFPSList)
- public
- type
- TCompareFunc = function(const Item1, Item2: T): Integer;
- TTypeList = array[0..MaxGListSize] of T;
- PTypeList = ^TTypeList;
- PT = ^T;
- TFPGListEnumeratorSpec = specialize TFPGListEnumerator<T>;
- protected
- var
- FOnCompare: TCompareFunc;
- procedure CopyItem(Src, Dest: Pointer); override;
- procedure Deref(Item: Pointer); override;
- function Get(Index: Integer): T; {$ifdef CLASSESINLINE} inline; {$endif}
- function GetList: PTypeList; {$ifdef CLASSESINLINE} inline; {$endif}
- function ItemPtrCompare(Item1, Item2: Pointer): Integer;
- procedure Put(Index: Integer; const Item: T); {$ifdef CLASSESINLINE} inline; {$endif}
- public
- constructor Create;
- function Add(const Item: T): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
- function Extract(const Item: T): T; {$ifdef CLASSESINLINE} inline; {$endif}
- function First: T; {$ifdef CLASSESINLINE} inline; {$endif}
- function GetEnumerator: TFPGListEnumeratorSpec; {$ifdef CLASSESINLINE} inline; {$endif}
- function IndexOf(const Item: T): Integer;
- procedure Insert(Index: Integer; const Item: T); {$ifdef CLASSESINLINE} inline; {$endif}
- function Last: T; {$ifdef CLASSESINLINE} inline; {$endif}
- {$info FIXME: bug #10479: implement TFPGList<T>.Assign(TFPGList) to work somehow}
- {procedure Assign(Source: TFPGList);}
- function Remove(const Item: T): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
- procedure Sort(Compare: TCompareFunc);
- property Items[Index: Integer]: T read Get write Put; default;
- property List: PTypeList read GetList;
- end;
- generic TFPGObjectList<T> = class(TFPSList)
- public
- type
- TCompareFunc = function(const Item1, Item2: T): Integer;
- TTypeList = array[0..MaxGListSize] of T;
- PTypeList = ^TTypeList;
- PT = ^T;
- protected
- var
- FOnCompare: TCompareFunc;
- FFreeObjects: Boolean;
- procedure CopyItem(Src, Dest: Pointer); override;
- procedure Deref(Item: Pointer); override;
- function Get(Index: Integer): T; {$ifdef CLASSESINLINE} inline; {$endif}
- function GetList: PTypeList; {$ifdef CLASSESINLINE} inline; {$endif}
- function ItemPtrCompare(Item1, Item2: Pointer): Integer;
- procedure Put(Index: Integer; const Item: T); {$ifdef CLASSESINLINE} inline; {$endif}
- public
- constructor Create(FreeObjects: Boolean = True);
- function Add(const Item: T): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
- function Extract(const Item: T): T; {$ifdef CLASSESINLINE} inline; {$endif}
- function First: T; {$ifdef CLASSESINLINE} inline; {$endif}
- function IndexOf(const Item: T): Integer;
- procedure Insert(Index: Integer; const Item: T); {$ifdef CLASSESINLINE} inline; {$endif}
- function Last: T; {$ifdef CLASSESINLINE} inline; {$endif}
- {$info FIXME: bug #10479: implement TFPGObjectList<T>.Assign(TFPGList) to work somehow}
- {procedure Assign(Source: TFPGList);}
- function Remove(const Item: T): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
- procedure Sort(Compare: TCompareFunc);
- property Items[Index: Integer]: T read Get write Put; default;
- property List: PTypeList read GetList;
- property FreeObjects: Boolean read FFreeObjects write FFreeObjects;
- end;
- generic TFPGInterfacedObjectList<T> = class(TFPSList)
- public
- type
- TCompareFunc = function(const Item1, Item2: T): Integer;
- TTypeList = array[0..MaxGListSize] of T;
- PTypeList = ^TTypeList;
- PT = ^T;
- protected
- var
- FOnCompare: TCompareFunc;
- procedure CopyItem(Src, Dest: Pointer); override;
- procedure Deref(Item: Pointer); override;
- function Get(Index: Integer): T; {$ifdef CLASSESINLINE} inline; {$endif}
- function GetList: PTypeList; {$ifdef CLASSESINLINE} inline; {$endif}
- function ItemPtrCompare(Item1, Item2: Pointer): Integer;
- procedure Put(Index: Integer; const Item: T); {$ifdef CLASSESINLINE} inline; {$endif}
- public
- constructor Create;
- function Add(const Item: T): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
- function Extract(const Item: T): T; {$ifdef CLASSESINLINE} inline; {$endif}
- function First: T; {$ifdef CLASSESINLINE} inline; {$endif}
- function IndexOf(const Item: T): Integer;
- procedure Insert(Index: Integer; const Item: T); {$ifdef CLASSESINLINE} inline; {$endif}
- function Last: T; {$ifdef CLASSESINLINE} inline; {$endif}
- {$info FIXME: bug #10479: implement TFPGInterfacedObjectList<T>.Assign(TFPGList) to work somehow}
- {procedure Assign(Source: TFPGList);}
- function Remove(const Item: T): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
- procedure Sort(Compare: TCompareFunc);
- property Items[Index: Integer]: T read Get write Put; default;
- property List: PTypeList read GetList;
- end;
- {$endif}
- TFPSMap = class(TFPSList)
- private
- FKeySize: Integer;
- FDataSize: Integer;
- FDuplicates: TDuplicates;
- FSorted: Boolean;
- FOnKeyPtrCompare: TFPSListCompareFunc;
- FOnDataPtrCompare: TFPSListCompareFunc;
- procedure SetSorted(Value: Boolean);
- protected
- function BinaryCompareKey(Key1, Key2: Pointer): Integer;
- function BinaryCompareData(Data1, Data2: Pointer): Integer;
- procedure SetOnKeyPtrCompare(Proc: TFPSListCompareFunc);
- procedure SetOnDataPtrCompare(Proc: TFPSListCompareFunc);
- procedure InitOnPtrCompare; virtual;
- procedure CopyKey(Src, Dest: Pointer); virtual;
- procedure CopyData(Src, Dest: Pointer); virtual;
- function GetKey(Index: Integer): Pointer;
- function GetKeyData(AKey: Pointer): Pointer;
- function GetData(Index: Integer): Pointer;
- function LinearIndexOf(AKey: Pointer): Integer;
- procedure PutKey(Index: Integer; AKey: Pointer);
- procedure PutKeyData(AKey: Pointer; NewData: Pointer);
- procedure PutData(Index: Integer; AData: Pointer);
- public
- constructor Create(AKeySize: Integer = sizeof(Pointer);
- ADataSize: integer = sizeof(Pointer));
- function Add(AKey, AData: Pointer): Integer;
- function Add(AKey: Pointer): Integer;
- function Find(AKey: Pointer; out Index: Integer): Boolean;
- function IndexOf(AKey: Pointer): Integer;
- function IndexOfData(AData: Pointer): Integer;
- function Insert(Index: Integer): Pointer;
- procedure Insert(Index: Integer; out AKey, AData: Pointer);
- procedure InsertKey(Index: Integer; AKey: Pointer);
- procedure InsertKeyData(Index: Integer; AKey, AData: Pointer);
- function Remove(AKey: Pointer): Integer;
- procedure Sort;
- property Duplicates: TDuplicates read FDuplicates write FDuplicates;
- property KeySize: Integer read FKeySize;
- property DataSize: Integer read FDataSize;
- property Keys[Index: Integer]: Pointer read GetKey write PutKey;
- property Data[Index: Integer]: Pointer read GetData write PutData;
- property KeyData[Key: Pointer]: Pointer read GetKeyData write PutKeyData; default;
- property Sorted: Boolean read FSorted write SetSorted;
- property OnPtrCompare: TFPSListCompareFunc read FOnKeyPtrCompare write SetOnKeyPtrCompare; //deprecated;
- property OnKeyPtrCompare: TFPSListCompareFunc read FOnKeyPtrCompare write SetOnKeyPtrCompare;
- property OnDataPtrCompare: TFPSListCompareFunc read FOnDataPtrCompare write SetOnDataPtrCompare;
- end;
- {$ifndef VER2_0}
- generic TFPGMap<TKey, TData> = class(TFPSMap)
- public
- type
- TKeyCompareFunc = function(const Key1, Key2: TKey): Integer;
- TDataCompareFunc = function(const Data1, Data2: TData): Integer;
- PKey = ^TKey;
- PData = ^TData;
- protected
- var
- FOnKeyCompare: TKeyCompareFunc;
- FOnDataCompare: TDataCompareFunc;
- procedure CopyItem(Src, Dest: Pointer); override;
- procedure CopyKey(Src, Dest: Pointer); override;
- procedure CopyData(Src, Dest: Pointer); override;
- procedure Deref(Item: Pointer); override;
- procedure InitOnPtrCompare; override;
- function GetKey(Index: Integer): TKey; {$ifdef CLASSESINLINE} inline; {$endif}
- function GetKeyData(const AKey: TKey): TData; {$ifdef CLASSESINLINE} inline; {$endif}
- function GetData(Index: Integer): TData; {$ifdef CLASSESINLINE} inline; {$endif}
- function KeyCompare(Key1, Key2: Pointer): Integer;
- function KeyCustomCompare(Key1, Key2: Pointer): Integer;
- //function DataCompare(Data1, Data2: Pointer): Integer;
- function DataCustomCompare(Data1, Data2: Pointer): Integer;
- procedure PutKey(Index: Integer; const NewKey: TKey); {$ifdef CLASSESINLINE} inline; {$endif}
- procedure PutKeyData(const AKey: TKey; const NewData: TData); {$ifdef CLASSESINLINE} inline; {$endif}
- procedure PutData(Index: Integer; const NewData: TData); {$ifdef CLASSESINLINE} inline; {$endif}
- procedure SetOnKeyCompare(NewCompare: TKeyCompareFunc);
- procedure SetOnDataCompare(NewCompare: TDataCompareFunc);
- public
- constructor Create;
- function Add(const AKey: TKey; const AData: TData): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
- function Add(const AKey: TKey): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
- function Find(const AKey: TKey; out Index: Integer): Boolean; {$ifdef CLASSESINLINE} inline; {$endif}
- function IndexOf(const AKey: TKey): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
- function IndexOfData(const AData: TData): Integer;
- procedure InsertKey(Index: Integer; const AKey: TKey);
- procedure InsertKeyData(Index: Integer; const AKey: TKey; const AData: TData);
- function Remove(const AKey: TKey): Integer;
- property Keys[Index: Integer]: TKey read GetKey write PutKey;
- property Data[Index: Integer]: TData read GetData write PutData;
- property KeyData[const AKey: TKey]: TData read GetKeyData write PutKeyData; default;
- property OnCompare: TKeyCompareFunc read FOnKeyCompare write SetOnKeyCompare; //deprecated;
- property OnKeyCompare: TKeyCompareFunc read FOnKeyCompare write SetOnKeyCompare;
- property OnDataCompare: TDataCompareFunc read FOnDataCompare write SetOnDataCompare;
- end;
- {$endif}
- implementation
- uses
- rtlconsts;
- {****************************************************************************
- TFPSList
- ****************************************************************************}
- constructor TFPSList.Create(AItemSize: integer);
- begin
- inherited Create;
- FItemSize := AItemSize;
- end;
- destructor TFPSList.Destroy;
- begin
- Clear;
- // Clear() does not clear the whole list; there is always a single temp entry
- // at the end which is never freed. Take care of that one here.
- FreeMem(FList);
- inherited Destroy;
- end;
- procedure TFPSList.CopyItem(Src, Dest: Pointer);
- begin
- System.Move(Src^, Dest^, FItemSize);
- end;
- procedure TFPSList.RaiseIndexError(Index : Integer);
- begin
- Error(SListIndexError, Index);
- end;
- function TFPSList.InternalGet(Index: Integer): Pointer;
- begin
- Result:=FList+Index*ItemSize;
- end;
- procedure TFPSList.InternalPut(Index: Integer; NewItem: Pointer);
- var
- ListItem: Pointer;
- begin
- ListItem := InternalItems[Index];
- CopyItem(NewItem, ListItem);
- end;
- function TFPSList.Get(Index: Integer): Pointer;
- begin
- if (Index < 0) or (Index >= FCount) then
- RaiseIndexError(Index);
- Result := InternalItems[Index];
- end;
- procedure TFPSList.Put(Index: Integer; Item: Pointer);
- begin
- if (Index < 0) or (Index >= FCount) then
- RaiseIndexError(Index);
- InternalItems[Index] := Item;
- end;
- procedure TFPSList.SetCapacity(NewCapacity: Integer);
- begin
- if (NewCapacity < FCount) or (NewCapacity > MaxListSize) then
- Error(SListCapacityError, NewCapacity);
- if NewCapacity = FCapacity then
- exit;
- ReallocMem(FList, (NewCapacity+1) * FItemSize);
- FillChar(InternalItems[FCapacity]^, (NewCapacity+1-FCapacity) * FItemSize, #0);
- FCapacity := NewCapacity;
- end;
- procedure TFPSList.Deref(Item: Pointer);
- begin
- end;
- procedure TFPSList.Deref(FromIndex, ToIndex: Integer);
- var
- ListItem, ListItemLast: Pointer;
- begin
- ListItem := InternalItems[FromIndex];
- ListItemLast := InternalItems[ToIndex];
- repeat
- Deref(ListItem);
- if ListItem = ListItemLast then
- break;
- ListItem := PByte(ListItem) + ItemSize;
- until false;
- end;
- procedure TFPSList.SetCount(NewCount: Integer);
- begin
- if (NewCount < 0) or (NewCount > MaxListSize) then
- Error(SListCountError, NewCount);
- if NewCount > FCapacity then
- SetCapacity(NewCount);
- if NewCount > FCount then
- FillByte(InternalItems[FCount]^, (NewCount-FCount) * FItemSize, 0)
- else if NewCount < FCount then
- Deref(NewCount, FCount-1);
- FCount := NewCount;
- end;
- function TFPSList.Add(Item: Pointer): Integer;
- begin
- if FCount = FCapacity then
- Self.Expand;
- CopyItem(Item, InternalItems[FCount]);
- Result := FCount;
- Inc(FCount);
- end;
- procedure TFPSList.Clear;
- begin
- if Assigned(FList) then
- begin
- SetCount(0);
- SetCapacity(0);
- end;
- end;
- procedure TFPSList.Delete(Index: Integer);
- var
- ListItem: Pointer;
- begin
- if (Index < 0) or (Index >= FCount) then
- Error(SListIndexError, Index);
- Dec(FCount);
- ListItem := InternalItems[Index];
- Deref(ListItem);
- System.Move(InternalItems[Index+1]^, ListItem^, (FCount - Index) * FItemSize);
- // Shrink the list if appropriate
- if (FCapacity > 256) and (FCount < FCapacity shr 2) then
- begin
- FCapacity := FCapacity shr 1;
- ReallocMem(FList, (FCapacity+1) * FItemSize);
- end;
- end;
- function TFPSList.Extract(Item: Pointer): Pointer;
- var
- i : Integer;
- begin
- Result := nil;
- i := IndexOf(Item);
- if i >= 0 then
- begin
- Result := InternalItems[i];
- System.Move(Result^, InternalItems[FCapacity]^, FItemSize);
- Delete(i);
- end;
- end;
- class procedure TFPSList.Error(const Msg: string; Data: PtrInt);
- begin
- raise EListError.CreateFmt(Msg,[Data]) at get_caller_addr(get_frame);
- end;
- procedure TFPSList.Exchange(Index1, Index2: Integer);
- begin
- if ((Index1 >= FCount) or (Index1 < 0)) then
- Error(SListIndexError, Index1);
- if ((Index2 >= FCount) or (Index2 < 0)) then
- Error(SListIndexError, Index2);
- InternalExchange(Index1, Index2);
- end;
- procedure TFPSList.InternalExchange(Index1, Index2: Integer);
- begin
- System.Move(InternalItems[Index1]^, InternalItems[FCapacity]^, FItemSize);
- System.Move(InternalItems[Index2]^, InternalItems[Index1]^, FItemSize);
- System.Move(InternalItems[FCapacity]^, InternalItems[Index2]^, FItemSize);
- end;
- function TFPSList.Expand: TFPSList;
- var
- IncSize : Longint;
- begin
- if FCount < FCapacity then exit;
- IncSize := 4;
- if FCapacity > 3 then IncSize := IncSize + 4;
- if FCapacity > 8 then IncSize := IncSize + 8;
- if FCapacity > 127 then Inc(IncSize, FCapacity shr 2);
- SetCapacity(FCapacity + IncSize);
- Result := Self;
- end;
- function TFPSList.First: Pointer;
- begin
- If FCount = 0 then
- Result := Nil
- else
- Result := InternalItems[0];
- end;
- function TFPSList.IndexOf(Item: Pointer): Integer;
- var
- ListItem: Pointer;
- begin
- Result := 0;
- ListItem := First;
- while (Result < FCount) and (CompareByte(ListItem^, Item^, FItemSize) <> 0) do
- begin
- Inc(Result);
- ListItem := PByte(ListItem)+FItemSize;
- end;
- if Result = FCount then Result := -1;
- end;
- function TFPSList.Insert(Index: Integer): Pointer;
- begin
- if (Index < 0) or (Index > FCount) then
- Error(SListIndexError, Index);
- if FCount = FCapacity then Self.Expand;
- Result := InternalItems[Index];
- if Index<FCount then
- begin
- System.Move(Result^, (Result+FItemSize)^, (FCount - Index) * FItemSize);
- { clear for compiler assisted types }
- System.FillByte(Result^, FItemSize, 0);
- end;
- Inc(FCount);
- end;
- procedure TFPSList.Insert(Index: Integer; Item: Pointer);
- begin
- CopyItem(Item, Insert(Index));
- end;
- function TFPSList.Last: Pointer;
- begin
- if FCount = 0 then
- Result := nil
- else
- Result := InternalItems[FCount - 1];
- end;
- procedure TFPSList.Move(CurIndex, NewIndex: Integer);
- var
- CurItem, NewItem, TmpItem, Src, Dest: Pointer;
- MoveCount: Integer;
- begin
- if (CurIndex < 0) or (CurIndex >= Count) then
- Error(SListIndexError, CurIndex);
- if (NewIndex < 0) or (NewIndex >= Count) then
- Error(SListIndexError, NewIndex);
- if CurIndex = NewIndex then
- exit;
- CurItem := InternalItems[CurIndex];
- NewItem := InternalItems[NewIndex];
- TmpItem := InternalItems[FCapacity];
- System.Move(CurItem^, TmpItem^, FItemSize);
- if NewIndex > CurIndex then
- begin
- Src := InternalItems[CurIndex+1];
- Dest := CurItem;
- MoveCount := NewIndex - CurIndex;
- end else begin
- Src := NewItem;
- Dest := InternalItems[NewIndex+1];
- MoveCount := CurIndex - NewIndex;
- end;
- System.Move(Src^, Dest^, MoveCount * FItemSize);
- System.Move(TmpItem^, NewItem^, FItemSize);
- end;
- function TFPSList.Remove(Item: Pointer): Integer;
- begin
- Result := IndexOf(Item);
- if Result <> -1 then
- Delete(Result);
- end;
- procedure TFPSList.Pack;
- var
- NewCount,
- i : integer;
- pdest,
- psrc : Pointer;
- begin
- NewCount:=0;
- psrc:=First;
- pdest:=psrc;
- For I:=0 To FCount-1 Do
- begin
- if assigned(pointer(psrc^)) then
- begin
- System.Move(psrc^, pdest^, FItemSize);
- inc(pdest);
- inc(NewCount);
- end;
- inc(psrc);
- end;
- FCount:=NewCount;
- end;
- // Needed by Sort method.
- procedure TFPSList.QuickSort(L, R: Integer; Compare: TFPSListCompareFunc);
- var
- I, J, P: Integer;
- PivotItem: Pointer;
- begin
- repeat
- I := L;
- J := R;
- P := (L + R) div 2;
- repeat
- PivotItem := InternalItems[P];
- while Compare(PivotItem, InternalItems[I]) > 0 do
- Inc(I);
- while Compare(PivotItem, InternalItems[J]) < 0 do
- Dec(J);
- if I <= J then
- begin
- InternalExchange(I, J);
- if P = I then
- P := J
- else if P = J then
- P := I;
- Inc(I);
- Dec(J);
- end;
- until I > J;
- if L < J then
- QuickSort(L, J, Compare);
- L := I;
- until I >= R;
- end;
- procedure TFPSList.Sort(Compare: TFPSListCompareFunc);
- begin
- if not Assigned(FList) or (FCount < 2) then exit;
- QuickSort(0, FCount-1, Compare);
- end;
- procedure TFPSList.Assign(Obj: TFPSList);
- var
- i: Integer;
- begin
- if Obj.ItemSize <> FItemSize then
- Error(SListItemSizeError, 0);
- Clear;
- for I := 0 to Obj.Count - 1 do
- Add(Obj[i]);
- end;
- {$ifndef VER2_0}
- {****************************************************************************}
- {* TFPGListEnumerator *}
- {****************************************************************************}
- function TFPGListEnumerator.GetCurrent: T;
- begin
- Result := T(FList.Items[FPosition]^);
- end;
- constructor TFPGListEnumerator.Create(AList: TFPSList);
- begin
- inherited Create;
- FList := AList;
- FPosition := -1;
- end;
- function TFPGListEnumerator.MoveNext: Boolean;
- begin
- inc(FPosition);
- Result := FPosition < FList.Count;
- end;
- {****************************************************************************}
- {* TFPGList *}
- {****************************************************************************}
- constructor TFPGList.Create;
- begin
- inherited Create(sizeof(T));
- end;
- procedure TFPGList.CopyItem(Src, Dest: Pointer);
- begin
- T(Dest^) := T(Src^);
- end;
- procedure TFPGList.Deref(Item: Pointer);
- begin
- Finalize(T(Item^));
- end;
- function TFPGList.Get(Index: Integer): T;
- begin
- Result := T(inherited Get(Index)^);
- end;
- function TFPGList.GetList: PTypeList;
- begin
- Result := PTypeList(FList);
- end;
- function TFPGList.ItemPtrCompare(Item1, Item2: Pointer): Integer;
- begin
- Result := FOnCompare(T(Item1^), T(Item2^));
- end;
- procedure TFPGList.Put(Index: Integer; const Item: T);
- begin
- inherited Put(Index, @Item);
- end;
- function TFPGList.Add(const Item: T): Integer;
- begin
- Result := inherited Add(@Item);
- end;
- function TFPGList.Extract(const Item: T): T;
- var
- ResPtr: Pointer;
- begin
- ResPtr := inherited Extract(@Item);
- if ResPtr <> nil then
- Result := T(ResPtr^)
- else
- FillByte(Result, sizeof(T), 0);
- end;
- function TFPGList.First: T;
- begin
- Result := T(inherited First^);
- end;
- function TFPGList.GetEnumerator: TFPGListEnumeratorSpec;
- begin
- Result := TFPGListEnumeratorSpec.Create(Self);
- end;
- function TFPGList.IndexOf(const Item: T): Integer;
- begin
- Result := 0;
- {$info TODO: fix inlining to work! InternalItems[Result]^}
- while (Result < FCount) and (PT(FList)[Result] <> Item) do
- Inc(Result);
- if Result = FCount then
- Result := -1;
- end;
- procedure TFPGList.Insert(Index: Integer; const Item: T);
- begin
- T(inherited Insert(Index)^) := Item;
- end;
- function TFPGList.Last: T;
- begin
- Result := T(inherited Last^);
- end;
- function TFPGList.Remove(const Item: T): Integer;
- begin
- Result := IndexOf(Item);
- if Result >= 0 then
- Delete(Result);
- end;
- procedure TFPGList.Sort(Compare: TCompareFunc);
- begin
- FOnCompare := Compare;
- inherited Sort(@ItemPtrCompare);
- end;
- {****************************************************************************}
- {* TFPGObjectList *}
- {****************************************************************************}
- constructor TFPGObjectList.Create(FreeObjects: Boolean);
- begin
- inherited Create;
- FFreeObjects := FreeObjects;
- end;
- procedure TFPGObjectList.CopyItem(Src, Dest: Pointer);
- begin
- T(Dest^) := T(Src^);
- {if TObject(Dest^) is TInterfacedObject then
- T(Dest^)._AddRef;}
- end;
- procedure TFPGObjectList.Deref(Item: Pointer);
- begin
- {if TObject(Item^) is TInterfacedObject then
- T(Item^)._Release
- else}
- if FFreeObjects then
- T(Item^).Free;
- end;
- function TFPGObjectList.Get(Index: Integer): T;
- begin
- Result := T(inherited Get(Index)^);
- end;
- function TFPGObjectList.GetList: PTypeList;
- begin
- Result := PTypeList(FList);
- end;
- function TFPGObjectList.ItemPtrCompare(Item1, Item2: Pointer): Integer;
- begin
- Result := FOnCompare(T(Item1^), T(Item2^));
- end;
- procedure TFPGObjectList.Put(Index: Integer; const Item: T);
- begin
- inherited Put(Index, @Item);
- end;
- function TFPGObjectList.Add(const Item: T): Integer;
- begin
- Result := inherited Add(@Item);
- end;
- function TFPGObjectList.Extract(const Item: T): T;
- var
- ResPtr: Pointer;
- begin
- ResPtr := inherited Extract(@Item);
- if ResPtr <> nil then
- Result := T(ResPtr^)
- else
- FillByte(Result, sizeof(T), 0);
- end;
- function TFPGObjectList.First: T;
- begin
- Result := T(inherited First^);
- end;
- function TFPGObjectList.IndexOf(const Item: T): Integer;
- begin
- Result := 0;
- {$info TODO: fix inlining to work! InternalItems[Result]^}
- while (Result < FCount) and (PT(FList)[Result] <> Item) do
- Inc(Result);
- if Result = FCount then
- Result := -1;
- end;
- procedure TFPGObjectList.Insert(Index: Integer; const Item: T);
- begin
- T(inherited Insert(Index)^) := Item;
- end;
- function TFPGObjectList.Last: T;
- begin
- Result := T(inherited Last^);
- end;
- function TFPGObjectList.Remove(const Item: T): Integer;
- begin
- Result := IndexOf(Item);
- if Result >= 0 then
- Delete(Result);
- end;
- procedure TFPGObjectList.Sort(Compare: TCompareFunc);
- begin
- FOnCompare := Compare;
- inherited Sort(@ItemPtrCompare);
- end;
- {****************************************************************************}
- {* TFPGInterfacedObjectList *}
- {****************************************************************************}
- constructor TFPGInterfacedObjectList.Create;
- begin
- inherited Create;
- end;
- procedure TFPGInterfacedObjectList.CopyItem(Src, Dest: Pointer);
- begin
- T(Dest^) := T(Src^);
- if Assigned(Pointer(Dest^)) then
- T(Dest^)._AddRef;
- end;
- procedure TFPGInterfacedObjectList.Deref(Item: Pointer);
- begin
- if Assigned(Pointer(Item^)) then
- T(Item^)._Release;
- end;
- function TFPGInterfacedObjectList.Get(Index: Integer): T;
- begin
- Result := T(inherited Get(Index)^);
- end;
- function TFPGInterfacedObjectList.GetList: PTypeList;
- begin
- Result := PTypeList(FList);
- end;
- function TFPGInterfacedObjectList.ItemPtrCompare(Item1, Item2: Pointer): Integer;
- begin
- Result := FOnCompare(T(Item1^), T(Item2^));
- end;
- procedure TFPGInterfacedObjectList.Put(Index: Integer; const Item: T);
- begin
- inherited Put(Index, @Item);
- end;
- function TFPGInterfacedObjectList.Add(const Item: T): Integer;
- begin
- Result := inherited Add(@Item);
- end;
- function TFPGInterfacedObjectList.Extract(const Item: T): T;
- var
- ResPtr: Pointer;
- begin
- ResPtr := inherited Extract(@Item);
- if ResPtr <> nil then
- Result := T(ResPtr^)
- else
- FillByte(Result, sizeof(T), 0);
- end;
- function TFPGInterfacedObjectList.First: T;
- begin
- Result := T(inherited First^);
- end;
- function TFPGInterfacedObjectList.IndexOf(const Item: T): Integer;
- begin
- Result := 0;
- {$info TODO: fix inlining to work! InternalItems[Result]^}
- while (Result < FCount) and (PT(FList)[Result] <> Item) do
- Inc(Result);
- if Result = FCount then
- Result := -1;
- end;
- procedure TFPGInterfacedObjectList.Insert(Index: Integer; const Item: T);
- begin
- T(inherited Insert(Index)^) := Item;
- end;
- function TFPGInterfacedObjectList.Last: T;
- begin
- Result := T(inherited Last^);
- end;
- function TFPGInterfacedObjectList.Remove(const Item: T): Integer;
- begin
- Result := IndexOf(Item);
- if Result >= 0 then
- Delete(Result);
- end;
- procedure TFPGInterfacedObjectList.Sort(Compare: TCompareFunc);
- begin
- FOnCompare := Compare;
- inherited Sort(@ItemPtrCompare);
- end;
- {$endif}
- {****************************************************************************
- TFPSMap
- ****************************************************************************}
- constructor TFPSMap.Create(AKeySize: Integer; ADataSize: integer);
- begin
- inherited Create(AKeySize+ADataSize);
- FKeySize := AKeySize;
- FDataSize := ADataSize;
- InitOnPtrCompare;
- end;
- procedure TFPSMap.CopyKey(Src, Dest: Pointer);
- begin
- System.Move(Src^, Dest^, FKeySize);
- end;
- procedure TFPSMap.CopyData(Src, Dest: Pointer);
- begin
- System.Move(Src^, Dest^, FDataSize);
- end;
- function TFPSMap.GetKey(Index: Integer): Pointer;
- begin
- Result := Items[Index];
- end;
- function TFPSMap.GetData(Index: Integer): Pointer;
- begin
- Result := PByte(Items[Index])+FKeySize;
- end;
- function TFPSMap.GetKeyData(AKey: Pointer): Pointer;
- var
- I: Integer;
- begin
- I := IndexOf(AKey);
- if I >= 0 then
- Result := InternalItems[I]+FKeySize
- else
- Error(SMapKeyError, PtrUInt(AKey));
- end;
- function TFPSMap.BinaryCompareKey(Key1, Key2: Pointer): Integer;
- begin
- Result := CompareByte(Key1^, Key2^, FKeySize);
- end;
- function TFPSMap.BinaryCompareData(Data1, Data2: Pointer): Integer;
- begin
- Result := CompareByte(Data1^, Data1^, FDataSize);
- end;
- procedure TFPSMap.SetOnKeyPtrCompare(Proc: TFPSListCompareFunc);
- begin
- if Proc <> nil then
- FOnKeyPtrCompare := Proc
- else
- FOnKeyPtrCompare := @BinaryCompareKey;
- end;
- procedure TFPSMap.SetOnDataPtrCompare(Proc: TFPSListCompareFunc);
- begin
- if Proc <> nil then
- FOnDataPtrCompare := Proc
- else
- FOnDataPtrCompare := @BinaryCompareData;
- end;
- procedure TFPSMap.InitOnPtrCompare;
- begin
- SetOnKeyPtrCompare(nil);
- SetOnDataPtrCompare(nil);
- end;
- procedure TFPSMap.PutKey(Index: Integer; AKey: Pointer);
- begin
- if FSorted then
- Error(SSortedListError, 0);
- CopyKey(AKey, Items[Index]);
- end;
- procedure TFPSMap.PutData(Index: Integer; AData: Pointer);
- begin
- CopyData(AData, PByte(Items[Index])+FKeySize);
- end;
- procedure TFPSMap.PutKeyData(AKey: Pointer; NewData: Pointer);
- var
- I: Integer;
- begin
- I := IndexOf(AKey);
- if I >= 0 then
- Data[I] := NewData
- else
- Add(AKey, NewData);
- end;
- procedure TFPSMap.SetSorted(Value: Boolean);
- begin
- if Value = FSorted then exit;
- FSorted := Value;
- if Value then Sort;
- end;
- function TFPSMap.Add(AKey: Pointer): Integer;
- begin
- if Sorted then
- begin
- if Find(AKey, Result) then
- case Duplicates of
- dupIgnore: exit;
- dupError: Error(SDuplicateItem, 0)
- end;
- end else
- Result := Count;
- CopyKey(AKey, inherited Insert(Result));
- end;
- function TFPSMap.Add(AKey, AData: Pointer): Integer;
- begin
- Result := Add(AKey);
- Data[Result] := AData;
- end;
- function TFPSMap.Find(AKey: Pointer; out Index: Integer): Boolean;
- { Searches for the first item <= Key, returns True if exact match,
- sets index to the index f the found string. }
- var
- I,L,R,Dir: Integer;
- begin
- Result := false;
- // Use binary search.
- L := 0;
- R := FCount-1;
- while L<=R do
- begin
- I := (L+R) div 2;
- Dir := FOnKeyPtrCompare(Items[I], AKey);
- if Dir < 0 then
- L := I+1
- else begin
- R := I-1;
- if Dir = 0 then
- begin
- Result := true;
- if Duplicates <> dupAccept then
- L := I;
- end;
- end;
- end;
- Index := L;
- end;
- function TFPSMap.LinearIndexOf(AKey: Pointer): Integer;
- var
- ListItem: Pointer;
- begin
- Result := 0;
- ListItem := First;
- while (Result < FCount) and (FOnKeyPtrCompare(ListItem, AKey) <> 0) do
- begin
- Inc(Result);
- ListItem := PByte(ListItem)+FItemSize;
- end;
- if Result = FCount then Result := -1;
- end;
- function TFPSMap.IndexOf(AKey: Pointer): Integer;
- begin
- if Sorted then
- begin
- if not Find(AKey, Result) then
- Result := -1;
- end else
- Result := LinearIndexOf(AKey);
- end;
- function TFPSMap.IndexOfData(AData: Pointer): Integer;
- var
- ListItem: Pointer;
- begin
- Result := 0;
- ListItem := First+FKeySize;
- while (Result < FCount) and (FOnDataPtrCompare(ListItem, AData) <> 0) do
- begin
- Inc(Result);
- ListItem := PByte(ListItem)+FItemSize;
- end;
- if Result = FCount then Result := -1;
- end;
- function TFPSMap.Insert(Index: Integer): Pointer;
- begin
- if FSorted then
- Error(SSortedListError, 0);
- Result := inherited Insert(Index);
- end;
- procedure TFPSMap.Insert(Index: Integer; out AKey, AData: Pointer);
- begin
- AKey := Insert(Index);
- AData := PByte(AKey) + FKeySize;
- end;
- procedure TFPSMap.InsertKey(Index: Integer; AKey: Pointer);
- begin
- CopyKey(AKey, Insert(Index));
- end;
- procedure TFPSMap.InsertKeyData(Index: Integer; AKey, AData: Pointer);
- var
- ListItem: Pointer;
- begin
- ListItem := Insert(Index);
- CopyKey(AKey, ListItem);
- CopyData(AData, PByte(ListItem)+FKeySize);
- end;
- function TFPSMap.Remove(AKey: Pointer): Integer;
- begin
- Result := IndexOf(AKey);
- if Result >= 0 then
- Delete(Result);
- end;
- procedure TFPSMap.Sort;
- begin
- inherited Sort(FOnKeyPtrCompare);
- end;
- {****************************************************************************
- TFPGMap
- ****************************************************************************}
- {$ifndef VER2_0}
- constructor TFPGMap.Create;
- begin
- inherited Create(SizeOf(TKey), SizeOf(TData));
- end;
- procedure TFPGMap.CopyItem(Src, Dest: Pointer);
- begin
- CopyKey(Src, Dest);
- CopyData(PByte(Src)+KeySize, PByte(Dest)+KeySize);
- end;
- procedure TFPGMap.CopyKey(Src, Dest: Pointer);
- begin
- TKey(Dest^) := TKey(Src^);
- end;
- procedure TFPGMap.CopyData(Src, Dest: Pointer);
- begin
- TData(Dest^) := TData(Src^);
- end;
- procedure TFPGMap.Deref(Item: Pointer);
- begin
- Finalize(TKey(Item^));
- Finalize(TData(Pointer(PByte(Item)+KeySize)^));
- end;
- function TFPGMap.GetKey(Index: Integer): TKey;
- begin
- Result := TKey(inherited GetKey(Index)^);
- end;
- function TFPGMap.GetData(Index: Integer): TData;
- begin
- Result := TData(inherited GetData(Index)^);
- end;
- function TFPGMap.GetKeyData(const AKey: TKey): TData;
- begin
- Result := TData(inherited GetKeyData(@AKey)^);
- end;
- function TFPGMap.KeyCompare(Key1, Key2: Pointer): Integer;
- begin
- if PKey(Key1)^ < PKey(Key2)^ then
- Result := -1
- else if PKey(Key1)^ > PKey(Key2)^ then
- Result := 1
- else
- Result := 0;
- end;
- {function TFPGMap.DataCompare(Data1, Data2: Pointer): Integer;
- begin
- if PData(Data1)^ < PData(Data2)^ then
- Result := -1
- else if PData(Data1)^ > PData(Data2)^ then
- Result := 1
- else
- Result := 0;
- end;}
- function TFPGMap.KeyCustomCompare(Key1, Key2: Pointer): Integer;
- begin
- Result := FOnKeyCompare(TKey(Key1^), TKey(Key2^));
- end;
- function TFPGMap.DataCustomCompare(Data1, Data2: Pointer): Integer;
- begin
- Result := FOnDataCompare(TData(Data1^), TData(Data2^));
- end;
- procedure TFPGMap.SetOnKeyCompare(NewCompare: TKeyCompareFunc);
- begin
- FOnKeyCompare := NewCompare;
- if NewCompare <> nil then
- OnKeyPtrCompare := @KeyCustomCompare
- else
- OnKeyPtrCompare := @KeyCompare;
- end;
- procedure TFPGMap.SetOnDataCompare(NewCompare: TDataCompareFunc);
- begin
- FOnDataCompare := NewCompare;
- if NewCompare <> nil then
- OnDataPtrCompare := @DataCustomCompare
- else
- OnDataPtrCompare := nil;
- end;
- procedure TFPGMap.InitOnPtrCompare;
- begin
- SetOnKeyCompare(nil);
- SetOnDataCompare(nil);
- end;
- procedure TFPGMap.PutKey(Index: Integer; const NewKey: TKey);
- begin
- inherited PutKey(Index, @NewKey);
- end;
- procedure TFPGMap.PutData(Index: Integer; const NewData: TData);
- begin
- inherited PutData(Index, @NewData);
- end;
- procedure TFPGMap.PutKeyData(const AKey: TKey; const NewData: TData);
- begin
- inherited PutKeyData(@AKey, @NewData);
- end;
- function TFPGMap.Add(const AKey: TKey): Integer;
- begin
- Result := inherited Add(@AKey);
- end;
- function TFPGMap.Add(const AKey: TKey; const AData: TData): Integer;
- begin
- Result := inherited Add(@AKey, @AData);
- end;
- function TFPGMap.Find(const AKey: TKey; out Index: Integer): Boolean;
- begin
- Result := inherited Find(@AKey, Index);
- end;
- function TFPGMap.IndexOf(const AKey: TKey): Integer;
- begin
- Result := inherited IndexOf(@AKey);
- end;
- function TFPGMap.IndexOfData(const AData: TData): Integer;
- begin
- { TODO: loop ? }
- Result := inherited IndexOfData(@AData);
- end;
- procedure TFPGMap.InsertKey(Index: Integer; const AKey: TKey);
- begin
- inherited InsertKey(Index, @AKey);
- end;
- procedure TFPGMap.InsertKeyData(Index: Integer; const AKey: TKey; const AData: TData);
- begin
- inherited InsertKeyData(Index, @AKey, @AData);
- end;
- function TFPGMap.Remove(const AKey: TKey): Integer;
- begin
- Result := inherited Remove(@AKey);
- end;
- {$endif}
- end.
|