mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-16 00:02:48 +02:00
New container class TDictionaryStringList for LazUtils
git-svn-id: trunk@40516 -
This commit is contained in:
parent
e085ecd22c
commit
a9239ca17d
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -2096,6 +2096,7 @@ components/lazutils/Makefile.fpc svneol=native#text/plain
|
||||
components/lazutils/asiancodepagefunctions.inc svneol=native#text/pascal
|
||||
components/lazutils/asiancodepages.inc svneol=native#text/pascal
|
||||
components/lazutils/avglvltree.pas svneol=native#text/pascal
|
||||
components/lazutils/dictionarystringlist.pas svneol=native#text/plain
|
||||
components/lazutils/easylazfreetype.pas svneol=native#text/pascal
|
||||
components/lazutils/fileutil.inc svneol=native#text/pascal
|
||||
components/lazutils/fileutil.pas svneol=native#text/pascal
|
||||
|
183
components/lazutils/dictionarystringlist.pas
Normal file
183
components/lazutils/dictionarystringlist.pas
Normal file
@ -0,0 +1,183 @@
|
||||
{
|
||||
*****************************************************************************
|
||||
* *
|
||||
* This file is part of the Lazarus Component Library (LCL) *
|
||||
* *
|
||||
* See the file COPYING.modifiedLGPL.txt, 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. *
|
||||
* *
|
||||
*****************************************************************************
|
||||
|
||||
Author: Juha Manninen
|
||||
|
||||
Abstract:
|
||||
This is an unsorted StringList with a fast lookup feature.
|
||||
Internally it uses a map container (TStringToPointerTree) to store the string again
|
||||
as key and string's index as value.
|
||||
It is then used for Contains, IndexOf and Find methods.
|
||||
|
||||
The extra container does not reserve too much memory because the strings are
|
||||
reference counted and not really copied.
|
||||
|
||||
This list cannot be sorted. For a sorted list you should use normal TStringList.
|
||||
This class is useful only when you must preserve the order in list,
|
||||
but also need to do fast lookups to see if a string exists.
|
||||
|
||||
"Duplicates" values dupIgnore and dupError are supported, unlike in unsorted StringList.
|
||||
|
||||
Insert, Delete and Exchange are not supported yet. They require the map's
|
||||
index values to be adjusted. There are at least 3 ways to solve it:
|
||||
1. Adjust only the changed indexes after each operation.
|
||||
2. Mark the map's index values as "dirty" after those operations.
|
||||
Adjust all the indexes when IndexOf() or Find() is called for the first time.
|
||||
3. Decide that those operations are not needed.
|
||||
This is a very specialized container after all.
|
||||
}
|
||||
unit DictionaryStringList;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, AvgLvlTree;
|
||||
|
||||
type
|
||||
|
||||
{ TDictionaryStringList }
|
||||
|
||||
TDictionaryStringList = class(TStringList)
|
||||
private
|
||||
FMap: TStringToPointerTree;
|
||||
function GetSorted: Boolean;
|
||||
procedure SetSorted(AValue: Boolean);
|
||||
protected
|
||||
// procedure InsertItem(Index: Integer; const S: string); override;
|
||||
// procedure InsertItem(Index: Integer; const S: string; O: TObject); override;
|
||||
public
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
function Add(const S: string): Integer; override;
|
||||
procedure Insert(Index: Integer; const S: string); override;
|
||||
procedure Clear; override;
|
||||
procedure Delete(Index: Integer); override;
|
||||
procedure Exchange(Index1, Index2: Integer); override;
|
||||
function Contains(const S: string): Boolean; // A new function
|
||||
function Find(const S: string; out Index: Integer): Boolean; override;
|
||||
function IndexOf(const S: string): Integer; override;
|
||||
procedure Sort; override;
|
||||
public
|
||||
property Sorted: Boolean read GetSorted write SetSorted;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
{ TDictionaryStringList }
|
||||
|
||||
constructor TDictionaryStringList.Create;
|
||||
begin
|
||||
inherited Create;
|
||||
FMap := TStringToPointerTree.Create(True);
|
||||
end;
|
||||
|
||||
destructor TDictionaryStringList.Destroy;
|
||||
begin
|
||||
FMap.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TDictionaryStringList.Add(const S: string): Integer;
|
||||
var
|
||||
i: PtrInt;
|
||||
begin
|
||||
Result := -1;
|
||||
if Duplicates <> dupAccept then
|
||||
if IndexOf(S) <> -1 then
|
||||
case Duplicates of
|
||||
DupIgnore : Exit;
|
||||
DupError : raise Exception.Create('TDictionaryStringList.Add: Duplicates are not allowed.');
|
||||
end;
|
||||
Result := inherited Add(S);
|
||||
i := Result;
|
||||
FMap[S] := Pointer(i); // Store index to map.
|
||||
end;
|
||||
|
||||
procedure TDictionaryStringList.Insert(Index: Integer; const S: string);
|
||||
begin
|
||||
raise Exception.Create('TDictionaryStringList.Insert is not implemented yet.');
|
||||
inherited Insert(Index, S);
|
||||
// ToDo: adjust all indexes in FMap after the item is inserted.
|
||||
end;
|
||||
{
|
||||
procedure TDictionaryStringList.InsertItem(Index: Integer; const S: string);
|
||||
begin
|
||||
inherited InsertItem(Index, S);
|
||||
end;
|
||||
|
||||
procedure TDictionaryStringList.InsertItem(Index: Integer; const S: string; O: TObject);
|
||||
begin
|
||||
inherited InsertItem(Index, S, O);
|
||||
end;
|
||||
}
|
||||
procedure TDictionaryStringList.Clear;
|
||||
begin
|
||||
inherited Clear;
|
||||
FMap.Clear;
|
||||
end;
|
||||
|
||||
procedure TDictionaryStringList.Delete(Index: Integer);
|
||||
begin
|
||||
raise Exception.Create('TDictionaryStringList.Delete is not implemented yet.');
|
||||
inherited Delete(Index);
|
||||
// ToDo: adjust all indexes in FMap after the item is deleted.
|
||||
end;
|
||||
|
||||
procedure TDictionaryStringList.Exchange(Index1, Index2: Integer);
|
||||
begin
|
||||
raise Exception.Create('TDictionaryStringList.Exchange is not implemented yet.');
|
||||
inherited Exchange(Index1, Index2);
|
||||
// ToDo: adjust all indexes in FMap after Exchange.
|
||||
end;
|
||||
|
||||
function TDictionaryStringList.Contains(const S: string): Boolean;
|
||||
begin
|
||||
Result := FMap.Contains(S);
|
||||
end;
|
||||
|
||||
function TDictionaryStringList.Find(const S: string; out Index: Integer): Boolean;
|
||||
begin
|
||||
Index := IndexOf(S);
|
||||
Result := Index <> -1;
|
||||
end;
|
||||
|
||||
function TDictionaryStringList.IndexOf(const S: string): Integer;
|
||||
begin
|
||||
if FMap.Contains(S) then
|
||||
Result := integer(PtrInt(FMap[S])) // Index is stored in the map.
|
||||
else
|
||||
Result := -1
|
||||
end;
|
||||
|
||||
procedure TDictionaryStringList.Sort;
|
||||
begin
|
||||
raise Exception.Create('This list is not meant to be sorted. Use TStringList instead.');
|
||||
end;
|
||||
|
||||
procedure TDictionaryStringList.SetSorted(AValue: Boolean);
|
||||
begin
|
||||
if AValue then
|
||||
Sort; // Raise an exception here, too.
|
||||
end;
|
||||
|
||||
function TDictionaryStringList.GetSorted: Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user