📄 jclarraylists.pas
字号:
I: Integer;
Last: Integer;
{$IFDEF THREADSAFE}
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
Last := First + Count - 1;
if Last >= FSize then
Last := FSize - 1;
Result := TJclStrArrayList.Create(Count);
for I := First to Last do
Result.Add(FElementData[I]);
end;
//=== { TJclArrayList } ======================================================
constructor TJclArrayList.Create(ACapacity: Integer = DefaultContainerCapacity;
AOwnsObjects: Boolean = True);
begin
inherited Create;
FSize := 0;
FOwnsObjects := AOwnsObjects;
if ACapacity < 0 then
FCapacity := 0
else
FCapacity := ACapacity;
SetLength(FElementData, FCapacity);
end;
constructor TJclArrayList.Create(ACollection: IJclCollection; AOwnsObjects: Boolean = True);
begin
// (rom) disabled because the following Create already calls inherited
// inherited Create;
if ACollection = nil then
raise EJclIllegalArgumentError.CreateRes(@RsENoCollection);
Create(ACollection.Size, AOwnsObjects);
AddAll(ACollection);
end;
destructor TJclArrayList.Destroy;
begin
Clear;
inherited Destroy;
end;
procedure TJclArrayList.Insert(Index: Integer; AObject: TObject);
{$IFDEF THREADSAFE}
var
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
if (Index < 0) or (Index > FSize) then
raise EJclOutOfBoundsError.CreateRes(@RsEOutOfBounds);
if FSize = Capacity then
Grow;
if FSize <> Index then
System.Move(FElementData[Index], FElementData[Index + 1],
(FSize - Index) * SizeOf(TObject));
FElementData[Index] := AObject;
Inc(FSize);
end;
function TJclArrayList.InsertAll(Index: Integer; ACollection: IJclCollection): Boolean;
var
It: IJclIterator;
Size: Integer;
{$IFDEF THREADSAFE}
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
Result := False;
if (Index < 0) or (Index >= FSize) then
raise EJclOutOfBoundsError.CreateRes(@RsEOutOfBounds);
if ACollection = nil then
Exit;
Size := ACollection.Size;
if FSize + Size >= Capacity then
Capacity := FSize + Size;
if Size <> 0 then
System.Move(FElementData[Index], FElementData[Index + Size],
Size * SizeOf(IInterface));
It := ACollection.First;
Result := It.HasNext;
while It.HasNext do
begin
FElementData[Index] := It.Next;
Inc(Index);
end;
end;
function TJclArrayList.Add(AObject: TObject): Boolean;
{$IFDEF THREADSAFE}
var
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
if FSize = Capacity then
Grow;
FElementData[FSize] := AObject;
Inc(FSize);
Result := True;
end;
function TJclArrayList.AddAll(ACollection: IJclCollection): Boolean;
var
It: IJclIterator;
{$IFDEF THREADSAFE}
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
Result := False;
if ACollection = nil then
Exit;
It := ACollection.First;
while It.HasNext do
begin
// (rom) inlining Add() gives about 5 percent performance increase
if FSize = Capacity then
Grow;
FElementData[FSize] := It.Next;
Inc(FSize);
end;
Result := True;
end;
procedure TJclArrayList.Clear;
var
I: Integer;
{$IFDEF THREADSAFE}
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
for I := 0 to FSize - 1 do
FreeObject(FElementData[I]);
FSize := 0;
end;
function TJclArrayList.Clone: TObject;
var
NewList: TJclArrayList;
begin
NewList := TJclArrayList.Create(Capacity, False); // Only one can have FOwnsObject = True
NewList.AddAll(Self);
Result := NewList;
end;
function TJclArrayList.Contains(AObject: TObject): Boolean;
var
I: Integer;
{$IFDEF THREADSAFE}
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
Result := False;
if AObject = nil then
Exit;
for I := 0 to FSize - 1 do
if FElementData[I] = AObject then
begin
Result := True;
Break;
end;
end;
function TJclArrayList.ContainsAll(ACollection: IJclCollection): Boolean;
var
It: IJclIterator;
{$IFDEF THREADSAFE}
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
Result := True;
if ACollection = nil then
Exit;
It := ACollection.First;
while Result and It.HasNext do
Result := contains(It.Next);
end;
function TJclArrayList.Equals(ACollection: IJclCollection): Boolean;
var
I: Integer;
It: IJclIterator;
{$IFDEF THREADSAFE}
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
Result := False;
if ACollection = nil then
Exit;
if FSize <> ACollection.Size then
Exit;
It := ACollection.First;
for I := 0 to FSize - 1 do
if FElementData[I] <> It.Next then
Exit;
Result := True;
end;
procedure TJclArrayList.FreeObject(var AObject: TObject);
begin
if FOwnsObjects then
begin
AObject.Free;
AObject := nil;
end;
end;
function TJclArrayList.GetObject(Index: Integer): TObject;
{$IFDEF THREADSAFE}
var
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
if (Index < 0) or (Index >= FSize) then
Result := nil
else
Result := FElementData[Index];
end;
procedure TJclArrayList.SetCapacity(ACapacity: Integer);
begin
if ACapacity >= FSize then
begin
SetLength(FElementData, ACapacity);
FCapacity := ACapacity;
end
else
raise EJclOutOfBoundsError.CreateRes(@RsEOutOfBounds);
end;
procedure TJclArrayList.Grow;
begin
if Capacity > 64 then
Capacity := Capacity + Capacity div 4
else if FCapacity = 0 then
FCapacity := 64
else
Capacity := Capacity * 4;
end;
function TJclArrayList.IndexOf(AObject: TObject): Integer;
var
I: Integer;
{$IFDEF THREADSAFE}
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
Result := -1;
if AObject = nil then
Exit;
for I := 0 to FSize - 1 do
if FElementData[I] = AObject then
begin
Result := I;
Break;
end;
end;
function TJclArrayList.First: IJclIterator;
begin
Result := TItr.Create(Self);
end;
function TJclArrayList.IsEmpty: Boolean;
begin
Result := FSize = 0;
end;
function TJclArrayList.Last: IJclIterator;
var
NewIterator: TItr;
begin
NewIterator := TItr.Create(Self);
NewIterator.FCursor := NewIterator.FOwnList.FSize;
NewIterator.FSize := NewIterator.FOwnList.FSize;
Result := NewIterator;
end;
function TJclArrayList.LastIndexOf(AObject: TObject): Integer;
var
I: Integer;
{$IFDEF THREADSAFE}
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
Result := -1;
if AObject = nil then
Exit;
for I := FSize - 1 downto 0 do
if FElementData[I] = AObject then
begin
Result := I;
Break;
end;
end;
function TJclArrayList.Remove(AObject: TObject): Boolean;
var
I: Integer;
{$IFDEF THREADSAFE}
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
Result := False;
if AObject = nil then
Exit;
for I := FSize - 1 downto 0 do
if FElementData[I] = AObject then // Removes all AObject
begin
FreeObject(FElementData[I]);
if FSize <> I then
System.Move(FElementData[I + 1], FElementData[I],
(FSize - I) * SizeOf(TObject));
Dec(FSize);
Result := True;
end;
end;
function TJclArrayList.Remove(Index: Integer): TObject;
{$IFDEF THREADSAFE}
var
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
if (Index < 0) or (Index >= FSize) then
raise EJclOutOfBoundsError.CreateRes(@RsEOutOfBounds);
Result := nil;
FreeObject(FElementData[Index]);
if FSize <> Index then
System.Move(FElementData[Index + 1], FElementData[Index],
(FSize - Index) * SizeOf(TObject));
Dec(FSize);
end;
function TJclArrayList.RemoveAll(ACollection: IJclCollection): Boolean;
var
It: IJclIterator;
{$IFDEF THREADSAFE}
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
Result := True;
if ACollection = nil then
Exit;
It := ACollection.First;
while It.HasNext do
Result := Remove(It.Next) and Result;
end;
function TJclArrayList.RetainAll(ACollection: IJclCollection): Boolean;
var
I: Integer;
{$IFDEF THREADSAFE}
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
Result := False;
if ACollection = nil then
Exit;
for I := FSize - 1 to 0 do
if not ACollection.Contains(FElementData[I]) then
Remove(I);
end;
procedure TJclArrayList.SetObject(Index: Integer; AObject: TObject);
{$IFDEF THREADSAFE}
var
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
if (Index < 0) or (Index >= FSize) then
raise EJclOutOfBoundsError.CreateRes(@RsEOutOfBounds);
FElementData[Index] := AObject;
end;
function TJclArrayList.Size: Integer;
begin
Result := FSize;
end;
function TJclArrayList.SubList(First, Count: Integer): IJclList;
var
I: Integer;
Last: Integer;
{$IFDEF THREADSAFE}
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
Last := First + Count - 1;
if Last >= FSize then
Last := FSize - 1;
Result := TJclArrayList.Create(Count, FOwnsObjects);
for I := First to Last do
Result.Add(FElementData[I]);
end;
// History:
// $Log: JclArrayLists.pas,v $
// Revision 1.10 2005/03/08 15:14:00 dade2004
// Fixed some bug on
// IJclStrList.InsertAll implementation
//
// Revision 1.9 2005/03/08 15:03:08 dade2004
// Fixed some bug on
// IJclStrList.InsertAll implementation
//
// Revision 1.8 2005/03/08 08:33:15 marquardt
// overhaul of exceptions and resourcestrings, minor style cleaning
//
// Revision 1.7 2005/03/03 08:02:56 marquardt
// various style cleanings, bugfixes and improvements
//
// Revision 1.6 2005/03/02 17:51:24 rrossmair
// - removed DCLAppendDelimited from JclAlgorithms, changed uses clauses accordingly
//
// Revision 1.5 2005/03/02 09:59:30 dade2004
// Added
// -TJclStrCollection in JclContainerIntf
// Every common methods for IJclStrCollection are implemented here
//
// -Every class that implement IJclStrCollection now derive from TJclStrCollection instead of TJclAbstractContainer
// -Every abstract method in TJclStrCollection has been marked as "override" in descendent classes
//
// DCLAppendDelimited has been removed from JclAlgorothms, his body has been fixed for a bug and put into
// relative method in TJclStrCollection
//
// Revision 1.4 2005/02/27 11:36:19 marquardt
// fixed and secured Capacity/Grow mechanism, raise exceptions with efficient CreateResRec
//
// Revision 1.3 2005/02/27 07:27:47 marquardt
// changed interface names from I to IJcl, moved resourcestrings to JclResource.pas
//
// Revision 1.2 2005/02/24 07:36:24 marquardt
// resolved the compiler warnings, style cleanup, removed code from JclContainerIntf.pas
//
// Revision 1.1 2005/02/24 03:57:10 rrossmair
// - donated DCL code, initial check-in
//
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -