git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.jcl@20 c37d764d-f447-7644-a108-883140d013fb
11967 lines
304 KiB
ObjectPascal
11967 lines
304 KiB
ObjectPascal
{**************************************************************************************************}
|
|
{ WARNING: JEDI preprocessor generated unit. Do not edit. }
|
|
{**************************************************************************************************}
|
|
|
|
{**************************************************************************************************}
|
|
{ }
|
|
{ Project JEDI Code Library (JCL) }
|
|
{ }
|
|
{ The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); }
|
|
{ you may not use this file except in compliance with the License. You may obtain a copy of the }
|
|
{ License at http://www.mozilla.org/MPL/ }
|
|
{ }
|
|
{ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF }
|
|
{ ANY KIND, either express or implied. See the License for the specific language governing rights }
|
|
{ and limitations under the License. }
|
|
{ }
|
|
{ The Original Code is ArrayList.pas. }
|
|
{ }
|
|
{ The Initial Developer of the Original Code is Jean-Philippe BEMPEL aka RDM. Portions created by }
|
|
{ Jean-Philippe BEMPEL are Copyright (C) Jean-Philippe BEMPEL (rdm_30 att yahoo dott com) }
|
|
{ All rights reserved. }
|
|
{ }
|
|
{ Contributors: }
|
|
{ Florent Ouchet (outchy) }
|
|
{ }
|
|
{**************************************************************************************************}
|
|
{ }
|
|
{ The Delphi Container Library }
|
|
{ }
|
|
{**************************************************************************************************}
|
|
{ }
|
|
{ Last modified: $Date:: 2009-10-22 18:22:16 +0200 (jeu., 22 oct. 2009) $ }
|
|
{ Revision: $Rev:: 3053 $ }
|
|
{ Author: $Author:: rrossmair $ }
|
|
{ }
|
|
{**************************************************************************************************}
|
|
|
|
unit JclArrayLists;
|
|
|
|
{$I jcl.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes,
|
|
{$IFDEF UNITVERSIONING}
|
|
JclUnitVersioning,
|
|
{$ENDIF UNITVERSIONING}
|
|
{$IFDEF SUPPORTS_GENERICS}
|
|
JclAlgorithms,
|
|
{$ENDIF SUPPORTS_GENERICS}
|
|
JclBase, JclAbstractContainers, JclContainerIntf, JclSynch;
|
|
|
|
type
|
|
TItrStart = (isFirst, isLast);
|
|
|
|
TJclIntfArrayList = class(TJclIntfAbstractContainer, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclIntfEqualityComparer,
|
|
IJclIntfCollection, IJclIntfList, IJclIntfArray)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
private
|
|
FElementData: TDynIInterfaceArray;
|
|
// fix ambiguous warnings when compiled on Delphi.net and earlier versions of Delphi.win32
|
|
// complaining about possible unaffected result.
|
|
function RaiseOutOfBoundsError: IInterface;
|
|
protected
|
|
procedure AssignDataTo(Dest: TJclAbstractContainerBase); override;
|
|
public
|
|
constructor Create(ACapacity: Integer); overload;
|
|
constructor Create(const ACollection: IJclIntfCollection); overload;
|
|
destructor Destroy; override;
|
|
{ IJclPackable }
|
|
procedure SetCapacity(Value: Integer); override;
|
|
{ IJclIntfCollection }
|
|
function Add(const AInterface: IInterface): Boolean;
|
|
function AddAll(const ACollection: IJclIntfCollection): Boolean;
|
|
procedure Clear;
|
|
function Contains(const AInterface: IInterface): Boolean;
|
|
function ContainsAll(const ACollection: IJclIntfCollection): Boolean;
|
|
function CollectionEquals(const ACollection: IJclIntfCollection): Boolean;
|
|
function Extract(const AInterface: IInterface): Boolean;
|
|
function ExtractAll(const ACollection: IJclIntfCollection): Boolean;
|
|
function First: IJclIntfIterator;
|
|
function IsEmpty: Boolean;
|
|
function Last: IJclIntfIterator;
|
|
function Remove(const AInterface: IInterface): Boolean;
|
|
function RemoveAll(const ACollection: IJclIntfCollection): Boolean;
|
|
function RetainAll(const ACollection: IJclIntfCollection): Boolean;
|
|
function Size: Integer;
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function GetEnumerator: IJclIntfIterator;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
{ IJclIntfList }
|
|
function Delete(Index: Integer): IInterface;
|
|
function ExtractIndex(Index: Integer): IInterface;
|
|
function GetObject(Index: Integer): IInterface;
|
|
function IndexOf(const AInterface: IInterface): Integer;
|
|
function Insert(Index: Integer; const AInterface: IInterface): Boolean;
|
|
function InsertAll(Index: Integer; const ACollection: IJclIntfCollection): Boolean;
|
|
function LastIndexOf(const AInterface: IInterface): Integer;
|
|
procedure SetObject(Index: Integer; const AInterface: IInterface);
|
|
function SubList(First, Count: Integer): IJclIntfList;
|
|
end;
|
|
|
|
TJclIntfArrayIterator = class(TJclAbstractIterator, IJclIntfIterator, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable)
|
|
private
|
|
FCursor: Integer;
|
|
FStart: TItrStart;
|
|
FOwnList: IJclIntfList;
|
|
protected
|
|
procedure AssignPropertiesTo(Dest: TJclAbstractIterator); override;
|
|
function CreateEmptyIterator: TJclAbstractIterator; override;
|
|
public
|
|
constructor Create(const AOwnList: IJclIntfList; ACursor: Integer; AValid: Boolean; AStart: TItrStart);
|
|
{ IJclIntfIterator }
|
|
function Add(const AInterface: IInterface): Boolean;
|
|
procedure Extract;
|
|
function GetObject: IInterface;
|
|
function HasNext: Boolean;
|
|
function HasPrevious: Boolean;
|
|
function Insert(const AInterface: IInterface): Boolean;
|
|
function IteratorEquals(const AIterator: IJclIntfIterator): Boolean;
|
|
function Next: IInterface;
|
|
function NextIndex: Integer;
|
|
function Previous: IInterface;
|
|
function PreviousIndex: Integer;
|
|
procedure Remove;
|
|
procedure Reset;
|
|
procedure SetObject(const AInterface: IInterface);
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function MoveNext: Boolean;
|
|
property Current: IInterface read GetObject;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
end;
|
|
|
|
TJclAnsiStrArrayList = class(TJclAnsiStrAbstractCollection, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclStrContainer, IJclAnsiStrContainer, IJclAnsiStrFlatContainer, IJclAnsiStrEqualityComparer,
|
|
IJclAnsiStrCollection, IJclAnsiStrList, IJclAnsiStrArray)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
private
|
|
FElementData: TDynAnsiStringArray;
|
|
// fix ambiguous warnings when compiled on Delphi.net and earlier versions of Delphi.win32
|
|
// complaining about possible unaffected result.
|
|
function RaiseOutOfBoundsError: AnsiString;
|
|
protected
|
|
procedure AssignDataTo(Dest: TJclAbstractContainerBase); override;
|
|
public
|
|
constructor Create(ACapacity: Integer); overload;
|
|
constructor Create(const ACollection: IJclAnsiStrCollection); overload;
|
|
destructor Destroy; override;
|
|
{ IJclPackable }
|
|
procedure SetCapacity(Value: Integer); override;
|
|
{ IJclAnsiStrCollection }
|
|
function Add(const AString: AnsiString): Boolean; override;
|
|
function AddAll(const ACollection: IJclAnsiStrCollection): Boolean; override;
|
|
procedure Clear; override;
|
|
function Contains(const AString: AnsiString): Boolean; override;
|
|
function ContainsAll(const ACollection: IJclAnsiStrCollection): Boolean; override;
|
|
function CollectionEquals(const ACollection: IJclAnsiStrCollection): Boolean; override;
|
|
function Extract(const AString: AnsiString): Boolean; override;
|
|
function ExtractAll(const ACollection: IJclAnsiStrCollection): Boolean; override;
|
|
function First: IJclAnsiStrIterator; override;
|
|
function IsEmpty: Boolean; override;
|
|
function Last: IJclAnsiStrIterator; override;
|
|
function Remove(const AString: AnsiString): Boolean; override;
|
|
function RemoveAll(const ACollection: IJclAnsiStrCollection): Boolean; override;
|
|
function RetainAll(const ACollection: IJclAnsiStrCollection): Boolean; override;
|
|
function Size: Integer; override;
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function GetEnumerator: IJclAnsiStrIterator; override;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
{ IJclAnsiStrList }
|
|
function Delete(Index: Integer): AnsiString;
|
|
function ExtractIndex(Index: Integer): AnsiString;
|
|
function GetString(Index: Integer): AnsiString;
|
|
function IndexOf(const AString: AnsiString): Integer;
|
|
function Insert(Index: Integer; const AString: AnsiString): Boolean;
|
|
function InsertAll(Index: Integer; const ACollection: IJclAnsiStrCollection): Boolean;
|
|
function LastIndexOf(const AString: AnsiString): Integer;
|
|
procedure SetString(Index: Integer; const AString: AnsiString);
|
|
function SubList(First, Count: Integer): IJclAnsiStrList;
|
|
end;
|
|
|
|
TJclAnsiStrArrayIterator = class(TJclAbstractIterator, IJclAnsiStrIterator, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable)
|
|
private
|
|
FCursor: Integer;
|
|
FStart: TItrStart;
|
|
FOwnList: IJclAnsiStrList;
|
|
protected
|
|
procedure AssignPropertiesTo(Dest: TJclAbstractIterator); override;
|
|
function CreateEmptyIterator: TJclAbstractIterator; override;
|
|
public
|
|
constructor Create(const AOwnList: IJclAnsiStrList; ACursor: Integer; AValid: Boolean; AStart: TItrStart);
|
|
{ IJclAnsiStrIterator }
|
|
function Add(const AString: AnsiString): Boolean;
|
|
procedure Extract;
|
|
function GetString: AnsiString;
|
|
function HasNext: Boolean;
|
|
function HasPrevious: Boolean;
|
|
function Insert(const AString: AnsiString): Boolean;
|
|
function IteratorEquals(const AIterator: IJclAnsiStrIterator): Boolean;
|
|
function Next: AnsiString;
|
|
function NextIndex: Integer;
|
|
function Previous: AnsiString;
|
|
function PreviousIndex: Integer;
|
|
procedure Remove;
|
|
procedure Reset;
|
|
procedure SetString(const AString: AnsiString);
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function MoveNext: Boolean;
|
|
property Current: AnsiString read GetString;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
end;
|
|
|
|
TJclWideStrArrayList = class(TJclWideStrAbstractCollection, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclStrContainer, IJclWideStrContainer, IJclWideStrFlatContainer, IJclWideStrEqualityComparer,
|
|
IJclWideStrCollection, IJclWideStrList, IJclWideStrArray)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
private
|
|
FElementData: TDynWideStringArray;
|
|
// fix ambiguous warnings when compiled on Delphi.net and earlier versions of Delphi.win32
|
|
// complaining about possible unaffected result.
|
|
function RaiseOutOfBoundsError: WideString;
|
|
protected
|
|
procedure AssignDataTo(Dest: TJclAbstractContainerBase); override;
|
|
public
|
|
constructor Create(ACapacity: Integer); overload;
|
|
constructor Create(const ACollection: IJclWideStrCollection); overload;
|
|
destructor Destroy; override;
|
|
{ IJclPackable }
|
|
procedure SetCapacity(Value: Integer); override;
|
|
{ IJclWideStrCollection }
|
|
function Add(const AString: WideString): Boolean; override;
|
|
function AddAll(const ACollection: IJclWideStrCollection): Boolean; override;
|
|
procedure Clear; override;
|
|
function Contains(const AString: WideString): Boolean; override;
|
|
function ContainsAll(const ACollection: IJclWideStrCollection): Boolean; override;
|
|
function CollectionEquals(const ACollection: IJclWideStrCollection): Boolean; override;
|
|
function Extract(const AString: WideString): Boolean; override;
|
|
function ExtractAll(const ACollection: IJclWideStrCollection): Boolean; override;
|
|
function First: IJclWideStrIterator; override;
|
|
function IsEmpty: Boolean; override;
|
|
function Last: IJclWideStrIterator; override;
|
|
function Remove(const AString: WideString): Boolean; override;
|
|
function RemoveAll(const ACollection: IJclWideStrCollection): Boolean; override;
|
|
function RetainAll(const ACollection: IJclWideStrCollection): Boolean; override;
|
|
function Size: Integer; override;
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function GetEnumerator: IJclWideStrIterator; override;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
{ IJclWideStrList }
|
|
function Delete(Index: Integer): WideString;
|
|
function ExtractIndex(Index: Integer): WideString;
|
|
function GetString(Index: Integer): WideString;
|
|
function IndexOf(const AString: WideString): Integer;
|
|
function Insert(Index: Integer; const AString: WideString): Boolean;
|
|
function InsertAll(Index: Integer; const ACollection: IJclWideStrCollection): Boolean;
|
|
function LastIndexOf(const AString: WideString): Integer;
|
|
procedure SetString(Index: Integer; const AString: WideString);
|
|
function SubList(First, Count: Integer): IJclWideStrList;
|
|
end;
|
|
|
|
TJclWideStrArrayIterator = class(TJclAbstractIterator, IJclWideStrIterator, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable)
|
|
private
|
|
FCursor: Integer;
|
|
FStart: TItrStart;
|
|
FOwnList: IJclWideStrList;
|
|
protected
|
|
procedure AssignPropertiesTo(Dest: TJclAbstractIterator); override;
|
|
function CreateEmptyIterator: TJclAbstractIterator; override;
|
|
public
|
|
constructor Create(const AOwnList: IJclWideStrList; ACursor: Integer; AValid: Boolean; AStart: TItrStart);
|
|
{ IJclWideStrIterator }
|
|
function Add(const AString: WideString): Boolean;
|
|
procedure Extract;
|
|
function GetString: WideString;
|
|
function HasNext: Boolean;
|
|
function HasPrevious: Boolean;
|
|
function Insert(const AString: WideString): Boolean;
|
|
function IteratorEquals(const AIterator: IJclWideStrIterator): Boolean;
|
|
function Next: WideString;
|
|
function NextIndex: Integer;
|
|
function Previous: WideString;
|
|
function PreviousIndex: Integer;
|
|
procedure Remove;
|
|
procedure Reset;
|
|
procedure SetString(const AString: WideString);
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function MoveNext: Boolean;
|
|
property Current: WideString read GetString;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_UNICODE_STRING}
|
|
TJclUnicodeStrArrayList = class(TJclUnicodeStrAbstractCollection, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclStrContainer, IJclUnicodeStrContainer, IJclUnicodeStrFlatContainer, IJclUnicodeStrEqualityComparer,
|
|
IJclUnicodeStrCollection, IJclUnicodeStrList, IJclUnicodeStrArray)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
private
|
|
FElementData: TDynUnicodeStringArray;
|
|
// fix ambiguous warnings when compiled on Delphi.net and earlier versions of Delphi.win32
|
|
// complaining about possible unaffected result.
|
|
function RaiseOutOfBoundsError: UnicodeString;
|
|
protected
|
|
procedure AssignDataTo(Dest: TJclAbstractContainerBase); override;
|
|
public
|
|
constructor Create(ACapacity: Integer); overload;
|
|
constructor Create(const ACollection: IJclUnicodeStrCollection); overload;
|
|
destructor Destroy; override;
|
|
{ IJclPackable }
|
|
procedure SetCapacity(Value: Integer); override;
|
|
{ IJclUnicodeStrCollection }
|
|
function Add(const AString: UnicodeString): Boolean; override;
|
|
function AddAll(const ACollection: IJclUnicodeStrCollection): Boolean; override;
|
|
procedure Clear; override;
|
|
function Contains(const AString: UnicodeString): Boolean; override;
|
|
function ContainsAll(const ACollection: IJclUnicodeStrCollection): Boolean; override;
|
|
function CollectionEquals(const ACollection: IJclUnicodeStrCollection): Boolean; override;
|
|
function Extract(const AString: UnicodeString): Boolean; override;
|
|
function ExtractAll(const ACollection: IJclUnicodeStrCollection): Boolean; override;
|
|
function First: IJclUnicodeStrIterator; override;
|
|
function IsEmpty: Boolean; override;
|
|
function Last: IJclUnicodeStrIterator; override;
|
|
function Remove(const AString: UnicodeString): Boolean; override;
|
|
function RemoveAll(const ACollection: IJclUnicodeStrCollection): Boolean; override;
|
|
function RetainAll(const ACollection: IJclUnicodeStrCollection): Boolean; override;
|
|
function Size: Integer; override;
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function GetEnumerator: IJclUnicodeStrIterator; override;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
{ IJclUnicodeStrList }
|
|
function Delete(Index: Integer): UnicodeString;
|
|
function ExtractIndex(Index: Integer): UnicodeString;
|
|
function GetString(Index: Integer): UnicodeString;
|
|
function IndexOf(const AString: UnicodeString): Integer;
|
|
function Insert(Index: Integer; const AString: UnicodeString): Boolean;
|
|
function InsertAll(Index: Integer; const ACollection: IJclUnicodeStrCollection): Boolean;
|
|
function LastIndexOf(const AString: UnicodeString): Integer;
|
|
procedure SetString(Index: Integer; const AString: UnicodeString);
|
|
function SubList(First, Count: Integer): IJclUnicodeStrList;
|
|
end;
|
|
|
|
TJclUnicodeStrArrayIterator = class(TJclAbstractIterator, IJclUnicodeStrIterator, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable)
|
|
private
|
|
FCursor: Integer;
|
|
FStart: TItrStart;
|
|
FOwnList: IJclUnicodeStrList;
|
|
protected
|
|
procedure AssignPropertiesTo(Dest: TJclAbstractIterator); override;
|
|
function CreateEmptyIterator: TJclAbstractIterator; override;
|
|
public
|
|
constructor Create(const AOwnList: IJclUnicodeStrList; ACursor: Integer; AValid: Boolean; AStart: TItrStart);
|
|
{ IJclUnicodeStrIterator }
|
|
function Add(const AString: UnicodeString): Boolean;
|
|
procedure Extract;
|
|
function GetString: UnicodeString;
|
|
function HasNext: Boolean;
|
|
function HasPrevious: Boolean;
|
|
function Insert(const AString: UnicodeString): Boolean;
|
|
function IteratorEquals(const AIterator: IJclUnicodeStrIterator): Boolean;
|
|
function Next: UnicodeString;
|
|
function NextIndex: Integer;
|
|
function Previous: UnicodeString;
|
|
function PreviousIndex: Integer;
|
|
procedure Remove;
|
|
procedure Reset;
|
|
procedure SetString(const AString: UnicodeString);
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function MoveNext: Boolean;
|
|
property Current: UnicodeString read GetString;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
end;
|
|
{$ENDIF SUPPORTS_UNICODE_STRING}
|
|
|
|
{$IFDEF CONTAINER_ANSISTR}
|
|
TJclStrArrayList = TJclAnsiStrArrayList;
|
|
{$ENDIF CONTAINER_ANSISTR}
|
|
{$IFDEF CONTAINER_WIDESTR}
|
|
TJclStrArrayList = TJclWideStrArrayList;
|
|
{$ENDIF CONTAINER_WIDESTR}
|
|
{$IFDEF CONTAINER_UNICODESTR}
|
|
TJclStrArrayList = TJclUnicodeStrArrayList;
|
|
{$ENDIF CONTAINER_UNICODESTR}
|
|
|
|
TJclSingleArrayList = class(TJclSingleAbstractContainer, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclSingleContainer, IJclSingleEqualityComparer,
|
|
IJclSingleCollection, IJclSingleList, IJclSingleArray)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
private
|
|
FElementData: TDynSingleArray;
|
|
// fix ambiguous warnings when compiled on Delphi.net and earlier versions of Delphi.win32
|
|
// complaining about possible unaffected result.
|
|
function RaiseOutOfBoundsError: Single;
|
|
protected
|
|
procedure AssignDataTo(Dest: TJclAbstractContainerBase); override;
|
|
public
|
|
constructor Create(ACapacity: Integer); overload;
|
|
constructor Create(const ACollection: IJclSingleCollection); overload;
|
|
destructor Destroy; override;
|
|
{ IJclPackable }
|
|
procedure SetCapacity(Value: Integer); override;
|
|
{ IJclSingleCollection }
|
|
function Add(const AValue: Single): Boolean;
|
|
function AddAll(const ACollection: IJclSingleCollection): Boolean;
|
|
procedure Clear;
|
|
function Contains(const AValue: Single): Boolean;
|
|
function ContainsAll(const ACollection: IJclSingleCollection): Boolean;
|
|
function CollectionEquals(const ACollection: IJclSingleCollection): Boolean;
|
|
function Extract(const AValue: Single): Boolean;
|
|
function ExtractAll(const ACollection: IJclSingleCollection): Boolean;
|
|
function First: IJclSingleIterator;
|
|
function IsEmpty: Boolean;
|
|
function Last: IJclSingleIterator;
|
|
function Remove(const AValue: Single): Boolean;
|
|
function RemoveAll(const ACollection: IJclSingleCollection): Boolean;
|
|
function RetainAll(const ACollection: IJclSingleCollection): Boolean;
|
|
function Size: Integer;
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function GetEnumerator: IJclSingleIterator;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
{ IJclSingleList }
|
|
function Delete(Index: Integer): Single;
|
|
function ExtractIndex(Index: Integer): Single;
|
|
function GetValue(Index: Integer): Single;
|
|
function IndexOf(const AValue: Single): Integer;
|
|
function Insert(Index: Integer; const AValue: Single): Boolean;
|
|
function InsertAll(Index: Integer; const ACollection: IJclSingleCollection): Boolean;
|
|
function LastIndexOf(const AValue: Single): Integer;
|
|
procedure SetValue(Index: Integer; const AValue: Single);
|
|
function SubList(First, Count: Integer): IJclSingleList;
|
|
end;
|
|
|
|
TJclSingleArrayIterator = class(TJclAbstractIterator, IJclSingleIterator, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable)
|
|
private
|
|
FCursor: Integer;
|
|
FStart: TItrStart;
|
|
FOwnList: IJclSingleList;
|
|
protected
|
|
procedure AssignPropertiesTo(Dest: TJclAbstractIterator); override;
|
|
function CreateEmptyIterator: TJclAbstractIterator; override;
|
|
public
|
|
constructor Create(const AOwnList: IJclSingleList; ACursor: Integer; AValid: Boolean; AStart: TItrStart);
|
|
{ IJclSingleIterator }
|
|
function Add(const AValue: Single): Boolean;
|
|
procedure Extract;
|
|
function GetValue: Single;
|
|
function HasNext: Boolean;
|
|
function HasPrevious: Boolean;
|
|
function Insert(const AValue: Single): Boolean;
|
|
function IteratorEquals(const AIterator: IJclSingleIterator): Boolean;
|
|
function Next: Single;
|
|
function NextIndex: Integer;
|
|
function Previous: Single;
|
|
function PreviousIndex: Integer;
|
|
procedure Remove;
|
|
procedure Reset;
|
|
procedure SetValue(const AValue: Single);
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function MoveNext: Boolean;
|
|
property Current: Single read GetValue;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
end;
|
|
|
|
TJclDoubleArrayList = class(TJclDoubleAbstractContainer, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclDoubleContainer, IJclDoubleEqualityComparer,
|
|
IJclDoubleCollection, IJclDoubleList, IJclDoubleArray)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
private
|
|
FElementData: TDynDoubleArray;
|
|
// fix ambiguous warnings when compiled on Delphi.net and earlier versions of Delphi.win32
|
|
// complaining about possible unaffected result.
|
|
function RaiseOutOfBoundsError: Double;
|
|
protected
|
|
procedure AssignDataTo(Dest: TJclAbstractContainerBase); override;
|
|
public
|
|
constructor Create(ACapacity: Integer); overload;
|
|
constructor Create(const ACollection: IJclDoubleCollection); overload;
|
|
destructor Destroy; override;
|
|
{ IJclPackable }
|
|
procedure SetCapacity(Value: Integer); override;
|
|
{ IJclDoubleCollection }
|
|
function Add(const AValue: Double): Boolean;
|
|
function AddAll(const ACollection: IJclDoubleCollection): Boolean;
|
|
procedure Clear;
|
|
function Contains(const AValue: Double): Boolean;
|
|
function ContainsAll(const ACollection: IJclDoubleCollection): Boolean;
|
|
function CollectionEquals(const ACollection: IJclDoubleCollection): Boolean;
|
|
function Extract(const AValue: Double): Boolean;
|
|
function ExtractAll(const ACollection: IJclDoubleCollection): Boolean;
|
|
function First: IJclDoubleIterator;
|
|
function IsEmpty: Boolean;
|
|
function Last: IJclDoubleIterator;
|
|
function Remove(const AValue: Double): Boolean;
|
|
function RemoveAll(const ACollection: IJclDoubleCollection): Boolean;
|
|
function RetainAll(const ACollection: IJclDoubleCollection): Boolean;
|
|
function Size: Integer;
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function GetEnumerator: IJclDoubleIterator;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
{ IJclDoubleList }
|
|
function Delete(Index: Integer): Double;
|
|
function ExtractIndex(Index: Integer): Double;
|
|
function GetValue(Index: Integer): Double;
|
|
function IndexOf(const AValue: Double): Integer;
|
|
function Insert(Index: Integer; const AValue: Double): Boolean;
|
|
function InsertAll(Index: Integer; const ACollection: IJclDoubleCollection): Boolean;
|
|
function LastIndexOf(const AValue: Double): Integer;
|
|
procedure SetValue(Index: Integer; const AValue: Double);
|
|
function SubList(First, Count: Integer): IJclDoubleList;
|
|
end;
|
|
|
|
TJclDoubleArrayIterator = class(TJclAbstractIterator, IJclDoubleIterator, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable)
|
|
private
|
|
FCursor: Integer;
|
|
FStart: TItrStart;
|
|
FOwnList: IJclDoubleList;
|
|
protected
|
|
procedure AssignPropertiesTo(Dest: TJclAbstractIterator); override;
|
|
function CreateEmptyIterator: TJclAbstractIterator; override;
|
|
public
|
|
constructor Create(const AOwnList: IJclDoubleList; ACursor: Integer; AValid: Boolean; AStart: TItrStart);
|
|
{ IJclDoubleIterator }
|
|
function Add(const AValue: Double): Boolean;
|
|
procedure Extract;
|
|
function GetValue: Double;
|
|
function HasNext: Boolean;
|
|
function HasPrevious: Boolean;
|
|
function Insert(const AValue: Double): Boolean;
|
|
function IteratorEquals(const AIterator: IJclDoubleIterator): Boolean;
|
|
function Next: Double;
|
|
function NextIndex: Integer;
|
|
function Previous: Double;
|
|
function PreviousIndex: Integer;
|
|
procedure Remove;
|
|
procedure Reset;
|
|
procedure SetValue(const AValue: Double);
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function MoveNext: Boolean;
|
|
property Current: Double read GetValue;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
end;
|
|
|
|
TJclExtendedArrayList = class(TJclExtendedAbstractContainer, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclExtendedContainer, IJclExtendedEqualityComparer,
|
|
IJclExtendedCollection, IJclExtendedList, IJclExtendedArray)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
private
|
|
FElementData: TDynExtendedArray;
|
|
// fix ambiguous warnings when compiled on Delphi.net and earlier versions of Delphi.win32
|
|
// complaining about possible unaffected result.
|
|
function RaiseOutOfBoundsError: Extended;
|
|
protected
|
|
procedure AssignDataTo(Dest: TJclAbstractContainerBase); override;
|
|
public
|
|
constructor Create(ACapacity: Integer); overload;
|
|
constructor Create(const ACollection: IJclExtendedCollection); overload;
|
|
destructor Destroy; override;
|
|
{ IJclPackable }
|
|
procedure SetCapacity(Value: Integer); override;
|
|
{ IJclExtendedCollection }
|
|
function Add(const AValue: Extended): Boolean;
|
|
function AddAll(const ACollection: IJclExtendedCollection): Boolean;
|
|
procedure Clear;
|
|
function Contains(const AValue: Extended): Boolean;
|
|
function ContainsAll(const ACollection: IJclExtendedCollection): Boolean;
|
|
function CollectionEquals(const ACollection: IJclExtendedCollection): Boolean;
|
|
function Extract(const AValue: Extended): Boolean;
|
|
function ExtractAll(const ACollection: IJclExtendedCollection): Boolean;
|
|
function First: IJclExtendedIterator;
|
|
function IsEmpty: Boolean;
|
|
function Last: IJclExtendedIterator;
|
|
function Remove(const AValue: Extended): Boolean;
|
|
function RemoveAll(const ACollection: IJclExtendedCollection): Boolean;
|
|
function RetainAll(const ACollection: IJclExtendedCollection): Boolean;
|
|
function Size: Integer;
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function GetEnumerator: IJclExtendedIterator;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
{ IJclExtendedList }
|
|
function Delete(Index: Integer): Extended;
|
|
function ExtractIndex(Index: Integer): Extended;
|
|
function GetValue(Index: Integer): Extended;
|
|
function IndexOf(const AValue: Extended): Integer;
|
|
function Insert(Index: Integer; const AValue: Extended): Boolean;
|
|
function InsertAll(Index: Integer; const ACollection: IJclExtendedCollection): Boolean;
|
|
function LastIndexOf(const AValue: Extended): Integer;
|
|
procedure SetValue(Index: Integer; const AValue: Extended);
|
|
function SubList(First, Count: Integer): IJclExtendedList;
|
|
end;
|
|
|
|
TJclExtendedArrayIterator = class(TJclAbstractIterator, IJclExtendedIterator, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable)
|
|
private
|
|
FCursor: Integer;
|
|
FStart: TItrStart;
|
|
FOwnList: IJclExtendedList;
|
|
protected
|
|
procedure AssignPropertiesTo(Dest: TJclAbstractIterator); override;
|
|
function CreateEmptyIterator: TJclAbstractIterator; override;
|
|
public
|
|
constructor Create(const AOwnList: IJclExtendedList; ACursor: Integer; AValid: Boolean; AStart: TItrStart);
|
|
{ IJclExtendedIterator }
|
|
function Add(const AValue: Extended): Boolean;
|
|
procedure Extract;
|
|
function GetValue: Extended;
|
|
function HasNext: Boolean;
|
|
function HasPrevious: Boolean;
|
|
function Insert(const AValue: Extended): Boolean;
|
|
function IteratorEquals(const AIterator: IJclExtendedIterator): Boolean;
|
|
function Next: Extended;
|
|
function NextIndex: Integer;
|
|
function Previous: Extended;
|
|
function PreviousIndex: Integer;
|
|
procedure Remove;
|
|
procedure Reset;
|
|
procedure SetValue(const AValue: Extended);
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function MoveNext: Boolean;
|
|
property Current: Extended read GetValue;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
end;
|
|
|
|
{$IFDEF MATH_EXTENDED_PRECISION}
|
|
TJclFloatArrayList = TJclExtendedArrayList;
|
|
{$ENDIF MATH_EXTENDED_PRECISION}
|
|
{$IFDEF MATH_DOUBLE_PRECISION}
|
|
TJclFloatArrayList = TJclDoubleArrayList;
|
|
{$ENDIF MATH_DOUBLE_PRECISION}
|
|
{$IFDEF MATH_SINGLE_PRECISION}
|
|
TJclFloatArrayList = TJclSingleArrayList;
|
|
{$ENDIF MATH_SINGLE_PRECISION}
|
|
|
|
TJclIntegerArrayList = class(TJclIntegerAbstractContainer, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclIntegerEqualityComparer,
|
|
IJclIntegerCollection, IJclIntegerList, IJclIntegerArray)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
private
|
|
FElementData: TDynIntegerArray;
|
|
// fix ambiguous warnings when compiled on Delphi.net and earlier versions of Delphi.win32
|
|
// complaining about possible unaffected result.
|
|
function RaiseOutOfBoundsError: Integer;
|
|
protected
|
|
procedure AssignDataTo(Dest: TJclAbstractContainerBase); override;
|
|
public
|
|
constructor Create(ACapacity: Integer); overload;
|
|
constructor Create(const ACollection: IJclIntegerCollection); overload;
|
|
destructor Destroy; override;
|
|
{ IJclPackable }
|
|
procedure SetCapacity(Value: Integer); override;
|
|
{ IJclIntegerCollection }
|
|
function Add(AValue: Integer): Boolean;
|
|
function AddAll(const ACollection: IJclIntegerCollection): Boolean;
|
|
procedure Clear;
|
|
function Contains(AValue: Integer): Boolean;
|
|
function ContainsAll(const ACollection: IJclIntegerCollection): Boolean;
|
|
function CollectionEquals(const ACollection: IJclIntegerCollection): Boolean;
|
|
function Extract(AValue: Integer): Boolean;
|
|
function ExtractAll(const ACollection: IJclIntegerCollection): Boolean;
|
|
function First: IJclIntegerIterator;
|
|
function IsEmpty: Boolean;
|
|
function Last: IJclIntegerIterator;
|
|
function Remove(AValue: Integer): Boolean;
|
|
function RemoveAll(const ACollection: IJclIntegerCollection): Boolean;
|
|
function RetainAll(const ACollection: IJclIntegerCollection): Boolean;
|
|
function Size: Integer;
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function GetEnumerator: IJclIntegerIterator;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
{ IJclIntegerList }
|
|
function Delete(Index: Integer): Integer;
|
|
function ExtractIndex(Index: Integer): Integer;
|
|
function GetValue(Index: Integer): Integer;
|
|
function IndexOf(AValue: Integer): Integer;
|
|
function Insert(Index: Integer; AValue: Integer): Boolean;
|
|
function InsertAll(Index: Integer; const ACollection: IJclIntegerCollection): Boolean;
|
|
function LastIndexOf(AValue: Integer): Integer;
|
|
procedure SetValue(Index: Integer; AValue: Integer);
|
|
function SubList(First, Count: Integer): IJclIntegerList;
|
|
end;
|
|
|
|
TJclIntegerArrayIterator = class(TJclAbstractIterator, IJclIntegerIterator, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable)
|
|
private
|
|
FCursor: Integer;
|
|
FStart: TItrStart;
|
|
FOwnList: IJclIntegerList;
|
|
protected
|
|
procedure AssignPropertiesTo(Dest: TJclAbstractIterator); override;
|
|
function CreateEmptyIterator: TJclAbstractIterator; override;
|
|
public
|
|
constructor Create(const AOwnList: IJclIntegerList; ACursor: Integer; AValid: Boolean; AStart: TItrStart);
|
|
{ IJclIntegerIterator }
|
|
function Add(AValue: Integer): Boolean;
|
|
procedure Extract;
|
|
function GetValue: Integer;
|
|
function HasNext: Boolean;
|
|
function HasPrevious: Boolean;
|
|
function Insert(AValue: Integer): Boolean;
|
|
function IteratorEquals(const AIterator: IJclIntegerIterator): Boolean;
|
|
function Next: Integer;
|
|
function NextIndex: Integer;
|
|
function Previous: Integer;
|
|
function PreviousIndex: Integer;
|
|
procedure Remove;
|
|
procedure Reset;
|
|
procedure SetValue(AValue: Integer);
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function MoveNext: Boolean;
|
|
property Current: Integer read GetValue;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
end;
|
|
|
|
TJclCardinalArrayList = class(TJclCardinalAbstractContainer, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclCardinalEqualityComparer,
|
|
IJclCardinalCollection, IJclCardinalList, IJclCardinalArray)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
private
|
|
FElementData: TDynCardinalArray;
|
|
// fix ambiguous warnings when compiled on Delphi.net and earlier versions of Delphi.win32
|
|
// complaining about possible unaffected result.
|
|
function RaiseOutOfBoundsError: Cardinal;
|
|
protected
|
|
procedure AssignDataTo(Dest: TJclAbstractContainerBase); override;
|
|
public
|
|
constructor Create(ACapacity: Integer); overload;
|
|
constructor Create(const ACollection: IJclCardinalCollection); overload;
|
|
destructor Destroy; override;
|
|
{ IJclPackable }
|
|
procedure SetCapacity(Value: Integer); override;
|
|
{ IJclCardinalCollection }
|
|
function Add(AValue: Cardinal): Boolean;
|
|
function AddAll(const ACollection: IJclCardinalCollection): Boolean;
|
|
procedure Clear;
|
|
function Contains(AValue: Cardinal): Boolean;
|
|
function ContainsAll(const ACollection: IJclCardinalCollection): Boolean;
|
|
function CollectionEquals(const ACollection: IJclCardinalCollection): Boolean;
|
|
function Extract(AValue: Cardinal): Boolean;
|
|
function ExtractAll(const ACollection: IJclCardinalCollection): Boolean;
|
|
function First: IJclCardinalIterator;
|
|
function IsEmpty: Boolean;
|
|
function Last: IJclCardinalIterator;
|
|
function Remove(AValue: Cardinal): Boolean;
|
|
function RemoveAll(const ACollection: IJclCardinalCollection): Boolean;
|
|
function RetainAll(const ACollection: IJclCardinalCollection): Boolean;
|
|
function Size: Integer;
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function GetEnumerator: IJclCardinalIterator;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
{ IJclCardinalList }
|
|
function Delete(Index: Integer): Cardinal;
|
|
function ExtractIndex(Index: Integer): Cardinal;
|
|
function GetValue(Index: Integer): Cardinal;
|
|
function IndexOf(AValue: Cardinal): Integer;
|
|
function Insert(Index: Integer; AValue: Cardinal): Boolean;
|
|
function InsertAll(Index: Integer; const ACollection: IJclCardinalCollection): Boolean;
|
|
function LastIndexOf(AValue: Cardinal): Integer;
|
|
procedure SetValue(Index: Integer; AValue: Cardinal);
|
|
function SubList(First, Count: Integer): IJclCardinalList;
|
|
end;
|
|
|
|
TJclCardinalArrayIterator = class(TJclAbstractIterator, IJclCardinalIterator, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable)
|
|
private
|
|
FCursor: Integer;
|
|
FStart: TItrStart;
|
|
FOwnList: IJclCardinalList;
|
|
protected
|
|
procedure AssignPropertiesTo(Dest: TJclAbstractIterator); override;
|
|
function CreateEmptyIterator: TJclAbstractIterator; override;
|
|
public
|
|
constructor Create(const AOwnList: IJclCardinalList; ACursor: Integer; AValid: Boolean; AStart: TItrStart);
|
|
{ IJclCardinalIterator }
|
|
function Add(AValue: Cardinal): Boolean;
|
|
procedure Extract;
|
|
function GetValue: Cardinal;
|
|
function HasNext: Boolean;
|
|
function HasPrevious: Boolean;
|
|
function Insert(AValue: Cardinal): Boolean;
|
|
function IteratorEquals(const AIterator: IJclCardinalIterator): Boolean;
|
|
function Next: Cardinal;
|
|
function NextIndex: Integer;
|
|
function Previous: Cardinal;
|
|
function PreviousIndex: Integer;
|
|
procedure Remove;
|
|
procedure Reset;
|
|
procedure SetValue(AValue: Cardinal);
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function MoveNext: Boolean;
|
|
property Current: Cardinal read GetValue;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
end;
|
|
|
|
TJclInt64ArrayList = class(TJclInt64AbstractContainer, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclInt64EqualityComparer,
|
|
IJclInt64Collection, IJclInt64List, IJclInt64Array)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
private
|
|
FElementData: TDynInt64Array;
|
|
// fix ambiguous warnings when compiled on Delphi.net and earlier versions of Delphi.win32
|
|
// complaining about possible unaffected result.
|
|
function RaiseOutOfBoundsError: Int64;
|
|
protected
|
|
procedure AssignDataTo(Dest: TJclAbstractContainerBase); override;
|
|
public
|
|
constructor Create(ACapacity: Integer); overload;
|
|
constructor Create(const ACollection: IJclInt64Collection); overload;
|
|
destructor Destroy; override;
|
|
{ IJclPackable }
|
|
procedure SetCapacity(Value: Integer); override;
|
|
{ IJclInt64Collection }
|
|
function Add(const AValue: Int64): Boolean;
|
|
function AddAll(const ACollection: IJclInt64Collection): Boolean;
|
|
procedure Clear;
|
|
function Contains(const AValue: Int64): Boolean;
|
|
function ContainsAll(const ACollection: IJclInt64Collection): Boolean;
|
|
function CollectionEquals(const ACollection: IJclInt64Collection): Boolean;
|
|
function Extract(const AValue: Int64): Boolean;
|
|
function ExtractAll(const ACollection: IJclInt64Collection): Boolean;
|
|
function First: IJclInt64Iterator;
|
|
function IsEmpty: Boolean;
|
|
function Last: IJclInt64Iterator;
|
|
function Remove(const AValue: Int64): Boolean;
|
|
function RemoveAll(const ACollection: IJclInt64Collection): Boolean;
|
|
function RetainAll(const ACollection: IJclInt64Collection): Boolean;
|
|
function Size: Integer;
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function GetEnumerator: IJclInt64Iterator;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
{ IJclInt64List }
|
|
function Delete(Index: Integer): Int64;
|
|
function ExtractIndex(Index: Integer): Int64;
|
|
function GetValue(Index: Integer): Int64;
|
|
function IndexOf(const AValue: Int64): Integer;
|
|
function Insert(Index: Integer; const AValue: Int64): Boolean;
|
|
function InsertAll(Index: Integer; const ACollection: IJclInt64Collection): Boolean;
|
|
function LastIndexOf(const AValue: Int64): Integer;
|
|
procedure SetValue(Index: Integer; const AValue: Int64);
|
|
function SubList(First, Count: Integer): IJclInt64List;
|
|
end;
|
|
|
|
TJclInt64ArrayIterator = class(TJclAbstractIterator, IJclInt64Iterator, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable)
|
|
private
|
|
FCursor: Integer;
|
|
FStart: TItrStart;
|
|
FOwnList: IJclInt64List;
|
|
protected
|
|
procedure AssignPropertiesTo(Dest: TJclAbstractIterator); override;
|
|
function CreateEmptyIterator: TJclAbstractIterator; override;
|
|
public
|
|
constructor Create(const AOwnList: IJclInt64List; ACursor: Integer; AValid: Boolean; AStart: TItrStart);
|
|
{ IJclInt64Iterator }
|
|
function Add(const AValue: Int64): Boolean;
|
|
procedure Extract;
|
|
function GetValue: Int64;
|
|
function HasNext: Boolean;
|
|
function HasPrevious: Boolean;
|
|
function Insert(const AValue: Int64): Boolean;
|
|
function IteratorEquals(const AIterator: IJclInt64Iterator): Boolean;
|
|
function Next: Int64;
|
|
function NextIndex: Integer;
|
|
function Previous: Int64;
|
|
function PreviousIndex: Integer;
|
|
procedure Remove;
|
|
procedure Reset;
|
|
procedure SetValue(const AValue: Int64);
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function MoveNext: Boolean;
|
|
property Current: Int64 read GetValue;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
end;
|
|
|
|
TJclPtrArrayList = class(TJclPtrAbstractContainer, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclPtrEqualityComparer,
|
|
IJclPtrCollection, IJclPtrList, IJclPtrArray)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
private
|
|
FElementData: TDynPointerArray;
|
|
// fix ambiguous warnings when compiled on Delphi.net and earlier versions of Delphi.win32
|
|
// complaining about possible unaffected result.
|
|
function RaiseOutOfBoundsError: Pointer;
|
|
protected
|
|
procedure AssignDataTo(Dest: TJclAbstractContainerBase); override;
|
|
public
|
|
constructor Create(ACapacity: Integer); overload;
|
|
constructor Create(const ACollection: IJclPtrCollection); overload;
|
|
destructor Destroy; override;
|
|
{ IJclPackable }
|
|
procedure SetCapacity(Value: Integer); override;
|
|
{ IJclPtrCollection }
|
|
function Add(APtr: Pointer): Boolean;
|
|
function AddAll(const ACollection: IJclPtrCollection): Boolean;
|
|
procedure Clear;
|
|
function Contains(APtr: Pointer): Boolean;
|
|
function ContainsAll(const ACollection: IJclPtrCollection): Boolean;
|
|
function CollectionEquals(const ACollection: IJclPtrCollection): Boolean;
|
|
function Extract(APtr: Pointer): Boolean;
|
|
function ExtractAll(const ACollection: IJclPtrCollection): Boolean;
|
|
function First: IJclPtrIterator;
|
|
function IsEmpty: Boolean;
|
|
function Last: IJclPtrIterator;
|
|
function Remove(APtr: Pointer): Boolean;
|
|
function RemoveAll(const ACollection: IJclPtrCollection): Boolean;
|
|
function RetainAll(const ACollection: IJclPtrCollection): Boolean;
|
|
function Size: Integer;
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function GetEnumerator: IJclPtrIterator;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
{ IJclPtrList }
|
|
function Delete(Index: Integer): Pointer;
|
|
function ExtractIndex(Index: Integer): Pointer;
|
|
function GetPointer(Index: Integer): Pointer;
|
|
function IndexOf(APtr: Pointer): Integer;
|
|
function Insert(Index: Integer; APtr: Pointer): Boolean;
|
|
function InsertAll(Index: Integer; const ACollection: IJclPtrCollection): Boolean;
|
|
function LastIndexOf(APtr: Pointer): Integer;
|
|
procedure SetPointer(Index: Integer; APtr: Pointer);
|
|
function SubList(First, Count: Integer): IJclPtrList;
|
|
end;
|
|
|
|
TJclPtrArrayIterator = class(TJclAbstractIterator, IJclPtrIterator, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable)
|
|
private
|
|
FCursor: Integer;
|
|
FStart: TItrStart;
|
|
FOwnList: IJclPtrList;
|
|
protected
|
|
procedure AssignPropertiesTo(Dest: TJclAbstractIterator); override;
|
|
function CreateEmptyIterator: TJclAbstractIterator; override;
|
|
public
|
|
constructor Create(const AOwnList: IJclPtrList; ACursor: Integer; AValid: Boolean; AStart: TItrStart);
|
|
{ IJclPtrIterator }
|
|
function Add(APtr: Pointer): Boolean;
|
|
procedure Extract;
|
|
function GetPointer: Pointer;
|
|
function HasNext: Boolean;
|
|
function HasPrevious: Boolean;
|
|
function Insert(APtr: Pointer): Boolean;
|
|
function IteratorEquals(const AIterator: IJclPtrIterator): Boolean;
|
|
function Next: Pointer;
|
|
function NextIndex: Integer;
|
|
function Previous: Pointer;
|
|
function PreviousIndex: Integer;
|
|
procedure Remove;
|
|
procedure Reset;
|
|
procedure SetPointer(APtr: Pointer);
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function MoveNext: Boolean;
|
|
property Current: Pointer read GetPointer;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
end;
|
|
|
|
TJclArrayList = class(TJclAbstractContainer, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclObjectOwner, IJclEqualityComparer,
|
|
IJclCollection, IJclList, IJclArray)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
private
|
|
FElementData: TDynObjectArray;
|
|
// fix ambiguous warnings when compiled on Delphi.net and earlier versions of Delphi.win32
|
|
// complaining about possible unaffected result.
|
|
function RaiseOutOfBoundsError: TObject;
|
|
protected
|
|
procedure AssignDataTo(Dest: TJclAbstractContainerBase); override;
|
|
public
|
|
constructor Create(ACapacity: Integer; AOwnsObjects: Boolean); overload;
|
|
constructor Create(const ACollection: IJclCollection; AOwnsObjects: Boolean); overload;
|
|
destructor Destroy; override;
|
|
{ IJclPackable }
|
|
procedure SetCapacity(Value: Integer); override;
|
|
{ IJclCollection }
|
|
function Add(AObject: TObject): Boolean;
|
|
function AddAll(const ACollection: IJclCollection): Boolean;
|
|
procedure Clear;
|
|
function Contains(AObject: TObject): Boolean;
|
|
function ContainsAll(const ACollection: IJclCollection): Boolean;
|
|
function CollectionEquals(const ACollection: IJclCollection): Boolean;
|
|
function Extract(AObject: TObject): Boolean;
|
|
function ExtractAll(const ACollection: IJclCollection): Boolean;
|
|
function First: IJclIterator;
|
|
function IsEmpty: Boolean;
|
|
function Last: IJclIterator;
|
|
function Remove(AObject: TObject): Boolean;
|
|
function RemoveAll(const ACollection: IJclCollection): Boolean;
|
|
function RetainAll(const ACollection: IJclCollection): Boolean;
|
|
function Size: Integer;
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function GetEnumerator: IJclIterator;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
{ IJclList }
|
|
function Delete(Index: Integer): TObject;
|
|
function ExtractIndex(Index: Integer): TObject;
|
|
function GetObject(Index: Integer): TObject;
|
|
function IndexOf(AObject: TObject): Integer;
|
|
function Insert(Index: Integer; AObject: TObject): Boolean;
|
|
function InsertAll(Index: Integer; const ACollection: IJclCollection): Boolean;
|
|
function LastIndexOf(AObject: TObject): Integer;
|
|
procedure SetObject(Index: Integer; AObject: TObject);
|
|
function SubList(First, Count: Integer): IJclList;
|
|
end;
|
|
|
|
TJclArrayIterator = class(TJclAbstractIterator, IJclIterator, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable)
|
|
private
|
|
FCursor: Integer;
|
|
FStart: TItrStart;
|
|
FOwnList: IJclList;
|
|
protected
|
|
procedure AssignPropertiesTo(Dest: TJclAbstractIterator); override;
|
|
function CreateEmptyIterator: TJclAbstractIterator; override;
|
|
public
|
|
constructor Create(const AOwnList: IJclList; ACursor: Integer; AValid: Boolean; AStart: TItrStart);
|
|
{ IJclIterator }
|
|
function Add(AObject: TObject): Boolean;
|
|
procedure Extract;
|
|
function GetObject: TObject;
|
|
function HasNext: Boolean;
|
|
function HasPrevious: Boolean;
|
|
function Insert(AObject: TObject): Boolean;
|
|
function IteratorEquals(const AIterator: IJclIterator): Boolean;
|
|
function Next: TObject;
|
|
function NextIndex: Integer;
|
|
function Previous: TObject;
|
|
function PreviousIndex: Integer;
|
|
procedure Remove;
|
|
procedure Reset;
|
|
procedure SetObject(AObject: TObject);
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function MoveNext: Boolean;
|
|
property Current: TObject read GetObject;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_GENERICS}
|
|
TJclArrayIterator<T> = class;
|
|
|
|
TJclArrayList<T> = class(TJclAbstractContainer<T>, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclItemOwner<T>, IJclEqualityComparer<T>,
|
|
IJclCollection<T>, IJclList<T>, IJclArray<T>)
|
|
protected
|
|
type
|
|
TDynArray = array of T;
|
|
TArrayIterator = TJclArrayIterator<T>;
|
|
procedure MoveArray(var List: TDynArray; FromIndex, ToIndex, Count: Integer);
|
|
private
|
|
FElementData: TDynArray;
|
|
// fix ambiguous warnings when compiled on Delphi.net and earlier versions of Delphi.win32
|
|
// complaining about possible unaffected result.
|
|
function RaiseOutOfBoundsError: T;
|
|
protected
|
|
procedure AssignDataTo(Dest: TJclAbstractContainerBase); override;
|
|
public
|
|
constructor Create(ACapacity: Integer; AOwnsItems: Boolean); overload;
|
|
constructor Create(const ACollection: IJclCollection<T>; AOwnsItems: Boolean); overload;
|
|
destructor Destroy; override;
|
|
{ IJclPackable }
|
|
procedure SetCapacity(Value: Integer); override;
|
|
{ IJclCollection<T> }
|
|
function Add(const AItem: T): Boolean;
|
|
function AddAll(const ACollection: IJclCollection<T>): Boolean;
|
|
procedure Clear;
|
|
function Contains(const AItem: T): Boolean;
|
|
function ContainsAll(const ACollection: IJclCollection<T>): Boolean;
|
|
function CollectionEquals(const ACollection: IJclCollection<T>): Boolean;
|
|
function Extract(const AItem: T): Boolean;
|
|
function ExtractAll(const ACollection: IJclCollection<T>): Boolean;
|
|
function First: IJclIterator<T>;
|
|
function IsEmpty: Boolean;
|
|
function Last: IJclIterator<T>;
|
|
function Remove(const AItem: T): Boolean;
|
|
function RemoveAll(const ACollection: IJclCollection<T>): Boolean;
|
|
function RetainAll(const ACollection: IJclCollection<T>): Boolean;
|
|
function Size: Integer;
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function GetEnumerator: IJclIterator<T>;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
{ IJclList<T> }
|
|
function Delete(Index: Integer): T;
|
|
function ExtractIndex(Index: Integer): T;
|
|
function GetItem(Index: Integer): T;
|
|
function IndexOf(const AItem: T): Integer;
|
|
function Insert(Index: Integer; const AItem: T): Boolean;
|
|
function InsertAll(Index: Integer; const ACollection: IJclCollection<T>): Boolean;
|
|
function LastIndexOf(const AItem: T): Integer;
|
|
procedure SetItem(Index: Integer; const AItem: T);
|
|
function SubList(First, Count: Integer): IJclList<T>;
|
|
end;
|
|
|
|
TJclArrayIterator<T> = class(TJclAbstractIterator, IJclIterator<T>, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable)
|
|
private
|
|
FCursor: Integer;
|
|
FStart: TItrStart;
|
|
FOwnList: IJclList<T>;
|
|
protected
|
|
procedure AssignPropertiesTo(Dest: TJclAbstractIterator); override;
|
|
function CreateEmptyIterator: TJclAbstractIterator; override;
|
|
public
|
|
constructor Create(const AOwnList: IJclList<T>; ACursor: Integer; AValid: Boolean; AStart: TItrStart);
|
|
{ IJclIterator<T> }
|
|
function Add(const AItem: T): Boolean;
|
|
procedure Extract;
|
|
function GetItem: T;
|
|
function HasNext: Boolean;
|
|
function HasPrevious: Boolean;
|
|
function Insert(const AItem: T): Boolean;
|
|
function IteratorEquals(const AIterator: IJclIterator<T>): Boolean;
|
|
function Next: T;
|
|
function NextIndex: Integer;
|
|
function Previous: T;
|
|
function PreviousIndex: Integer;
|
|
procedure Remove;
|
|
procedure Reset;
|
|
procedure SetItem(const AItem: T);
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function MoveNext: Boolean;
|
|
property Current: T read GetItem;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
end;
|
|
|
|
// E = External helper to compare items for equality
|
|
// GetHashCode is not used
|
|
TJclArrayListE<T> = class(TJclArrayList<T>, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclItemOwner<T>, IJclEqualityComparer<T>,
|
|
IJclCollection<T>, IJclList<T>, IJclArray<T>)
|
|
private
|
|
FEqualityComparer: IJclEqualityComparer<T>;
|
|
protected
|
|
procedure AssignPropertiesTo(Dest: TJclAbstractContainerBase); override;
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
public
|
|
constructor Create(const AEqualityComparer: IJclEqualityComparer<T>; ACapacity: Integer; AOwnsItems: Boolean); overload;
|
|
constructor Create(const AEqualityComparer: IJclEqualityComparer<T>; const ACollection: IJclCollection<T>; AOwnsItems: Boolean); overload;
|
|
{ IJclEqualityComparer<T> }
|
|
function ItemsEqual(const A, B: T): Boolean; override;
|
|
property EqualityComparer: IJclEqualityComparer<T> read FEqualityComparer write FEqualityComparer;
|
|
end;
|
|
|
|
// F = Function to compare items for equality
|
|
TJclArrayListF<T> = class(TJclArrayList<T>, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclItemOwner<T>, IJclEqualityComparer<T>,
|
|
IJclCollection<T>, IJclList<T>, IJclArray<T>)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
public
|
|
constructor Create(const AEqualityCompare: TEqualityCompare<T>; ACapacity: Integer; AOwnsItems: Boolean); overload;
|
|
constructor Create(const AEqualityCompare: TEqualityCompare<T>; const ACollection: IJclCollection<T>; AOwnsItems: Boolean); overload;
|
|
end;
|
|
|
|
// I = Items can compare themselves to others
|
|
TJclArrayListI<T: IEquatable<T>> = class(TJclArrayList<T>, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclItemOwner<T>, IJclEqualityComparer<T>,
|
|
IJclCollection<T>, IJclList<T>, IJclArray<T>)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
public
|
|
{ IJclEqualityComparer<T> }
|
|
function ItemsEqual(const A, B: T): Boolean; override;
|
|
end;
|
|
|
|
{$ENDIF SUPPORTS_GENERICS}
|
|
|
|
{$IFDEF UNITVERSIONING}
|
|
const
|
|
UnitVersioning: TUnitVersionInfo = (
|
|
RCSfile: '$URL: https://jcl.svn.sourceforge.net/svnroot/jcl/tags/JCL-2.1-Build3536/jcl/source/common/JclArrayLists.pas $';
|
|
Revision: '$Revision: 3053 $';
|
|
Date: '$Date: 2009-10-22 18:22:16 +0200 (jeu., 22 oct. 2009) $';
|
|
LogPath: 'JCL\source\common';
|
|
Extra: '';
|
|
Data: nil
|
|
);
|
|
{$ENDIF UNITVERSIONING}
|
|
|
|
implementation
|
|
|
|
uses
|
|
SysUtils;
|
|
|
|
//=== { TJclIntfArrayList } ======================================================
|
|
|
|
constructor TJclIntfArrayList.Create(ACapacity: Integer);
|
|
begin
|
|
inherited Create();
|
|
SetCapacity(ACapacity);
|
|
end;
|
|
|
|
constructor TJclIntfArrayList.Create(const ACollection: IJclIntfCollection);
|
|
begin
|
|
inherited Create();
|
|
if ACollection = nil then
|
|
raise EJclNoCollectionError.Create;
|
|
SetCapacity(ACollection.Size);
|
|
AddAll(ACollection);
|
|
end;
|
|
|
|
destructor TJclIntfArrayList.Destroy;
|
|
begin
|
|
FReadOnly := False;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJclIntfArrayList.Add(const AInterface: IInterface): Boolean;
|
|
var
|
|
Index: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FAllowDefaultElements or not ItemsEqual(AInterface, nil);
|
|
if Result then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for Index := 0 to FSize - 1 do
|
|
if ItemsEqual(AInterface, FElementData[Index]) then
|
|
begin
|
|
Result := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
if FSize = FCapacity then
|
|
AutoGrow;
|
|
Result := FSize < FCapacity;
|
|
if Result then
|
|
begin
|
|
FElementData[FSize] := AInterface;
|
|
Inc(FSize);
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntfArrayList.AddAll(const ACollection: IJclIntfCollection): Boolean;
|
|
var
|
|
It: IJclIntfIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Add(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclIntfArrayList.AssignDataTo(Dest: TJclAbstractContainerBase);
|
|
var
|
|
ADest: TJclIntfArrayList;
|
|
ACollection: IJclIntfCollection;
|
|
begin
|
|
inherited AssignDataTo(Dest);
|
|
if Dest is TJclIntfArrayList then
|
|
begin
|
|
ADest := TJclIntfArrayList(Dest);
|
|
ADest.Clear;
|
|
ADest.AddAll(Self);
|
|
end
|
|
else
|
|
if Supports(IInterface(Dest), IJclIntfCollection, ACollection) then
|
|
begin
|
|
ACollection.Clear;
|
|
ACollection.AddAll(Self);
|
|
end;
|
|
end;
|
|
|
|
procedure TJclIntfArrayList.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
for I := 0 to FSize - 1 do
|
|
FreeObject(FElementData[I]);
|
|
FSize := 0;
|
|
AutoPack;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntfArrayList.CollectionEquals(const ACollection: IJclIntfCollection): Boolean;
|
|
var
|
|
I: Integer;
|
|
It: IJclIntfIterator;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$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 not ItemsEqual(FElementData[I], It.Next) then
|
|
Exit;
|
|
Result := True;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntfArrayList.Contains(const AInterface: IInterface): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AInterface) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntfArrayList.ContainsAll(const ACollection: IJclIntfCollection): Boolean;
|
|
var
|
|
It: IJclIntfIterator;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := True;
|
|
if ACollection = nil then
|
|
Exit;
|
|
It := ACollection.First;
|
|
while Result and It.HasNext do
|
|
Result := Contains(It.Next);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntfArrayList.Delete(Index: Integer): IInterface;
|
|
var
|
|
Extracted: IInterface;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Extracted := ExtractIndex(Index);
|
|
Result := FreeObject(Extracted);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntfArrayList.Extract(const AInterface: IInterface): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
for I := FSize - 1 downto 0 do
|
|
if ItemsEqual(FElementData[I], AInterface) then
|
|
begin
|
|
FElementData[I] := nil;
|
|
if I < (FSize - 1) then
|
|
MoveArray(FElementData, I + 1, I, FSize - I);
|
|
Dec(FSize);
|
|
Result := True;
|
|
if FRemoveSingleElement then
|
|
Break;
|
|
end;
|
|
AutoPack;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntfArrayList.ExtractAll(const ACollection: IJclIntfCollection): Boolean;
|
|
var
|
|
It: IJclIntfIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Extract(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntfArrayList.ExtractIndex(Index: Integer): IInterface;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (Index >= 0) and (Index < FSize) then
|
|
begin
|
|
Result := FElementData[Index];
|
|
if Index < (FSize - 1) then
|
|
MoveArray(FElementData, Index + 1, Index, FSize - Index);
|
|
Dec(FSize);
|
|
AutoPack;
|
|
end
|
|
else
|
|
Result := RaiseOutOfBoundsError;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntfArrayList.First: IJclIntfIterator;
|
|
begin
|
|
Result := TJclIntfArrayIterator.Create(Self, 0, False, isFirst);
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function TJclIntfArrayList.GetEnumerator: IJclIntfIterator;
|
|
begin
|
|
Result := TJclIntfArrayIterator.Create(Self, 0, False, isFirst);
|
|
end;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
|
|
function TJclIntfArrayList.GetObject(Index: Integer): IInterface;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := nil;
|
|
if (Index >= 0) and (Index < FSize) then
|
|
Result := FElementData[Index]
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create(IntToStr(Index));
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntfArrayList.IndexOf(const AInterface: IInterface): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := -1;
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AInterface) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntfArrayList.Insert(Index: Integer; const AInterface: IInterface): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FAllowDefaultElements or not ItemsEqual(AInterface, nil);
|
|
|
|
if (Index < 0) or (Index > FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
|
|
if Result then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(AInterface, FElementData[I]) then
|
|
begin
|
|
Result := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
if FSize = FCapacity then
|
|
AutoGrow;
|
|
Result := FSize < FCapacity;
|
|
if Result then
|
|
begin
|
|
if Index < FSize then
|
|
MoveArray(FElementData, Index, Index + 1, FSize - Index);
|
|
FElementData[Index] := AInterface;
|
|
Inc(FSize);
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntfArrayList.InsertAll(Index: Integer; const ACollection: IJclIntfCollection): Boolean;
|
|
var
|
|
It: IJclIntfIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if (Index < 0) or (Index > FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
if ACollection = nil then
|
|
Exit;
|
|
|
|
Result := True;
|
|
It := ACollection.Last;
|
|
while It.HasPrevious do
|
|
Result := Insert(Index, It.Previous) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntfArrayList.IsEmpty: Boolean;
|
|
begin
|
|
Result := FSize = 0;
|
|
end;
|
|
|
|
function TJclIntfArrayList.Last: IJclIntfIterator;
|
|
begin
|
|
Result := TJclIntfArrayIterator.Create(Self, FSize - 1, False, isLast);
|
|
end;
|
|
|
|
function TJclIntfArrayList.LastIndexOf(const AInterface: IInterface): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := -1;
|
|
for I := FSize - 1 downto 0 do
|
|
if ItemsEqual(FElementData[I], AInterface) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntfArrayList.RaiseOutOfBoundsError: IInterface;
|
|
begin
|
|
raise EJclOutOfBoundsError.Create;
|
|
end;
|
|
|
|
function TJclIntfArrayList.Remove(const AInterface: IInterface): Boolean;
|
|
var
|
|
Extracted: IInterface;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := Extract(AInterface);
|
|
if Result then
|
|
begin
|
|
Extracted := AInterface;
|
|
FreeObject(Extracted);
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntfArrayList.RemoveAll(const ACollection: IJclIntfCollection): Boolean;
|
|
var
|
|
It: IJclIntfIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Remove(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntfArrayList.RetainAll(const ACollection: IJclIntfCollection): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
for I := FSize - 1 downto 0 do
|
|
if not ACollection.Contains(FElementData[I]) then
|
|
Delete(I);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclIntfArrayList.SetCapacity(Value: Integer);
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if Value >= FSize then
|
|
begin
|
|
SetLength(FElementData, Value);
|
|
inherited SetCapacity(Value);
|
|
end
|
|
else
|
|
raise EJclOutOfBoundsError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclIntfArrayList.SetObject(Index: Integer; const AInterface: IInterface);
|
|
var
|
|
ReplaceItem: Boolean;
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (Index < 0) or (Index >= FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
ReplaceItem := FAllowDefaultElements or not ItemsEqual(AInterface, nil);
|
|
if ReplaceItem then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AInterface) then
|
|
begin
|
|
ReplaceItem := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
if ReplaceItem then
|
|
begin
|
|
FreeObject(FElementData[Index]);
|
|
FElementData[Index] := AInterface;
|
|
end;
|
|
end;
|
|
if not ReplaceItem then
|
|
Delete(Index);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntfArrayList.Size: Integer;
|
|
begin
|
|
Result := FSize;
|
|
end;
|
|
|
|
function TJclIntfArrayList.SubList(First, Count: Integer): IJclIntfList;
|
|
var
|
|
I: Integer;
|
|
Last: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Last := First + Count - 1;
|
|
if Last >= FSize then
|
|
Last := FSize - 1;
|
|
Result := CreateEmptyContainer as IJclIntfList;
|
|
for I := First to Last do
|
|
Result.Add(FElementData[I]);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntfArrayList.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclIntfArrayList.Create(FSize);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
//=== { TJclIntfArrayIterator } ===============================================================
|
|
|
|
constructor TJclIntfArrayIterator.Create(const AOwnList: IJclIntfList; ACursor: Integer; AValid: Boolean; AStart: TItrStart);
|
|
begin
|
|
inherited Create(AValid);
|
|
FOwnList := AOwnList;
|
|
FStart := AStart;
|
|
FCursor := ACursor;
|
|
end;
|
|
|
|
function TJclIntfArrayIterator.Add(const AInterface: IInterface): Boolean;
|
|
begin
|
|
Result := FOwnList.Add(AInterface);
|
|
end;
|
|
|
|
procedure TJclIntfArrayIterator.AssignPropertiesTo(Dest: TJclAbstractIterator);
|
|
var
|
|
ADest: TJclIntfArrayIterator;
|
|
begin
|
|
inherited AssignPropertiesTo(Dest);
|
|
if Dest is TJclIntfArrayIterator then
|
|
begin
|
|
ADest := TJclIntfArrayIterator(Dest);
|
|
ADest.FOwnList := FOwnList;
|
|
ADest.FCursor := FCursor;
|
|
ADest.FStart := FStart;
|
|
end;
|
|
end;
|
|
|
|
function TJclIntfArrayIterator.CreateEmptyIterator: TJclAbstractIterator;
|
|
begin
|
|
Result := TJclIntfArrayIterator.Create(FOwnList, FCursor, Valid, FStart);
|
|
end;
|
|
|
|
procedure TJclIntfArrayIterator.Extract;
|
|
begin
|
|
CheckValid;
|
|
Valid := False;
|
|
FOwnList.ExtractIndex(FCursor);
|
|
end;
|
|
|
|
function TJclIntfArrayIterator.GetObject: IInterface;
|
|
begin
|
|
CheckValid;
|
|
Result := FOwnList.GetObject(FCursor);
|
|
end;
|
|
|
|
function TJclIntfArrayIterator.HasNext: Boolean;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor < (FOwnList.Size - 1)
|
|
else
|
|
Result := FCursor < FOwnList.Size;
|
|
end;
|
|
|
|
function TJclIntfArrayIterator.HasPrevious: Boolean;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor > 0
|
|
else
|
|
Result := FCursor >= 0;
|
|
end;
|
|
|
|
function TJclIntfArrayIterator.Insert(const AInterface: IInterface): Boolean;
|
|
begin
|
|
CheckValid;
|
|
Result := FOwnList.Insert(FCursor, AInterface);
|
|
end;
|
|
|
|
function TJclIntfArrayIterator.IteratorEquals(const AIterator: IJclIntfIterator): Boolean;
|
|
var
|
|
Obj: TObject;
|
|
ItrObj: TJclIntfArrayIterator;
|
|
begin
|
|
Result := False;
|
|
if AIterator = nil then
|
|
Exit;
|
|
Obj := AIterator.GetIteratorReference;
|
|
if Obj is TJclIntfArrayIterator then
|
|
begin
|
|
ItrObj := TJclIntfArrayIterator(Obj);
|
|
Result := (FOwnList = ItrObj.FOwnList) and (FCursor = ItrObj.FCursor) and (Valid = ItrObj.Valid);
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function TJclIntfArrayIterator.MoveNext: Boolean;
|
|
begin
|
|
if Valid then
|
|
Inc(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FCursor < FOwnList.Size;
|
|
end;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
|
|
function TJclIntfArrayIterator.Next: IInterface;
|
|
begin
|
|
if Valid then
|
|
Inc(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FOwnList.GetObject(FCursor);
|
|
end;
|
|
|
|
function TJclIntfArrayIterator.NextIndex: Integer;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor + 1
|
|
else
|
|
Result := FCursor;
|
|
end;
|
|
|
|
function TJclIntfArrayIterator.Previous: IInterface;
|
|
begin
|
|
if Valid then
|
|
Dec(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FOwnList.GetObject(FCursor);
|
|
end;
|
|
|
|
function TJclIntfArrayIterator.PreviousIndex: Integer;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor - 1
|
|
else
|
|
Result := FCursor;
|
|
end;
|
|
|
|
procedure TJclIntfArrayIterator.Remove;
|
|
begin
|
|
CheckValid;
|
|
Valid := False;
|
|
FOwnList.Delete(FCursor);
|
|
end;
|
|
|
|
procedure TJclIntfArrayIterator.Reset;
|
|
begin
|
|
Valid := False;
|
|
case FStart of
|
|
isFirst:
|
|
FCursor := 0;
|
|
isLast:
|
|
FCursor := FOwnList.Size - 1;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclIntfArrayIterator.SetObject(const AInterface: IInterface);
|
|
begin
|
|
CheckValid;
|
|
FOwnList.SetObject(FCursor, AInterface);
|
|
end;
|
|
|
|
//=== { TJclAnsiStrArrayList } ======================================================
|
|
|
|
constructor TJclAnsiStrArrayList.Create(ACapacity: Integer);
|
|
begin
|
|
inherited Create();
|
|
SetCapacity(ACapacity);
|
|
end;
|
|
|
|
constructor TJclAnsiStrArrayList.Create(const ACollection: IJclAnsiStrCollection);
|
|
begin
|
|
inherited Create();
|
|
if ACollection = nil then
|
|
raise EJclNoCollectionError.Create;
|
|
SetCapacity(ACollection.Size);
|
|
AddAll(ACollection);
|
|
end;
|
|
|
|
destructor TJclAnsiStrArrayList.Destroy;
|
|
begin
|
|
FReadOnly := False;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJclAnsiStrArrayList.Add(const AString: AnsiString): Boolean;
|
|
var
|
|
Index: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FAllowDefaultElements or not ItemsEqual(AString, '');
|
|
if Result then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for Index := 0 to FSize - 1 do
|
|
if ItemsEqual(AString, FElementData[Index]) then
|
|
begin
|
|
Result := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
if FSize = FCapacity then
|
|
AutoGrow;
|
|
Result := FSize < FCapacity;
|
|
if Result then
|
|
begin
|
|
FElementData[FSize] := AString;
|
|
Inc(FSize);
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclAnsiStrArrayList.AddAll(const ACollection: IJclAnsiStrCollection): Boolean;
|
|
var
|
|
It: IJclAnsiStrIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Add(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclAnsiStrArrayList.AssignDataTo(Dest: TJclAbstractContainerBase);
|
|
var
|
|
ADest: TJclAnsiStrArrayList;
|
|
ACollection: IJclAnsiStrCollection;
|
|
begin
|
|
inherited AssignDataTo(Dest);
|
|
if Dest is TJclAnsiStrArrayList then
|
|
begin
|
|
ADest := TJclAnsiStrArrayList(Dest);
|
|
ADest.Clear;
|
|
ADest.AddAll(Self);
|
|
end
|
|
else
|
|
if Supports(IInterface(Dest), IJclAnsiStrCollection, ACollection) then
|
|
begin
|
|
ACollection.Clear;
|
|
ACollection.AddAll(Self);
|
|
end;
|
|
end;
|
|
|
|
procedure TJclAnsiStrArrayList.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
for I := 0 to FSize - 1 do
|
|
FreeString(FElementData[I]);
|
|
FSize := 0;
|
|
AutoPack;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclAnsiStrArrayList.CollectionEquals(const ACollection: IJclAnsiStrCollection): Boolean;
|
|
var
|
|
I: Integer;
|
|
It: IJclAnsiStrIterator;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$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 not ItemsEqual(FElementData[I], It.Next) then
|
|
Exit;
|
|
Result := True;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclAnsiStrArrayList.Contains(const AString: AnsiString): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AString) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclAnsiStrArrayList.ContainsAll(const ACollection: IJclAnsiStrCollection): Boolean;
|
|
var
|
|
It: IJclAnsiStrIterator;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := True;
|
|
if ACollection = nil then
|
|
Exit;
|
|
It := ACollection.First;
|
|
while Result and It.HasNext do
|
|
Result := Contains(It.Next);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclAnsiStrArrayList.Delete(Index: Integer): AnsiString;
|
|
var
|
|
Extracted: AnsiString;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Extracted := ExtractIndex(Index);
|
|
Result := FreeString(Extracted);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclAnsiStrArrayList.Extract(const AString: AnsiString): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
for I := FSize - 1 downto 0 do
|
|
if ItemsEqual(FElementData[I], AString) then
|
|
begin
|
|
FElementData[I] := '';
|
|
if I < (FSize - 1) then
|
|
MoveArray(FElementData, I + 1, I, FSize - I);
|
|
Dec(FSize);
|
|
Result := True;
|
|
if FRemoveSingleElement then
|
|
Break;
|
|
end;
|
|
AutoPack;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclAnsiStrArrayList.ExtractAll(const ACollection: IJclAnsiStrCollection): Boolean;
|
|
var
|
|
It: IJclAnsiStrIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Extract(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclAnsiStrArrayList.ExtractIndex(Index: Integer): AnsiString;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (Index >= 0) and (Index < FSize) then
|
|
begin
|
|
Result := FElementData[Index];
|
|
if Index < (FSize - 1) then
|
|
MoveArray(FElementData, Index + 1, Index, FSize - Index);
|
|
Dec(FSize);
|
|
AutoPack;
|
|
end
|
|
else
|
|
Result := RaiseOutOfBoundsError;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclAnsiStrArrayList.First: IJclAnsiStrIterator;
|
|
begin
|
|
Result := TJclAnsiStrArrayIterator.Create(Self, 0, False, isFirst);
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function TJclAnsiStrArrayList.GetEnumerator: IJclAnsiStrIterator;
|
|
begin
|
|
Result := TJclAnsiStrArrayIterator.Create(Self, 0, False, isFirst);
|
|
end;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
|
|
function TJclAnsiStrArrayList.GetString(Index: Integer): AnsiString;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := '';
|
|
if (Index >= 0) and (Index < FSize) then
|
|
Result := FElementData[Index]
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create(IntToStr(Index));
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclAnsiStrArrayList.IndexOf(const AString: AnsiString): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := -1;
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AString) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclAnsiStrArrayList.Insert(Index: Integer; const AString: AnsiString): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FAllowDefaultElements or not ItemsEqual(AString, '');
|
|
|
|
if (Index < 0) or (Index > FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
|
|
if Result then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(AString, FElementData[I]) then
|
|
begin
|
|
Result := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
if FSize = FCapacity then
|
|
AutoGrow;
|
|
Result := FSize < FCapacity;
|
|
if Result then
|
|
begin
|
|
if Index < FSize then
|
|
MoveArray(FElementData, Index, Index + 1, FSize - Index);
|
|
FElementData[Index] := AString;
|
|
Inc(FSize);
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclAnsiStrArrayList.InsertAll(Index: Integer; const ACollection: IJclAnsiStrCollection): Boolean;
|
|
var
|
|
It: IJclAnsiStrIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if (Index < 0) or (Index > FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
if ACollection = nil then
|
|
Exit;
|
|
|
|
Result := True;
|
|
It := ACollection.Last;
|
|
while It.HasPrevious do
|
|
Result := Insert(Index, It.Previous) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclAnsiStrArrayList.IsEmpty: Boolean;
|
|
begin
|
|
Result := FSize = 0;
|
|
end;
|
|
|
|
function TJclAnsiStrArrayList.Last: IJclAnsiStrIterator;
|
|
begin
|
|
Result := TJclAnsiStrArrayIterator.Create(Self, FSize - 1, False, isLast);
|
|
end;
|
|
|
|
function TJclAnsiStrArrayList.LastIndexOf(const AString: AnsiString): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := -1;
|
|
for I := FSize - 1 downto 0 do
|
|
if ItemsEqual(FElementData[I], AString) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclAnsiStrArrayList.RaiseOutOfBoundsError: AnsiString;
|
|
begin
|
|
raise EJclOutOfBoundsError.Create;
|
|
end;
|
|
|
|
function TJclAnsiStrArrayList.Remove(const AString: AnsiString): Boolean;
|
|
var
|
|
Extracted: AnsiString;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := Extract(AString);
|
|
if Result then
|
|
begin
|
|
Extracted := AString;
|
|
FreeString(Extracted);
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclAnsiStrArrayList.RemoveAll(const ACollection: IJclAnsiStrCollection): Boolean;
|
|
var
|
|
It: IJclAnsiStrIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Remove(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclAnsiStrArrayList.RetainAll(const ACollection: IJclAnsiStrCollection): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
for I := FSize - 1 downto 0 do
|
|
if not ACollection.Contains(FElementData[I]) then
|
|
Delete(I);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclAnsiStrArrayList.SetCapacity(Value: Integer);
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if Value >= FSize then
|
|
begin
|
|
SetLength(FElementData, Value);
|
|
inherited SetCapacity(Value);
|
|
end
|
|
else
|
|
raise EJclOutOfBoundsError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclAnsiStrArrayList.SetString(Index: Integer; const AString: AnsiString);
|
|
var
|
|
ReplaceItem: Boolean;
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (Index < 0) or (Index >= FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
ReplaceItem := FAllowDefaultElements or not ItemsEqual(AString, '');
|
|
if ReplaceItem then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AString) then
|
|
begin
|
|
ReplaceItem := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
if ReplaceItem then
|
|
begin
|
|
FreeString(FElementData[Index]);
|
|
FElementData[Index] := AString;
|
|
end;
|
|
end;
|
|
if not ReplaceItem then
|
|
Delete(Index);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclAnsiStrArrayList.Size: Integer;
|
|
begin
|
|
Result := FSize;
|
|
end;
|
|
|
|
function TJclAnsiStrArrayList.SubList(First, Count: Integer): IJclAnsiStrList;
|
|
var
|
|
I: Integer;
|
|
Last: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Last := First + Count - 1;
|
|
if Last >= FSize then
|
|
Last := FSize - 1;
|
|
Result := CreateEmptyContainer as IJclAnsiStrList;
|
|
for I := First to Last do
|
|
Result.Add(FElementData[I]);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclAnsiStrArrayList.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclAnsiStrArrayList.Create(FSize);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
//=== { TJclAnsiStrArrayIterator } ===============================================================
|
|
|
|
constructor TJclAnsiStrArrayIterator.Create(const AOwnList: IJclAnsiStrList; ACursor: Integer; AValid: Boolean; AStart: TItrStart);
|
|
begin
|
|
inherited Create(AValid);
|
|
FOwnList := AOwnList;
|
|
FStart := AStart;
|
|
FCursor := ACursor;
|
|
end;
|
|
|
|
function TJclAnsiStrArrayIterator.Add(const AString: AnsiString): Boolean;
|
|
begin
|
|
Result := FOwnList.Add(AString);
|
|
end;
|
|
|
|
procedure TJclAnsiStrArrayIterator.AssignPropertiesTo(Dest: TJclAbstractIterator);
|
|
var
|
|
ADest: TJclAnsiStrArrayIterator;
|
|
begin
|
|
inherited AssignPropertiesTo(Dest);
|
|
if Dest is TJclAnsiStrArrayIterator then
|
|
begin
|
|
ADest := TJclAnsiStrArrayIterator(Dest);
|
|
ADest.FOwnList := FOwnList;
|
|
ADest.FCursor := FCursor;
|
|
ADest.FStart := FStart;
|
|
end;
|
|
end;
|
|
|
|
function TJclAnsiStrArrayIterator.CreateEmptyIterator: TJclAbstractIterator;
|
|
begin
|
|
Result := TJclAnsiStrArrayIterator.Create(FOwnList, FCursor, Valid, FStart);
|
|
end;
|
|
|
|
procedure TJclAnsiStrArrayIterator.Extract;
|
|
begin
|
|
CheckValid;
|
|
Valid := False;
|
|
FOwnList.ExtractIndex(FCursor);
|
|
end;
|
|
|
|
function TJclAnsiStrArrayIterator.GetString: AnsiString;
|
|
begin
|
|
CheckValid;
|
|
Result := FOwnList.GetString(FCursor);
|
|
end;
|
|
|
|
function TJclAnsiStrArrayIterator.HasNext: Boolean;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor < (FOwnList.Size - 1)
|
|
else
|
|
Result := FCursor < FOwnList.Size;
|
|
end;
|
|
|
|
function TJclAnsiStrArrayIterator.HasPrevious: Boolean;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor > 0
|
|
else
|
|
Result := FCursor >= 0;
|
|
end;
|
|
|
|
function TJclAnsiStrArrayIterator.Insert(const AString: AnsiString): Boolean;
|
|
begin
|
|
CheckValid;
|
|
Result := FOwnList.Insert(FCursor, AString);
|
|
end;
|
|
|
|
function TJclAnsiStrArrayIterator.IteratorEquals(const AIterator: IJclAnsiStrIterator): Boolean;
|
|
var
|
|
Obj: TObject;
|
|
ItrObj: TJclAnsiStrArrayIterator;
|
|
begin
|
|
Result := False;
|
|
if AIterator = nil then
|
|
Exit;
|
|
Obj := AIterator.GetIteratorReference;
|
|
if Obj is TJclAnsiStrArrayIterator then
|
|
begin
|
|
ItrObj := TJclAnsiStrArrayIterator(Obj);
|
|
Result := (FOwnList = ItrObj.FOwnList) and (FCursor = ItrObj.FCursor) and (Valid = ItrObj.Valid);
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function TJclAnsiStrArrayIterator.MoveNext: Boolean;
|
|
begin
|
|
if Valid then
|
|
Inc(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FCursor < FOwnList.Size;
|
|
end;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
|
|
function TJclAnsiStrArrayIterator.Next: AnsiString;
|
|
begin
|
|
if Valid then
|
|
Inc(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FOwnList.GetString(FCursor);
|
|
end;
|
|
|
|
function TJclAnsiStrArrayIterator.NextIndex: Integer;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor + 1
|
|
else
|
|
Result := FCursor;
|
|
end;
|
|
|
|
function TJclAnsiStrArrayIterator.Previous: AnsiString;
|
|
begin
|
|
if Valid then
|
|
Dec(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FOwnList.GetString(FCursor);
|
|
end;
|
|
|
|
function TJclAnsiStrArrayIterator.PreviousIndex: Integer;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor - 1
|
|
else
|
|
Result := FCursor;
|
|
end;
|
|
|
|
procedure TJclAnsiStrArrayIterator.Remove;
|
|
begin
|
|
CheckValid;
|
|
Valid := False;
|
|
FOwnList.Delete(FCursor);
|
|
end;
|
|
|
|
procedure TJclAnsiStrArrayIterator.Reset;
|
|
begin
|
|
Valid := False;
|
|
case FStart of
|
|
isFirst:
|
|
FCursor := 0;
|
|
isLast:
|
|
FCursor := FOwnList.Size - 1;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclAnsiStrArrayIterator.SetString(const AString: AnsiString);
|
|
begin
|
|
CheckValid;
|
|
FOwnList.SetString(FCursor, AString);
|
|
end;
|
|
|
|
//=== { TJclWideStrArrayList } ======================================================
|
|
|
|
constructor TJclWideStrArrayList.Create(ACapacity: Integer);
|
|
begin
|
|
inherited Create();
|
|
SetCapacity(ACapacity);
|
|
end;
|
|
|
|
constructor TJclWideStrArrayList.Create(const ACollection: IJclWideStrCollection);
|
|
begin
|
|
inherited Create();
|
|
if ACollection = nil then
|
|
raise EJclNoCollectionError.Create;
|
|
SetCapacity(ACollection.Size);
|
|
AddAll(ACollection);
|
|
end;
|
|
|
|
destructor TJclWideStrArrayList.Destroy;
|
|
begin
|
|
FReadOnly := False;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJclWideStrArrayList.Add(const AString: WideString): Boolean;
|
|
var
|
|
Index: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FAllowDefaultElements or not ItemsEqual(AString, '');
|
|
if Result then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for Index := 0 to FSize - 1 do
|
|
if ItemsEqual(AString, FElementData[Index]) then
|
|
begin
|
|
Result := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
if FSize = FCapacity then
|
|
AutoGrow;
|
|
Result := FSize < FCapacity;
|
|
if Result then
|
|
begin
|
|
FElementData[FSize] := AString;
|
|
Inc(FSize);
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclWideStrArrayList.AddAll(const ACollection: IJclWideStrCollection): Boolean;
|
|
var
|
|
It: IJclWideStrIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Add(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclWideStrArrayList.AssignDataTo(Dest: TJclAbstractContainerBase);
|
|
var
|
|
ADest: TJclWideStrArrayList;
|
|
ACollection: IJclWideStrCollection;
|
|
begin
|
|
inherited AssignDataTo(Dest);
|
|
if Dest is TJclWideStrArrayList then
|
|
begin
|
|
ADest := TJclWideStrArrayList(Dest);
|
|
ADest.Clear;
|
|
ADest.AddAll(Self);
|
|
end
|
|
else
|
|
if Supports(IInterface(Dest), IJclWideStrCollection, ACollection) then
|
|
begin
|
|
ACollection.Clear;
|
|
ACollection.AddAll(Self);
|
|
end;
|
|
end;
|
|
|
|
procedure TJclWideStrArrayList.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
for I := 0 to FSize - 1 do
|
|
FreeString(FElementData[I]);
|
|
FSize := 0;
|
|
AutoPack;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclWideStrArrayList.CollectionEquals(const ACollection: IJclWideStrCollection): Boolean;
|
|
var
|
|
I: Integer;
|
|
It: IJclWideStrIterator;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$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 not ItemsEqual(FElementData[I], It.Next) then
|
|
Exit;
|
|
Result := True;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclWideStrArrayList.Contains(const AString: WideString): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AString) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclWideStrArrayList.ContainsAll(const ACollection: IJclWideStrCollection): Boolean;
|
|
var
|
|
It: IJclWideStrIterator;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := True;
|
|
if ACollection = nil then
|
|
Exit;
|
|
It := ACollection.First;
|
|
while Result and It.HasNext do
|
|
Result := Contains(It.Next);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclWideStrArrayList.Delete(Index: Integer): WideString;
|
|
var
|
|
Extracted: WideString;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Extracted := ExtractIndex(Index);
|
|
Result := FreeString(Extracted);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclWideStrArrayList.Extract(const AString: WideString): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
for I := FSize - 1 downto 0 do
|
|
if ItemsEqual(FElementData[I], AString) then
|
|
begin
|
|
FElementData[I] := '';
|
|
if I < (FSize - 1) then
|
|
MoveArray(FElementData, I + 1, I, FSize - I);
|
|
Dec(FSize);
|
|
Result := True;
|
|
if FRemoveSingleElement then
|
|
Break;
|
|
end;
|
|
AutoPack;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclWideStrArrayList.ExtractAll(const ACollection: IJclWideStrCollection): Boolean;
|
|
var
|
|
It: IJclWideStrIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Extract(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclWideStrArrayList.ExtractIndex(Index: Integer): WideString;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (Index >= 0) and (Index < FSize) then
|
|
begin
|
|
Result := FElementData[Index];
|
|
if Index < (FSize - 1) then
|
|
MoveArray(FElementData, Index + 1, Index, FSize - Index);
|
|
Dec(FSize);
|
|
AutoPack;
|
|
end
|
|
else
|
|
Result := RaiseOutOfBoundsError;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclWideStrArrayList.First: IJclWideStrIterator;
|
|
begin
|
|
Result := TJclWideStrArrayIterator.Create(Self, 0, False, isFirst);
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function TJclWideStrArrayList.GetEnumerator: IJclWideStrIterator;
|
|
begin
|
|
Result := TJclWideStrArrayIterator.Create(Self, 0, False, isFirst);
|
|
end;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
|
|
function TJclWideStrArrayList.GetString(Index: Integer): WideString;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := '';
|
|
if (Index >= 0) and (Index < FSize) then
|
|
Result := FElementData[Index]
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create(IntToStr(Index));
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclWideStrArrayList.IndexOf(const AString: WideString): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := -1;
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AString) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclWideStrArrayList.Insert(Index: Integer; const AString: WideString): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FAllowDefaultElements or not ItemsEqual(AString, '');
|
|
|
|
if (Index < 0) or (Index > FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
|
|
if Result then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(AString, FElementData[I]) then
|
|
begin
|
|
Result := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
if FSize = FCapacity then
|
|
AutoGrow;
|
|
Result := FSize < FCapacity;
|
|
if Result then
|
|
begin
|
|
if Index < FSize then
|
|
MoveArray(FElementData, Index, Index + 1, FSize - Index);
|
|
FElementData[Index] := AString;
|
|
Inc(FSize);
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclWideStrArrayList.InsertAll(Index: Integer; const ACollection: IJclWideStrCollection): Boolean;
|
|
var
|
|
It: IJclWideStrIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if (Index < 0) or (Index > FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
if ACollection = nil then
|
|
Exit;
|
|
|
|
Result := True;
|
|
It := ACollection.Last;
|
|
while It.HasPrevious do
|
|
Result := Insert(Index, It.Previous) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclWideStrArrayList.IsEmpty: Boolean;
|
|
begin
|
|
Result := FSize = 0;
|
|
end;
|
|
|
|
function TJclWideStrArrayList.Last: IJclWideStrIterator;
|
|
begin
|
|
Result := TJclWideStrArrayIterator.Create(Self, FSize - 1, False, isLast);
|
|
end;
|
|
|
|
function TJclWideStrArrayList.LastIndexOf(const AString: WideString): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := -1;
|
|
for I := FSize - 1 downto 0 do
|
|
if ItemsEqual(FElementData[I], AString) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclWideStrArrayList.RaiseOutOfBoundsError: WideString;
|
|
begin
|
|
raise EJclOutOfBoundsError.Create;
|
|
end;
|
|
|
|
function TJclWideStrArrayList.Remove(const AString: WideString): Boolean;
|
|
var
|
|
Extracted: WideString;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := Extract(AString);
|
|
if Result then
|
|
begin
|
|
Extracted := AString;
|
|
FreeString(Extracted);
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclWideStrArrayList.RemoveAll(const ACollection: IJclWideStrCollection): Boolean;
|
|
var
|
|
It: IJclWideStrIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Remove(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclWideStrArrayList.RetainAll(const ACollection: IJclWideStrCollection): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
for I := FSize - 1 downto 0 do
|
|
if not ACollection.Contains(FElementData[I]) then
|
|
Delete(I);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclWideStrArrayList.SetCapacity(Value: Integer);
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if Value >= FSize then
|
|
begin
|
|
SetLength(FElementData, Value);
|
|
inherited SetCapacity(Value);
|
|
end
|
|
else
|
|
raise EJclOutOfBoundsError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclWideStrArrayList.SetString(Index: Integer; const AString: WideString);
|
|
var
|
|
ReplaceItem: Boolean;
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (Index < 0) or (Index >= FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
ReplaceItem := FAllowDefaultElements or not ItemsEqual(AString, '');
|
|
if ReplaceItem then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AString) then
|
|
begin
|
|
ReplaceItem := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
if ReplaceItem then
|
|
begin
|
|
FreeString(FElementData[Index]);
|
|
FElementData[Index] := AString;
|
|
end;
|
|
end;
|
|
if not ReplaceItem then
|
|
Delete(Index);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclWideStrArrayList.Size: Integer;
|
|
begin
|
|
Result := FSize;
|
|
end;
|
|
|
|
function TJclWideStrArrayList.SubList(First, Count: Integer): IJclWideStrList;
|
|
var
|
|
I: Integer;
|
|
Last: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Last := First + Count - 1;
|
|
if Last >= FSize then
|
|
Last := FSize - 1;
|
|
Result := CreateEmptyContainer as IJclWideStrList;
|
|
for I := First to Last do
|
|
Result.Add(FElementData[I]);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclWideStrArrayList.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclWideStrArrayList.Create(FSize);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
//=== { TJclWideStrArrayIterator } ===============================================================
|
|
|
|
constructor TJclWideStrArrayIterator.Create(const AOwnList: IJclWideStrList; ACursor: Integer; AValid: Boolean; AStart: TItrStart);
|
|
begin
|
|
inherited Create(AValid);
|
|
FOwnList := AOwnList;
|
|
FStart := AStart;
|
|
FCursor := ACursor;
|
|
end;
|
|
|
|
function TJclWideStrArrayIterator.Add(const AString: WideString): Boolean;
|
|
begin
|
|
Result := FOwnList.Add(AString);
|
|
end;
|
|
|
|
procedure TJclWideStrArrayIterator.AssignPropertiesTo(Dest: TJclAbstractIterator);
|
|
var
|
|
ADest: TJclWideStrArrayIterator;
|
|
begin
|
|
inherited AssignPropertiesTo(Dest);
|
|
if Dest is TJclWideStrArrayIterator then
|
|
begin
|
|
ADest := TJclWideStrArrayIterator(Dest);
|
|
ADest.FOwnList := FOwnList;
|
|
ADest.FCursor := FCursor;
|
|
ADest.FStart := FStart;
|
|
end;
|
|
end;
|
|
|
|
function TJclWideStrArrayIterator.CreateEmptyIterator: TJclAbstractIterator;
|
|
begin
|
|
Result := TJclWideStrArrayIterator.Create(FOwnList, FCursor, Valid, FStart);
|
|
end;
|
|
|
|
procedure TJclWideStrArrayIterator.Extract;
|
|
begin
|
|
CheckValid;
|
|
Valid := False;
|
|
FOwnList.ExtractIndex(FCursor);
|
|
end;
|
|
|
|
function TJclWideStrArrayIterator.GetString: WideString;
|
|
begin
|
|
CheckValid;
|
|
Result := FOwnList.GetString(FCursor);
|
|
end;
|
|
|
|
function TJclWideStrArrayIterator.HasNext: Boolean;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor < (FOwnList.Size - 1)
|
|
else
|
|
Result := FCursor < FOwnList.Size;
|
|
end;
|
|
|
|
function TJclWideStrArrayIterator.HasPrevious: Boolean;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor > 0
|
|
else
|
|
Result := FCursor >= 0;
|
|
end;
|
|
|
|
function TJclWideStrArrayIterator.Insert(const AString: WideString): Boolean;
|
|
begin
|
|
CheckValid;
|
|
Result := FOwnList.Insert(FCursor, AString);
|
|
end;
|
|
|
|
function TJclWideStrArrayIterator.IteratorEquals(const AIterator: IJclWideStrIterator): Boolean;
|
|
var
|
|
Obj: TObject;
|
|
ItrObj: TJclWideStrArrayIterator;
|
|
begin
|
|
Result := False;
|
|
if AIterator = nil then
|
|
Exit;
|
|
Obj := AIterator.GetIteratorReference;
|
|
if Obj is TJclWideStrArrayIterator then
|
|
begin
|
|
ItrObj := TJclWideStrArrayIterator(Obj);
|
|
Result := (FOwnList = ItrObj.FOwnList) and (FCursor = ItrObj.FCursor) and (Valid = ItrObj.Valid);
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function TJclWideStrArrayIterator.MoveNext: Boolean;
|
|
begin
|
|
if Valid then
|
|
Inc(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FCursor < FOwnList.Size;
|
|
end;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
|
|
function TJclWideStrArrayIterator.Next: WideString;
|
|
begin
|
|
if Valid then
|
|
Inc(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FOwnList.GetString(FCursor);
|
|
end;
|
|
|
|
function TJclWideStrArrayIterator.NextIndex: Integer;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor + 1
|
|
else
|
|
Result := FCursor;
|
|
end;
|
|
|
|
function TJclWideStrArrayIterator.Previous: WideString;
|
|
begin
|
|
if Valid then
|
|
Dec(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FOwnList.GetString(FCursor);
|
|
end;
|
|
|
|
function TJclWideStrArrayIterator.PreviousIndex: Integer;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor - 1
|
|
else
|
|
Result := FCursor;
|
|
end;
|
|
|
|
procedure TJclWideStrArrayIterator.Remove;
|
|
begin
|
|
CheckValid;
|
|
Valid := False;
|
|
FOwnList.Delete(FCursor);
|
|
end;
|
|
|
|
procedure TJclWideStrArrayIterator.Reset;
|
|
begin
|
|
Valid := False;
|
|
case FStart of
|
|
isFirst:
|
|
FCursor := 0;
|
|
isLast:
|
|
FCursor := FOwnList.Size - 1;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclWideStrArrayIterator.SetString(const AString: WideString);
|
|
begin
|
|
CheckValid;
|
|
FOwnList.SetString(FCursor, AString);
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_UNICODE_STRING}
|
|
//=== { TJclUnicodeStrArrayList } ======================================================
|
|
|
|
constructor TJclUnicodeStrArrayList.Create(ACapacity: Integer);
|
|
begin
|
|
inherited Create();
|
|
SetCapacity(ACapacity);
|
|
end;
|
|
|
|
constructor TJclUnicodeStrArrayList.Create(const ACollection: IJclUnicodeStrCollection);
|
|
begin
|
|
inherited Create();
|
|
if ACollection = nil then
|
|
raise EJclNoCollectionError.Create;
|
|
SetCapacity(ACollection.Size);
|
|
AddAll(ACollection);
|
|
end;
|
|
|
|
destructor TJclUnicodeStrArrayList.Destroy;
|
|
begin
|
|
FReadOnly := False;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayList.Add(const AString: UnicodeString): Boolean;
|
|
var
|
|
Index: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FAllowDefaultElements or not ItemsEqual(AString, '');
|
|
if Result then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for Index := 0 to FSize - 1 do
|
|
if ItemsEqual(AString, FElementData[Index]) then
|
|
begin
|
|
Result := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
if FSize = FCapacity then
|
|
AutoGrow;
|
|
Result := FSize < FCapacity;
|
|
if Result then
|
|
begin
|
|
FElementData[FSize] := AString;
|
|
Inc(FSize);
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayList.AddAll(const ACollection: IJclUnicodeStrCollection): Boolean;
|
|
var
|
|
It: IJclUnicodeStrIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Add(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclUnicodeStrArrayList.AssignDataTo(Dest: TJclAbstractContainerBase);
|
|
var
|
|
ADest: TJclUnicodeStrArrayList;
|
|
ACollection: IJclUnicodeStrCollection;
|
|
begin
|
|
inherited AssignDataTo(Dest);
|
|
if Dest is TJclUnicodeStrArrayList then
|
|
begin
|
|
ADest := TJclUnicodeStrArrayList(Dest);
|
|
ADest.Clear;
|
|
ADest.AddAll(Self);
|
|
end
|
|
else
|
|
if Supports(IInterface(Dest), IJclUnicodeStrCollection, ACollection) then
|
|
begin
|
|
ACollection.Clear;
|
|
ACollection.AddAll(Self);
|
|
end;
|
|
end;
|
|
|
|
procedure TJclUnicodeStrArrayList.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
for I := 0 to FSize - 1 do
|
|
FreeString(FElementData[I]);
|
|
FSize := 0;
|
|
AutoPack;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayList.CollectionEquals(const ACollection: IJclUnicodeStrCollection): Boolean;
|
|
var
|
|
I: Integer;
|
|
It: IJclUnicodeStrIterator;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$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 not ItemsEqual(FElementData[I], It.Next) then
|
|
Exit;
|
|
Result := True;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayList.Contains(const AString: UnicodeString): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AString) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayList.ContainsAll(const ACollection: IJclUnicodeStrCollection): Boolean;
|
|
var
|
|
It: IJclUnicodeStrIterator;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := True;
|
|
if ACollection = nil then
|
|
Exit;
|
|
It := ACollection.First;
|
|
while Result and It.HasNext do
|
|
Result := Contains(It.Next);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayList.Delete(Index: Integer): UnicodeString;
|
|
var
|
|
Extracted: UnicodeString;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Extracted := ExtractIndex(Index);
|
|
Result := FreeString(Extracted);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayList.Extract(const AString: UnicodeString): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
for I := FSize - 1 downto 0 do
|
|
if ItemsEqual(FElementData[I], AString) then
|
|
begin
|
|
FElementData[I] := '';
|
|
if I < (FSize - 1) then
|
|
MoveArray(FElementData, I + 1, I, FSize - I);
|
|
Dec(FSize);
|
|
Result := True;
|
|
if FRemoveSingleElement then
|
|
Break;
|
|
end;
|
|
AutoPack;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayList.ExtractAll(const ACollection: IJclUnicodeStrCollection): Boolean;
|
|
var
|
|
It: IJclUnicodeStrIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Extract(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayList.ExtractIndex(Index: Integer): UnicodeString;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (Index >= 0) and (Index < FSize) then
|
|
begin
|
|
Result := FElementData[Index];
|
|
if Index < (FSize - 1) then
|
|
MoveArray(FElementData, Index + 1, Index, FSize - Index);
|
|
Dec(FSize);
|
|
AutoPack;
|
|
end
|
|
else
|
|
Result := RaiseOutOfBoundsError;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayList.First: IJclUnicodeStrIterator;
|
|
begin
|
|
Result := TJclUnicodeStrArrayIterator.Create(Self, 0, False, isFirst);
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function TJclUnicodeStrArrayList.GetEnumerator: IJclUnicodeStrIterator;
|
|
begin
|
|
Result := TJclUnicodeStrArrayIterator.Create(Self, 0, False, isFirst);
|
|
end;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
|
|
function TJclUnicodeStrArrayList.GetString(Index: Integer): UnicodeString;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := '';
|
|
if (Index >= 0) and (Index < FSize) then
|
|
Result := FElementData[Index]
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create(IntToStr(Index));
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayList.IndexOf(const AString: UnicodeString): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := -1;
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AString) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayList.Insert(Index: Integer; const AString: UnicodeString): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FAllowDefaultElements or not ItemsEqual(AString, '');
|
|
|
|
if (Index < 0) or (Index > FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
|
|
if Result then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(AString, FElementData[I]) then
|
|
begin
|
|
Result := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
if FSize = FCapacity then
|
|
AutoGrow;
|
|
Result := FSize < FCapacity;
|
|
if Result then
|
|
begin
|
|
if Index < FSize then
|
|
MoveArray(FElementData, Index, Index + 1, FSize - Index);
|
|
FElementData[Index] := AString;
|
|
Inc(FSize);
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayList.InsertAll(Index: Integer; const ACollection: IJclUnicodeStrCollection): Boolean;
|
|
var
|
|
It: IJclUnicodeStrIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if (Index < 0) or (Index > FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
if ACollection = nil then
|
|
Exit;
|
|
|
|
Result := True;
|
|
It := ACollection.Last;
|
|
while It.HasPrevious do
|
|
Result := Insert(Index, It.Previous) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayList.IsEmpty: Boolean;
|
|
begin
|
|
Result := FSize = 0;
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayList.Last: IJclUnicodeStrIterator;
|
|
begin
|
|
Result := TJclUnicodeStrArrayIterator.Create(Self, FSize - 1, False, isLast);
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayList.LastIndexOf(const AString: UnicodeString): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := -1;
|
|
for I := FSize - 1 downto 0 do
|
|
if ItemsEqual(FElementData[I], AString) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayList.RaiseOutOfBoundsError: UnicodeString;
|
|
begin
|
|
raise EJclOutOfBoundsError.Create;
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayList.Remove(const AString: UnicodeString): Boolean;
|
|
var
|
|
Extracted: UnicodeString;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := Extract(AString);
|
|
if Result then
|
|
begin
|
|
Extracted := AString;
|
|
FreeString(Extracted);
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayList.RemoveAll(const ACollection: IJclUnicodeStrCollection): Boolean;
|
|
var
|
|
It: IJclUnicodeStrIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Remove(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayList.RetainAll(const ACollection: IJclUnicodeStrCollection): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
for I := FSize - 1 downto 0 do
|
|
if not ACollection.Contains(FElementData[I]) then
|
|
Delete(I);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclUnicodeStrArrayList.SetCapacity(Value: Integer);
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if Value >= FSize then
|
|
begin
|
|
SetLength(FElementData, Value);
|
|
inherited SetCapacity(Value);
|
|
end
|
|
else
|
|
raise EJclOutOfBoundsError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclUnicodeStrArrayList.SetString(Index: Integer; const AString: UnicodeString);
|
|
var
|
|
ReplaceItem: Boolean;
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (Index < 0) or (Index >= FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
ReplaceItem := FAllowDefaultElements or not ItemsEqual(AString, '');
|
|
if ReplaceItem then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AString) then
|
|
begin
|
|
ReplaceItem := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
if ReplaceItem then
|
|
begin
|
|
FreeString(FElementData[Index]);
|
|
FElementData[Index] := AString;
|
|
end;
|
|
end;
|
|
if not ReplaceItem then
|
|
Delete(Index);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayList.Size: Integer;
|
|
begin
|
|
Result := FSize;
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayList.SubList(First, Count: Integer): IJclUnicodeStrList;
|
|
var
|
|
I: Integer;
|
|
Last: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Last := First + Count - 1;
|
|
if Last >= FSize then
|
|
Last := FSize - 1;
|
|
Result := CreateEmptyContainer as IJclUnicodeStrList;
|
|
for I := First to Last do
|
|
Result.Add(FElementData[I]);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayList.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclUnicodeStrArrayList.Create(FSize);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
//=== { TJclUnicodeStrArrayIterator } ===============================================================
|
|
|
|
constructor TJclUnicodeStrArrayIterator.Create(const AOwnList: IJclUnicodeStrList; ACursor: Integer; AValid: Boolean; AStart: TItrStart);
|
|
begin
|
|
inherited Create(AValid);
|
|
FOwnList := AOwnList;
|
|
FStart := AStart;
|
|
FCursor := ACursor;
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayIterator.Add(const AString: UnicodeString): Boolean;
|
|
begin
|
|
Result := FOwnList.Add(AString);
|
|
end;
|
|
|
|
procedure TJclUnicodeStrArrayIterator.AssignPropertiesTo(Dest: TJclAbstractIterator);
|
|
var
|
|
ADest: TJclUnicodeStrArrayIterator;
|
|
begin
|
|
inherited AssignPropertiesTo(Dest);
|
|
if Dest is TJclUnicodeStrArrayIterator then
|
|
begin
|
|
ADest := TJclUnicodeStrArrayIterator(Dest);
|
|
ADest.FOwnList := FOwnList;
|
|
ADest.FCursor := FCursor;
|
|
ADest.FStart := FStart;
|
|
end;
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayIterator.CreateEmptyIterator: TJclAbstractIterator;
|
|
begin
|
|
Result := TJclUnicodeStrArrayIterator.Create(FOwnList, FCursor, Valid, FStart);
|
|
end;
|
|
|
|
procedure TJclUnicodeStrArrayIterator.Extract;
|
|
begin
|
|
CheckValid;
|
|
Valid := False;
|
|
FOwnList.ExtractIndex(FCursor);
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayIterator.GetString: UnicodeString;
|
|
begin
|
|
CheckValid;
|
|
Result := FOwnList.GetString(FCursor);
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayIterator.HasNext: Boolean;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor < (FOwnList.Size - 1)
|
|
else
|
|
Result := FCursor < FOwnList.Size;
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayIterator.HasPrevious: Boolean;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor > 0
|
|
else
|
|
Result := FCursor >= 0;
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayIterator.Insert(const AString: UnicodeString): Boolean;
|
|
begin
|
|
CheckValid;
|
|
Result := FOwnList.Insert(FCursor, AString);
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayIterator.IteratorEquals(const AIterator: IJclUnicodeStrIterator): Boolean;
|
|
var
|
|
Obj: TObject;
|
|
ItrObj: TJclUnicodeStrArrayIterator;
|
|
begin
|
|
Result := False;
|
|
if AIterator = nil then
|
|
Exit;
|
|
Obj := AIterator.GetIteratorReference;
|
|
if Obj is TJclUnicodeStrArrayIterator then
|
|
begin
|
|
ItrObj := TJclUnicodeStrArrayIterator(Obj);
|
|
Result := (FOwnList = ItrObj.FOwnList) and (FCursor = ItrObj.FCursor) and (Valid = ItrObj.Valid);
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function TJclUnicodeStrArrayIterator.MoveNext: Boolean;
|
|
begin
|
|
if Valid then
|
|
Inc(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FCursor < FOwnList.Size;
|
|
end;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
|
|
function TJclUnicodeStrArrayIterator.Next: UnicodeString;
|
|
begin
|
|
if Valid then
|
|
Inc(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FOwnList.GetString(FCursor);
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayIterator.NextIndex: Integer;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor + 1
|
|
else
|
|
Result := FCursor;
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayIterator.Previous: UnicodeString;
|
|
begin
|
|
if Valid then
|
|
Dec(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FOwnList.GetString(FCursor);
|
|
end;
|
|
|
|
function TJclUnicodeStrArrayIterator.PreviousIndex: Integer;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor - 1
|
|
else
|
|
Result := FCursor;
|
|
end;
|
|
|
|
procedure TJclUnicodeStrArrayIterator.Remove;
|
|
begin
|
|
CheckValid;
|
|
Valid := False;
|
|
FOwnList.Delete(FCursor);
|
|
end;
|
|
|
|
procedure TJclUnicodeStrArrayIterator.Reset;
|
|
begin
|
|
Valid := False;
|
|
case FStart of
|
|
isFirst:
|
|
FCursor := 0;
|
|
isLast:
|
|
FCursor := FOwnList.Size - 1;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclUnicodeStrArrayIterator.SetString(const AString: UnicodeString);
|
|
begin
|
|
CheckValid;
|
|
FOwnList.SetString(FCursor, AString);
|
|
end;
|
|
{$ENDIF SUPPORTS_UNICODE_STRING}
|
|
|
|
|
|
//=== { TJclSingleArrayList } ======================================================
|
|
|
|
constructor TJclSingleArrayList.Create(ACapacity: Integer);
|
|
begin
|
|
inherited Create();
|
|
SetCapacity(ACapacity);
|
|
end;
|
|
|
|
constructor TJclSingleArrayList.Create(const ACollection: IJclSingleCollection);
|
|
begin
|
|
inherited Create();
|
|
if ACollection = nil then
|
|
raise EJclNoCollectionError.Create;
|
|
SetCapacity(ACollection.Size);
|
|
AddAll(ACollection);
|
|
end;
|
|
|
|
destructor TJclSingleArrayList.Destroy;
|
|
begin
|
|
FReadOnly := False;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJclSingleArrayList.Add(const AValue: Single): Boolean;
|
|
var
|
|
Index: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FAllowDefaultElements or not ItemsEqual(AValue, 0.0);
|
|
if Result then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for Index := 0 to FSize - 1 do
|
|
if ItemsEqual(AValue, FElementData[Index]) then
|
|
begin
|
|
Result := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
if FSize = FCapacity then
|
|
AutoGrow;
|
|
Result := FSize < FCapacity;
|
|
if Result then
|
|
begin
|
|
FElementData[FSize] := AValue;
|
|
Inc(FSize);
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclSingleArrayList.AddAll(const ACollection: IJclSingleCollection): Boolean;
|
|
var
|
|
It: IJclSingleIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Add(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclSingleArrayList.AssignDataTo(Dest: TJclAbstractContainerBase);
|
|
var
|
|
ADest: TJclSingleArrayList;
|
|
ACollection: IJclSingleCollection;
|
|
begin
|
|
inherited AssignDataTo(Dest);
|
|
if Dest is TJclSingleArrayList then
|
|
begin
|
|
ADest := TJclSingleArrayList(Dest);
|
|
ADest.Clear;
|
|
ADest.AddAll(Self);
|
|
end
|
|
else
|
|
if Supports(IInterface(Dest), IJclSingleCollection, ACollection) then
|
|
begin
|
|
ACollection.Clear;
|
|
ACollection.AddAll(Self);
|
|
end;
|
|
end;
|
|
|
|
procedure TJclSingleArrayList.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
for I := 0 to FSize - 1 do
|
|
FreeSingle(FElementData[I]);
|
|
FSize := 0;
|
|
AutoPack;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclSingleArrayList.CollectionEquals(const ACollection: IJclSingleCollection): Boolean;
|
|
var
|
|
I: Integer;
|
|
It: IJclSingleIterator;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$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 not ItemsEqual(FElementData[I], It.Next) then
|
|
Exit;
|
|
Result := True;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclSingleArrayList.Contains(const AValue: Single): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclSingleArrayList.ContainsAll(const ACollection: IJclSingleCollection): Boolean;
|
|
var
|
|
It: IJclSingleIterator;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := True;
|
|
if ACollection = nil then
|
|
Exit;
|
|
It := ACollection.First;
|
|
while Result and It.HasNext do
|
|
Result := Contains(It.Next);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclSingleArrayList.Delete(Index: Integer): Single;
|
|
var
|
|
Extracted: Single;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Extracted := ExtractIndex(Index);
|
|
Result := FreeSingle(Extracted);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclSingleArrayList.Extract(const AValue: Single): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
for I := FSize - 1 downto 0 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
FElementData[I] := 0.0;
|
|
if I < (FSize - 1) then
|
|
MoveArray(FElementData, I + 1, I, FSize - I);
|
|
Dec(FSize);
|
|
Result := True;
|
|
if FRemoveSingleElement then
|
|
Break;
|
|
end;
|
|
AutoPack;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclSingleArrayList.ExtractAll(const ACollection: IJclSingleCollection): Boolean;
|
|
var
|
|
It: IJclSingleIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Extract(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclSingleArrayList.ExtractIndex(Index: Integer): Single;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (Index >= 0) and (Index < FSize) then
|
|
begin
|
|
Result := FElementData[Index];
|
|
if Index < (FSize - 1) then
|
|
MoveArray(FElementData, Index + 1, Index, FSize - Index);
|
|
Dec(FSize);
|
|
AutoPack;
|
|
end
|
|
else
|
|
Result := RaiseOutOfBoundsError;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclSingleArrayList.First: IJclSingleIterator;
|
|
begin
|
|
Result := TJclSingleArrayIterator.Create(Self, 0, False, isFirst);
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function TJclSingleArrayList.GetEnumerator: IJclSingleIterator;
|
|
begin
|
|
Result := TJclSingleArrayIterator.Create(Self, 0, False, isFirst);
|
|
end;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
|
|
function TJclSingleArrayList.GetValue(Index: Integer): Single;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := 0.0;
|
|
if (Index >= 0) and (Index < FSize) then
|
|
Result := FElementData[Index]
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create(IntToStr(Index));
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclSingleArrayList.IndexOf(const AValue: Single): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := -1;
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclSingleArrayList.Insert(Index: Integer; const AValue: Single): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FAllowDefaultElements or not ItemsEqual(AValue, 0.0);
|
|
|
|
if (Index < 0) or (Index > FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
|
|
if Result then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(AValue, FElementData[I]) then
|
|
begin
|
|
Result := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
if FSize = FCapacity then
|
|
AutoGrow;
|
|
Result := FSize < FCapacity;
|
|
if Result then
|
|
begin
|
|
if Index < FSize then
|
|
MoveArray(FElementData, Index, Index + 1, FSize - Index);
|
|
FElementData[Index] := AValue;
|
|
Inc(FSize);
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclSingleArrayList.InsertAll(Index: Integer; const ACollection: IJclSingleCollection): Boolean;
|
|
var
|
|
It: IJclSingleIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if (Index < 0) or (Index > FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
if ACollection = nil then
|
|
Exit;
|
|
|
|
Result := True;
|
|
It := ACollection.Last;
|
|
while It.HasPrevious do
|
|
Result := Insert(Index, It.Previous) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclSingleArrayList.IsEmpty: Boolean;
|
|
begin
|
|
Result := FSize = 0;
|
|
end;
|
|
|
|
function TJclSingleArrayList.Last: IJclSingleIterator;
|
|
begin
|
|
Result := TJclSingleArrayIterator.Create(Self, FSize - 1, False, isLast);
|
|
end;
|
|
|
|
function TJclSingleArrayList.LastIndexOf(const AValue: Single): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := -1;
|
|
for I := FSize - 1 downto 0 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclSingleArrayList.RaiseOutOfBoundsError: Single;
|
|
begin
|
|
raise EJclOutOfBoundsError.Create;
|
|
end;
|
|
|
|
function TJclSingleArrayList.Remove(const AValue: Single): Boolean;
|
|
var
|
|
Extracted: Single;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := Extract(AValue);
|
|
if Result then
|
|
begin
|
|
Extracted := AValue;
|
|
FreeSingle(Extracted);
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclSingleArrayList.RemoveAll(const ACollection: IJclSingleCollection): Boolean;
|
|
var
|
|
It: IJclSingleIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Remove(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclSingleArrayList.RetainAll(const ACollection: IJclSingleCollection): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
for I := FSize - 1 downto 0 do
|
|
if not ACollection.Contains(FElementData[I]) then
|
|
Delete(I);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclSingleArrayList.SetCapacity(Value: Integer);
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if Value >= FSize then
|
|
begin
|
|
SetLength(FElementData, Value);
|
|
inherited SetCapacity(Value);
|
|
end
|
|
else
|
|
raise EJclOutOfBoundsError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclSingleArrayList.SetValue(Index: Integer; const AValue: Single);
|
|
var
|
|
ReplaceItem: Boolean;
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (Index < 0) or (Index >= FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
ReplaceItem := FAllowDefaultElements or not ItemsEqual(AValue, 0.0);
|
|
if ReplaceItem then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
ReplaceItem := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
if ReplaceItem then
|
|
begin
|
|
FreeSingle(FElementData[Index]);
|
|
FElementData[Index] := AValue;
|
|
end;
|
|
end;
|
|
if not ReplaceItem then
|
|
Delete(Index);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclSingleArrayList.Size: Integer;
|
|
begin
|
|
Result := FSize;
|
|
end;
|
|
|
|
function TJclSingleArrayList.SubList(First, Count: Integer): IJclSingleList;
|
|
var
|
|
I: Integer;
|
|
Last: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Last := First + Count - 1;
|
|
if Last >= FSize then
|
|
Last := FSize - 1;
|
|
Result := CreateEmptyContainer as IJclSingleList;
|
|
for I := First to Last do
|
|
Result.Add(FElementData[I]);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclSingleArrayList.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclSingleArrayList.Create(FSize);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
//=== { TJclSingleArrayIterator } ===============================================================
|
|
|
|
constructor TJclSingleArrayIterator.Create(const AOwnList: IJclSingleList; ACursor: Integer; AValid: Boolean; AStart: TItrStart);
|
|
begin
|
|
inherited Create(AValid);
|
|
FOwnList := AOwnList;
|
|
FStart := AStart;
|
|
FCursor := ACursor;
|
|
end;
|
|
|
|
function TJclSingleArrayIterator.Add(const AValue: Single): Boolean;
|
|
begin
|
|
Result := FOwnList.Add(AValue);
|
|
end;
|
|
|
|
procedure TJclSingleArrayIterator.AssignPropertiesTo(Dest: TJclAbstractIterator);
|
|
var
|
|
ADest: TJclSingleArrayIterator;
|
|
begin
|
|
inherited AssignPropertiesTo(Dest);
|
|
if Dest is TJclSingleArrayIterator then
|
|
begin
|
|
ADest := TJclSingleArrayIterator(Dest);
|
|
ADest.FOwnList := FOwnList;
|
|
ADest.FCursor := FCursor;
|
|
ADest.FStart := FStart;
|
|
end;
|
|
end;
|
|
|
|
function TJclSingleArrayIterator.CreateEmptyIterator: TJclAbstractIterator;
|
|
begin
|
|
Result := TJclSingleArrayIterator.Create(FOwnList, FCursor, Valid, FStart);
|
|
end;
|
|
|
|
procedure TJclSingleArrayIterator.Extract;
|
|
begin
|
|
CheckValid;
|
|
Valid := False;
|
|
FOwnList.ExtractIndex(FCursor);
|
|
end;
|
|
|
|
function TJclSingleArrayIterator.GetValue: Single;
|
|
begin
|
|
CheckValid;
|
|
Result := FOwnList.GetValue(FCursor);
|
|
end;
|
|
|
|
function TJclSingleArrayIterator.HasNext: Boolean;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor < (FOwnList.Size - 1)
|
|
else
|
|
Result := FCursor < FOwnList.Size;
|
|
end;
|
|
|
|
function TJclSingleArrayIterator.HasPrevious: Boolean;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor > 0
|
|
else
|
|
Result := FCursor >= 0;
|
|
end;
|
|
|
|
function TJclSingleArrayIterator.Insert(const AValue: Single): Boolean;
|
|
begin
|
|
CheckValid;
|
|
Result := FOwnList.Insert(FCursor, AValue);
|
|
end;
|
|
|
|
function TJclSingleArrayIterator.IteratorEquals(const AIterator: IJclSingleIterator): Boolean;
|
|
var
|
|
Obj: TObject;
|
|
ItrObj: TJclSingleArrayIterator;
|
|
begin
|
|
Result := False;
|
|
if AIterator = nil then
|
|
Exit;
|
|
Obj := AIterator.GetIteratorReference;
|
|
if Obj is TJclSingleArrayIterator then
|
|
begin
|
|
ItrObj := TJclSingleArrayIterator(Obj);
|
|
Result := (FOwnList = ItrObj.FOwnList) and (FCursor = ItrObj.FCursor) and (Valid = ItrObj.Valid);
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function TJclSingleArrayIterator.MoveNext: Boolean;
|
|
begin
|
|
if Valid then
|
|
Inc(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FCursor < FOwnList.Size;
|
|
end;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
|
|
function TJclSingleArrayIterator.Next: Single;
|
|
begin
|
|
if Valid then
|
|
Inc(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FOwnList.GetValue(FCursor);
|
|
end;
|
|
|
|
function TJclSingleArrayIterator.NextIndex: Integer;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor + 1
|
|
else
|
|
Result := FCursor;
|
|
end;
|
|
|
|
function TJclSingleArrayIterator.Previous: Single;
|
|
begin
|
|
if Valid then
|
|
Dec(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FOwnList.GetValue(FCursor);
|
|
end;
|
|
|
|
function TJclSingleArrayIterator.PreviousIndex: Integer;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor - 1
|
|
else
|
|
Result := FCursor;
|
|
end;
|
|
|
|
procedure TJclSingleArrayIterator.Remove;
|
|
begin
|
|
CheckValid;
|
|
Valid := False;
|
|
FOwnList.Delete(FCursor);
|
|
end;
|
|
|
|
procedure TJclSingleArrayIterator.Reset;
|
|
begin
|
|
Valid := False;
|
|
case FStart of
|
|
isFirst:
|
|
FCursor := 0;
|
|
isLast:
|
|
FCursor := FOwnList.Size - 1;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclSingleArrayIterator.SetValue(const AValue: Single);
|
|
begin
|
|
CheckValid;
|
|
FOwnList.SetValue(FCursor, AValue);
|
|
end;
|
|
|
|
//=== { TJclDoubleArrayList } ======================================================
|
|
|
|
constructor TJclDoubleArrayList.Create(ACapacity: Integer);
|
|
begin
|
|
inherited Create();
|
|
SetCapacity(ACapacity);
|
|
end;
|
|
|
|
constructor TJclDoubleArrayList.Create(const ACollection: IJclDoubleCollection);
|
|
begin
|
|
inherited Create();
|
|
if ACollection = nil then
|
|
raise EJclNoCollectionError.Create;
|
|
SetCapacity(ACollection.Size);
|
|
AddAll(ACollection);
|
|
end;
|
|
|
|
destructor TJclDoubleArrayList.Destroy;
|
|
begin
|
|
FReadOnly := False;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJclDoubleArrayList.Add(const AValue: Double): Boolean;
|
|
var
|
|
Index: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FAllowDefaultElements or not ItemsEqual(AValue, 0.0);
|
|
if Result then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for Index := 0 to FSize - 1 do
|
|
if ItemsEqual(AValue, FElementData[Index]) then
|
|
begin
|
|
Result := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
if FSize = FCapacity then
|
|
AutoGrow;
|
|
Result := FSize < FCapacity;
|
|
if Result then
|
|
begin
|
|
FElementData[FSize] := AValue;
|
|
Inc(FSize);
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclDoubleArrayList.AddAll(const ACollection: IJclDoubleCollection): Boolean;
|
|
var
|
|
It: IJclDoubleIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Add(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclDoubleArrayList.AssignDataTo(Dest: TJclAbstractContainerBase);
|
|
var
|
|
ADest: TJclDoubleArrayList;
|
|
ACollection: IJclDoubleCollection;
|
|
begin
|
|
inherited AssignDataTo(Dest);
|
|
if Dest is TJclDoubleArrayList then
|
|
begin
|
|
ADest := TJclDoubleArrayList(Dest);
|
|
ADest.Clear;
|
|
ADest.AddAll(Self);
|
|
end
|
|
else
|
|
if Supports(IInterface(Dest), IJclDoubleCollection, ACollection) then
|
|
begin
|
|
ACollection.Clear;
|
|
ACollection.AddAll(Self);
|
|
end;
|
|
end;
|
|
|
|
procedure TJclDoubleArrayList.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
for I := 0 to FSize - 1 do
|
|
FreeDouble(FElementData[I]);
|
|
FSize := 0;
|
|
AutoPack;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclDoubleArrayList.CollectionEquals(const ACollection: IJclDoubleCollection): Boolean;
|
|
var
|
|
I: Integer;
|
|
It: IJclDoubleIterator;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$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 not ItemsEqual(FElementData[I], It.Next) then
|
|
Exit;
|
|
Result := True;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclDoubleArrayList.Contains(const AValue: Double): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclDoubleArrayList.ContainsAll(const ACollection: IJclDoubleCollection): Boolean;
|
|
var
|
|
It: IJclDoubleIterator;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := True;
|
|
if ACollection = nil then
|
|
Exit;
|
|
It := ACollection.First;
|
|
while Result and It.HasNext do
|
|
Result := Contains(It.Next);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclDoubleArrayList.Delete(Index: Integer): Double;
|
|
var
|
|
Extracted: Double;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Extracted := ExtractIndex(Index);
|
|
Result := FreeDouble(Extracted);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclDoubleArrayList.Extract(const AValue: Double): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
for I := FSize - 1 downto 0 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
FElementData[I] := 0.0;
|
|
if I < (FSize - 1) then
|
|
MoveArray(FElementData, I + 1, I, FSize - I);
|
|
Dec(FSize);
|
|
Result := True;
|
|
if FRemoveSingleElement then
|
|
Break;
|
|
end;
|
|
AutoPack;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclDoubleArrayList.ExtractAll(const ACollection: IJclDoubleCollection): Boolean;
|
|
var
|
|
It: IJclDoubleIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Extract(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclDoubleArrayList.ExtractIndex(Index: Integer): Double;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (Index >= 0) and (Index < FSize) then
|
|
begin
|
|
Result := FElementData[Index];
|
|
if Index < (FSize - 1) then
|
|
MoveArray(FElementData, Index + 1, Index, FSize - Index);
|
|
Dec(FSize);
|
|
AutoPack;
|
|
end
|
|
else
|
|
Result := RaiseOutOfBoundsError;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclDoubleArrayList.First: IJclDoubleIterator;
|
|
begin
|
|
Result := TJclDoubleArrayIterator.Create(Self, 0, False, isFirst);
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function TJclDoubleArrayList.GetEnumerator: IJclDoubleIterator;
|
|
begin
|
|
Result := TJclDoubleArrayIterator.Create(Self, 0, False, isFirst);
|
|
end;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
|
|
function TJclDoubleArrayList.GetValue(Index: Integer): Double;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := 0.0;
|
|
if (Index >= 0) and (Index < FSize) then
|
|
Result := FElementData[Index]
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create(IntToStr(Index));
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclDoubleArrayList.IndexOf(const AValue: Double): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := -1;
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclDoubleArrayList.Insert(Index: Integer; const AValue: Double): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FAllowDefaultElements or not ItemsEqual(AValue, 0.0);
|
|
|
|
if (Index < 0) or (Index > FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
|
|
if Result then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(AValue, FElementData[I]) then
|
|
begin
|
|
Result := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
if FSize = FCapacity then
|
|
AutoGrow;
|
|
Result := FSize < FCapacity;
|
|
if Result then
|
|
begin
|
|
if Index < FSize then
|
|
MoveArray(FElementData, Index, Index + 1, FSize - Index);
|
|
FElementData[Index] := AValue;
|
|
Inc(FSize);
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclDoubleArrayList.InsertAll(Index: Integer; const ACollection: IJclDoubleCollection): Boolean;
|
|
var
|
|
It: IJclDoubleIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if (Index < 0) or (Index > FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
if ACollection = nil then
|
|
Exit;
|
|
|
|
Result := True;
|
|
It := ACollection.Last;
|
|
while It.HasPrevious do
|
|
Result := Insert(Index, It.Previous) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclDoubleArrayList.IsEmpty: Boolean;
|
|
begin
|
|
Result := FSize = 0;
|
|
end;
|
|
|
|
function TJclDoubleArrayList.Last: IJclDoubleIterator;
|
|
begin
|
|
Result := TJclDoubleArrayIterator.Create(Self, FSize - 1, False, isLast);
|
|
end;
|
|
|
|
function TJclDoubleArrayList.LastIndexOf(const AValue: Double): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := -1;
|
|
for I := FSize - 1 downto 0 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclDoubleArrayList.RaiseOutOfBoundsError: Double;
|
|
begin
|
|
raise EJclOutOfBoundsError.Create;
|
|
end;
|
|
|
|
function TJclDoubleArrayList.Remove(const AValue: Double): Boolean;
|
|
var
|
|
Extracted: Double;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := Extract(AValue);
|
|
if Result then
|
|
begin
|
|
Extracted := AValue;
|
|
FreeDouble(Extracted);
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclDoubleArrayList.RemoveAll(const ACollection: IJclDoubleCollection): Boolean;
|
|
var
|
|
It: IJclDoubleIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Remove(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclDoubleArrayList.RetainAll(const ACollection: IJclDoubleCollection): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
for I := FSize - 1 downto 0 do
|
|
if not ACollection.Contains(FElementData[I]) then
|
|
Delete(I);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclDoubleArrayList.SetCapacity(Value: Integer);
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if Value >= FSize then
|
|
begin
|
|
SetLength(FElementData, Value);
|
|
inherited SetCapacity(Value);
|
|
end
|
|
else
|
|
raise EJclOutOfBoundsError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclDoubleArrayList.SetValue(Index: Integer; const AValue: Double);
|
|
var
|
|
ReplaceItem: Boolean;
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (Index < 0) or (Index >= FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
ReplaceItem := FAllowDefaultElements or not ItemsEqual(AValue, 0.0);
|
|
if ReplaceItem then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
ReplaceItem := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
if ReplaceItem then
|
|
begin
|
|
FreeDouble(FElementData[Index]);
|
|
FElementData[Index] := AValue;
|
|
end;
|
|
end;
|
|
if not ReplaceItem then
|
|
Delete(Index);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclDoubleArrayList.Size: Integer;
|
|
begin
|
|
Result := FSize;
|
|
end;
|
|
|
|
function TJclDoubleArrayList.SubList(First, Count: Integer): IJclDoubleList;
|
|
var
|
|
I: Integer;
|
|
Last: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Last := First + Count - 1;
|
|
if Last >= FSize then
|
|
Last := FSize - 1;
|
|
Result := CreateEmptyContainer as IJclDoubleList;
|
|
for I := First to Last do
|
|
Result.Add(FElementData[I]);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclDoubleArrayList.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclDoubleArrayList.Create(FSize);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
//=== { TJclDoubleArrayIterator } ===============================================================
|
|
|
|
constructor TJclDoubleArrayIterator.Create(const AOwnList: IJclDoubleList; ACursor: Integer; AValid: Boolean; AStart: TItrStart);
|
|
begin
|
|
inherited Create(AValid);
|
|
FOwnList := AOwnList;
|
|
FStart := AStart;
|
|
FCursor := ACursor;
|
|
end;
|
|
|
|
function TJclDoubleArrayIterator.Add(const AValue: Double): Boolean;
|
|
begin
|
|
Result := FOwnList.Add(AValue);
|
|
end;
|
|
|
|
procedure TJclDoubleArrayIterator.AssignPropertiesTo(Dest: TJclAbstractIterator);
|
|
var
|
|
ADest: TJclDoubleArrayIterator;
|
|
begin
|
|
inherited AssignPropertiesTo(Dest);
|
|
if Dest is TJclDoubleArrayIterator then
|
|
begin
|
|
ADest := TJclDoubleArrayIterator(Dest);
|
|
ADest.FOwnList := FOwnList;
|
|
ADest.FCursor := FCursor;
|
|
ADest.FStart := FStart;
|
|
end;
|
|
end;
|
|
|
|
function TJclDoubleArrayIterator.CreateEmptyIterator: TJclAbstractIterator;
|
|
begin
|
|
Result := TJclDoubleArrayIterator.Create(FOwnList, FCursor, Valid, FStart);
|
|
end;
|
|
|
|
procedure TJclDoubleArrayIterator.Extract;
|
|
begin
|
|
CheckValid;
|
|
Valid := False;
|
|
FOwnList.ExtractIndex(FCursor);
|
|
end;
|
|
|
|
function TJclDoubleArrayIterator.GetValue: Double;
|
|
begin
|
|
CheckValid;
|
|
Result := FOwnList.GetValue(FCursor);
|
|
end;
|
|
|
|
function TJclDoubleArrayIterator.HasNext: Boolean;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor < (FOwnList.Size - 1)
|
|
else
|
|
Result := FCursor < FOwnList.Size;
|
|
end;
|
|
|
|
function TJclDoubleArrayIterator.HasPrevious: Boolean;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor > 0
|
|
else
|
|
Result := FCursor >= 0;
|
|
end;
|
|
|
|
function TJclDoubleArrayIterator.Insert(const AValue: Double): Boolean;
|
|
begin
|
|
CheckValid;
|
|
Result := FOwnList.Insert(FCursor, AValue);
|
|
end;
|
|
|
|
function TJclDoubleArrayIterator.IteratorEquals(const AIterator: IJclDoubleIterator): Boolean;
|
|
var
|
|
Obj: TObject;
|
|
ItrObj: TJclDoubleArrayIterator;
|
|
begin
|
|
Result := False;
|
|
if AIterator = nil then
|
|
Exit;
|
|
Obj := AIterator.GetIteratorReference;
|
|
if Obj is TJclDoubleArrayIterator then
|
|
begin
|
|
ItrObj := TJclDoubleArrayIterator(Obj);
|
|
Result := (FOwnList = ItrObj.FOwnList) and (FCursor = ItrObj.FCursor) and (Valid = ItrObj.Valid);
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function TJclDoubleArrayIterator.MoveNext: Boolean;
|
|
begin
|
|
if Valid then
|
|
Inc(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FCursor < FOwnList.Size;
|
|
end;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
|
|
function TJclDoubleArrayIterator.Next: Double;
|
|
begin
|
|
if Valid then
|
|
Inc(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FOwnList.GetValue(FCursor);
|
|
end;
|
|
|
|
function TJclDoubleArrayIterator.NextIndex: Integer;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor + 1
|
|
else
|
|
Result := FCursor;
|
|
end;
|
|
|
|
function TJclDoubleArrayIterator.Previous: Double;
|
|
begin
|
|
if Valid then
|
|
Dec(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FOwnList.GetValue(FCursor);
|
|
end;
|
|
|
|
function TJclDoubleArrayIterator.PreviousIndex: Integer;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor - 1
|
|
else
|
|
Result := FCursor;
|
|
end;
|
|
|
|
procedure TJclDoubleArrayIterator.Remove;
|
|
begin
|
|
CheckValid;
|
|
Valid := False;
|
|
FOwnList.Delete(FCursor);
|
|
end;
|
|
|
|
procedure TJclDoubleArrayIterator.Reset;
|
|
begin
|
|
Valid := False;
|
|
case FStart of
|
|
isFirst:
|
|
FCursor := 0;
|
|
isLast:
|
|
FCursor := FOwnList.Size - 1;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclDoubleArrayIterator.SetValue(const AValue: Double);
|
|
begin
|
|
CheckValid;
|
|
FOwnList.SetValue(FCursor, AValue);
|
|
end;
|
|
|
|
//=== { TJclExtendedArrayList } ======================================================
|
|
|
|
constructor TJclExtendedArrayList.Create(ACapacity: Integer);
|
|
begin
|
|
inherited Create();
|
|
SetCapacity(ACapacity);
|
|
end;
|
|
|
|
constructor TJclExtendedArrayList.Create(const ACollection: IJclExtendedCollection);
|
|
begin
|
|
inherited Create();
|
|
if ACollection = nil then
|
|
raise EJclNoCollectionError.Create;
|
|
SetCapacity(ACollection.Size);
|
|
AddAll(ACollection);
|
|
end;
|
|
|
|
destructor TJclExtendedArrayList.Destroy;
|
|
begin
|
|
FReadOnly := False;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJclExtendedArrayList.Add(const AValue: Extended): Boolean;
|
|
var
|
|
Index: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FAllowDefaultElements or not ItemsEqual(AValue, 0.0);
|
|
if Result then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for Index := 0 to FSize - 1 do
|
|
if ItemsEqual(AValue, FElementData[Index]) then
|
|
begin
|
|
Result := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
if FSize = FCapacity then
|
|
AutoGrow;
|
|
Result := FSize < FCapacity;
|
|
if Result then
|
|
begin
|
|
FElementData[FSize] := AValue;
|
|
Inc(FSize);
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclExtendedArrayList.AddAll(const ACollection: IJclExtendedCollection): Boolean;
|
|
var
|
|
It: IJclExtendedIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Add(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclExtendedArrayList.AssignDataTo(Dest: TJclAbstractContainerBase);
|
|
var
|
|
ADest: TJclExtendedArrayList;
|
|
ACollection: IJclExtendedCollection;
|
|
begin
|
|
inherited AssignDataTo(Dest);
|
|
if Dest is TJclExtendedArrayList then
|
|
begin
|
|
ADest := TJclExtendedArrayList(Dest);
|
|
ADest.Clear;
|
|
ADest.AddAll(Self);
|
|
end
|
|
else
|
|
if Supports(IInterface(Dest), IJclExtendedCollection, ACollection) then
|
|
begin
|
|
ACollection.Clear;
|
|
ACollection.AddAll(Self);
|
|
end;
|
|
end;
|
|
|
|
procedure TJclExtendedArrayList.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
for I := 0 to FSize - 1 do
|
|
FreeExtended(FElementData[I]);
|
|
FSize := 0;
|
|
AutoPack;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclExtendedArrayList.CollectionEquals(const ACollection: IJclExtendedCollection): Boolean;
|
|
var
|
|
I: Integer;
|
|
It: IJclExtendedIterator;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$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 not ItemsEqual(FElementData[I], It.Next) then
|
|
Exit;
|
|
Result := True;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclExtendedArrayList.Contains(const AValue: Extended): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclExtendedArrayList.ContainsAll(const ACollection: IJclExtendedCollection): Boolean;
|
|
var
|
|
It: IJclExtendedIterator;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := True;
|
|
if ACollection = nil then
|
|
Exit;
|
|
It := ACollection.First;
|
|
while Result and It.HasNext do
|
|
Result := Contains(It.Next);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclExtendedArrayList.Delete(Index: Integer): Extended;
|
|
var
|
|
Extracted: Extended;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Extracted := ExtractIndex(Index);
|
|
Result := FreeExtended(Extracted);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclExtendedArrayList.Extract(const AValue: Extended): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
for I := FSize - 1 downto 0 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
FElementData[I] := 0.0;
|
|
if I < (FSize - 1) then
|
|
MoveArray(FElementData, I + 1, I, FSize - I);
|
|
Dec(FSize);
|
|
Result := True;
|
|
if FRemoveSingleElement then
|
|
Break;
|
|
end;
|
|
AutoPack;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclExtendedArrayList.ExtractAll(const ACollection: IJclExtendedCollection): Boolean;
|
|
var
|
|
It: IJclExtendedIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Extract(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclExtendedArrayList.ExtractIndex(Index: Integer): Extended;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (Index >= 0) and (Index < FSize) then
|
|
begin
|
|
Result := FElementData[Index];
|
|
if Index < (FSize - 1) then
|
|
MoveArray(FElementData, Index + 1, Index, FSize - Index);
|
|
Dec(FSize);
|
|
AutoPack;
|
|
end
|
|
else
|
|
Result := RaiseOutOfBoundsError;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclExtendedArrayList.First: IJclExtendedIterator;
|
|
begin
|
|
Result := TJclExtendedArrayIterator.Create(Self, 0, False, isFirst);
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function TJclExtendedArrayList.GetEnumerator: IJclExtendedIterator;
|
|
begin
|
|
Result := TJclExtendedArrayIterator.Create(Self, 0, False, isFirst);
|
|
end;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
|
|
function TJclExtendedArrayList.GetValue(Index: Integer): Extended;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := 0.0;
|
|
if (Index >= 0) and (Index < FSize) then
|
|
Result := FElementData[Index]
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create(IntToStr(Index));
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclExtendedArrayList.IndexOf(const AValue: Extended): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := -1;
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclExtendedArrayList.Insert(Index: Integer; const AValue: Extended): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FAllowDefaultElements or not ItemsEqual(AValue, 0.0);
|
|
|
|
if (Index < 0) or (Index > FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
|
|
if Result then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(AValue, FElementData[I]) then
|
|
begin
|
|
Result := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
if FSize = FCapacity then
|
|
AutoGrow;
|
|
Result := FSize < FCapacity;
|
|
if Result then
|
|
begin
|
|
if Index < FSize then
|
|
MoveArray(FElementData, Index, Index + 1, FSize - Index);
|
|
FElementData[Index] := AValue;
|
|
Inc(FSize);
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclExtendedArrayList.InsertAll(Index: Integer; const ACollection: IJclExtendedCollection): Boolean;
|
|
var
|
|
It: IJclExtendedIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if (Index < 0) or (Index > FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
if ACollection = nil then
|
|
Exit;
|
|
|
|
Result := True;
|
|
It := ACollection.Last;
|
|
while It.HasPrevious do
|
|
Result := Insert(Index, It.Previous) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclExtendedArrayList.IsEmpty: Boolean;
|
|
begin
|
|
Result := FSize = 0;
|
|
end;
|
|
|
|
function TJclExtendedArrayList.Last: IJclExtendedIterator;
|
|
begin
|
|
Result := TJclExtendedArrayIterator.Create(Self, FSize - 1, False, isLast);
|
|
end;
|
|
|
|
function TJclExtendedArrayList.LastIndexOf(const AValue: Extended): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := -1;
|
|
for I := FSize - 1 downto 0 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclExtendedArrayList.RaiseOutOfBoundsError: Extended;
|
|
begin
|
|
raise EJclOutOfBoundsError.Create;
|
|
end;
|
|
|
|
function TJclExtendedArrayList.Remove(const AValue: Extended): Boolean;
|
|
var
|
|
Extracted: Extended;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := Extract(AValue);
|
|
if Result then
|
|
begin
|
|
Extracted := AValue;
|
|
FreeExtended(Extracted);
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclExtendedArrayList.RemoveAll(const ACollection: IJclExtendedCollection): Boolean;
|
|
var
|
|
It: IJclExtendedIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Remove(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclExtendedArrayList.RetainAll(const ACollection: IJclExtendedCollection): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
for I := FSize - 1 downto 0 do
|
|
if not ACollection.Contains(FElementData[I]) then
|
|
Delete(I);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclExtendedArrayList.SetCapacity(Value: Integer);
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if Value >= FSize then
|
|
begin
|
|
SetLength(FElementData, Value);
|
|
inherited SetCapacity(Value);
|
|
end
|
|
else
|
|
raise EJclOutOfBoundsError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclExtendedArrayList.SetValue(Index: Integer; const AValue: Extended);
|
|
var
|
|
ReplaceItem: Boolean;
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (Index < 0) or (Index >= FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
ReplaceItem := FAllowDefaultElements or not ItemsEqual(AValue, 0.0);
|
|
if ReplaceItem then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
ReplaceItem := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
if ReplaceItem then
|
|
begin
|
|
FreeExtended(FElementData[Index]);
|
|
FElementData[Index] := AValue;
|
|
end;
|
|
end;
|
|
if not ReplaceItem then
|
|
Delete(Index);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclExtendedArrayList.Size: Integer;
|
|
begin
|
|
Result := FSize;
|
|
end;
|
|
|
|
function TJclExtendedArrayList.SubList(First, Count: Integer): IJclExtendedList;
|
|
var
|
|
I: Integer;
|
|
Last: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Last := First + Count - 1;
|
|
if Last >= FSize then
|
|
Last := FSize - 1;
|
|
Result := CreateEmptyContainer as IJclExtendedList;
|
|
for I := First to Last do
|
|
Result.Add(FElementData[I]);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclExtendedArrayList.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclExtendedArrayList.Create(FSize);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
//=== { TJclExtendedArrayIterator } ===============================================================
|
|
|
|
constructor TJclExtendedArrayIterator.Create(const AOwnList: IJclExtendedList; ACursor: Integer; AValid: Boolean; AStart: TItrStart);
|
|
begin
|
|
inherited Create(AValid);
|
|
FOwnList := AOwnList;
|
|
FStart := AStart;
|
|
FCursor := ACursor;
|
|
end;
|
|
|
|
function TJclExtendedArrayIterator.Add(const AValue: Extended): Boolean;
|
|
begin
|
|
Result := FOwnList.Add(AValue);
|
|
end;
|
|
|
|
procedure TJclExtendedArrayIterator.AssignPropertiesTo(Dest: TJclAbstractIterator);
|
|
var
|
|
ADest: TJclExtendedArrayIterator;
|
|
begin
|
|
inherited AssignPropertiesTo(Dest);
|
|
if Dest is TJclExtendedArrayIterator then
|
|
begin
|
|
ADest := TJclExtendedArrayIterator(Dest);
|
|
ADest.FOwnList := FOwnList;
|
|
ADest.FCursor := FCursor;
|
|
ADest.FStart := FStart;
|
|
end;
|
|
end;
|
|
|
|
function TJclExtendedArrayIterator.CreateEmptyIterator: TJclAbstractIterator;
|
|
begin
|
|
Result := TJclExtendedArrayIterator.Create(FOwnList, FCursor, Valid, FStart);
|
|
end;
|
|
|
|
procedure TJclExtendedArrayIterator.Extract;
|
|
begin
|
|
CheckValid;
|
|
Valid := False;
|
|
FOwnList.ExtractIndex(FCursor);
|
|
end;
|
|
|
|
function TJclExtendedArrayIterator.GetValue: Extended;
|
|
begin
|
|
CheckValid;
|
|
Result := FOwnList.GetValue(FCursor);
|
|
end;
|
|
|
|
function TJclExtendedArrayIterator.HasNext: Boolean;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor < (FOwnList.Size - 1)
|
|
else
|
|
Result := FCursor < FOwnList.Size;
|
|
end;
|
|
|
|
function TJclExtendedArrayIterator.HasPrevious: Boolean;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor > 0
|
|
else
|
|
Result := FCursor >= 0;
|
|
end;
|
|
|
|
function TJclExtendedArrayIterator.Insert(const AValue: Extended): Boolean;
|
|
begin
|
|
CheckValid;
|
|
Result := FOwnList.Insert(FCursor, AValue);
|
|
end;
|
|
|
|
function TJclExtendedArrayIterator.IteratorEquals(const AIterator: IJclExtendedIterator): Boolean;
|
|
var
|
|
Obj: TObject;
|
|
ItrObj: TJclExtendedArrayIterator;
|
|
begin
|
|
Result := False;
|
|
if AIterator = nil then
|
|
Exit;
|
|
Obj := AIterator.GetIteratorReference;
|
|
if Obj is TJclExtendedArrayIterator then
|
|
begin
|
|
ItrObj := TJclExtendedArrayIterator(Obj);
|
|
Result := (FOwnList = ItrObj.FOwnList) and (FCursor = ItrObj.FCursor) and (Valid = ItrObj.Valid);
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function TJclExtendedArrayIterator.MoveNext: Boolean;
|
|
begin
|
|
if Valid then
|
|
Inc(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FCursor < FOwnList.Size;
|
|
end;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
|
|
function TJclExtendedArrayIterator.Next: Extended;
|
|
begin
|
|
if Valid then
|
|
Inc(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FOwnList.GetValue(FCursor);
|
|
end;
|
|
|
|
function TJclExtendedArrayIterator.NextIndex: Integer;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor + 1
|
|
else
|
|
Result := FCursor;
|
|
end;
|
|
|
|
function TJclExtendedArrayIterator.Previous: Extended;
|
|
begin
|
|
if Valid then
|
|
Dec(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FOwnList.GetValue(FCursor);
|
|
end;
|
|
|
|
function TJclExtendedArrayIterator.PreviousIndex: Integer;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor - 1
|
|
else
|
|
Result := FCursor;
|
|
end;
|
|
|
|
procedure TJclExtendedArrayIterator.Remove;
|
|
begin
|
|
CheckValid;
|
|
Valid := False;
|
|
FOwnList.Delete(FCursor);
|
|
end;
|
|
|
|
procedure TJclExtendedArrayIterator.Reset;
|
|
begin
|
|
Valid := False;
|
|
case FStart of
|
|
isFirst:
|
|
FCursor := 0;
|
|
isLast:
|
|
FCursor := FOwnList.Size - 1;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclExtendedArrayIterator.SetValue(const AValue: Extended);
|
|
begin
|
|
CheckValid;
|
|
FOwnList.SetValue(FCursor, AValue);
|
|
end;
|
|
|
|
//=== { TJclIntegerArrayList } ======================================================
|
|
|
|
constructor TJclIntegerArrayList.Create(ACapacity: Integer);
|
|
begin
|
|
inherited Create();
|
|
SetCapacity(ACapacity);
|
|
end;
|
|
|
|
constructor TJclIntegerArrayList.Create(const ACollection: IJclIntegerCollection);
|
|
begin
|
|
inherited Create();
|
|
if ACollection = nil then
|
|
raise EJclNoCollectionError.Create;
|
|
SetCapacity(ACollection.Size);
|
|
AddAll(ACollection);
|
|
end;
|
|
|
|
destructor TJclIntegerArrayList.Destroy;
|
|
begin
|
|
FReadOnly := False;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJclIntegerArrayList.Add(AValue: Integer): Boolean;
|
|
var
|
|
Index: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FAllowDefaultElements or not ItemsEqual(AValue, 0);
|
|
if Result then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for Index := 0 to FSize - 1 do
|
|
if ItemsEqual(AValue, FElementData[Index]) then
|
|
begin
|
|
Result := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
if FSize = FCapacity then
|
|
AutoGrow;
|
|
Result := FSize < FCapacity;
|
|
if Result then
|
|
begin
|
|
FElementData[FSize] := AValue;
|
|
Inc(FSize);
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntegerArrayList.AddAll(const ACollection: IJclIntegerCollection): Boolean;
|
|
var
|
|
It: IJclIntegerIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Add(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclIntegerArrayList.AssignDataTo(Dest: TJclAbstractContainerBase);
|
|
var
|
|
ADest: TJclIntegerArrayList;
|
|
ACollection: IJclIntegerCollection;
|
|
begin
|
|
inherited AssignDataTo(Dest);
|
|
if Dest is TJclIntegerArrayList then
|
|
begin
|
|
ADest := TJclIntegerArrayList(Dest);
|
|
ADest.Clear;
|
|
ADest.AddAll(Self);
|
|
end
|
|
else
|
|
if Supports(IInterface(Dest), IJclIntegerCollection, ACollection) then
|
|
begin
|
|
ACollection.Clear;
|
|
ACollection.AddAll(Self);
|
|
end;
|
|
end;
|
|
|
|
procedure TJclIntegerArrayList.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
for I := 0 to FSize - 1 do
|
|
FreeInteger(FElementData[I]);
|
|
FSize := 0;
|
|
AutoPack;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntegerArrayList.CollectionEquals(const ACollection: IJclIntegerCollection): Boolean;
|
|
var
|
|
I: Integer;
|
|
It: IJclIntegerIterator;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$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 not ItemsEqual(FElementData[I], It.Next) then
|
|
Exit;
|
|
Result := True;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntegerArrayList.Contains(AValue: Integer): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntegerArrayList.ContainsAll(const ACollection: IJclIntegerCollection): Boolean;
|
|
var
|
|
It: IJclIntegerIterator;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := True;
|
|
if ACollection = nil then
|
|
Exit;
|
|
It := ACollection.First;
|
|
while Result and It.HasNext do
|
|
Result := Contains(It.Next);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntegerArrayList.Delete(Index: Integer): Integer;
|
|
var
|
|
Extracted: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Extracted := ExtractIndex(Index);
|
|
Result := FreeInteger(Extracted);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntegerArrayList.Extract(AValue: Integer): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
for I := FSize - 1 downto 0 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
FElementData[I] := 0;
|
|
if I < (FSize - 1) then
|
|
MoveArray(FElementData, I + 1, I, FSize - I);
|
|
Dec(FSize);
|
|
Result := True;
|
|
if FRemoveSingleElement then
|
|
Break;
|
|
end;
|
|
AutoPack;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntegerArrayList.ExtractAll(const ACollection: IJclIntegerCollection): Boolean;
|
|
var
|
|
It: IJclIntegerIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Extract(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntegerArrayList.ExtractIndex(Index: Integer): Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (Index >= 0) and (Index < FSize) then
|
|
begin
|
|
Result := FElementData[Index];
|
|
if Index < (FSize - 1) then
|
|
MoveArray(FElementData, Index + 1, Index, FSize - Index);
|
|
Dec(FSize);
|
|
AutoPack;
|
|
end
|
|
else
|
|
Result := RaiseOutOfBoundsError;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntegerArrayList.First: IJclIntegerIterator;
|
|
begin
|
|
Result := TJclIntegerArrayIterator.Create(Self, 0, False, isFirst);
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function TJclIntegerArrayList.GetEnumerator: IJclIntegerIterator;
|
|
begin
|
|
Result := TJclIntegerArrayIterator.Create(Self, 0, False, isFirst);
|
|
end;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
|
|
function TJclIntegerArrayList.GetValue(Index: Integer): Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := 0;
|
|
if (Index >= 0) and (Index < FSize) then
|
|
Result := FElementData[Index]
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create(IntToStr(Index));
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntegerArrayList.IndexOf(AValue: Integer): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := -1;
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntegerArrayList.Insert(Index: Integer; AValue: Integer): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FAllowDefaultElements or not ItemsEqual(AValue, 0);
|
|
|
|
if (Index < 0) or (Index > FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
|
|
if Result then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(AValue, FElementData[I]) then
|
|
begin
|
|
Result := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
if FSize = FCapacity then
|
|
AutoGrow;
|
|
Result := FSize < FCapacity;
|
|
if Result then
|
|
begin
|
|
if Index < FSize then
|
|
MoveArray(FElementData, Index, Index + 1, FSize - Index);
|
|
FElementData[Index] := AValue;
|
|
Inc(FSize);
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntegerArrayList.InsertAll(Index: Integer; const ACollection: IJclIntegerCollection): Boolean;
|
|
var
|
|
It: IJclIntegerIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if (Index < 0) or (Index > FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
if ACollection = nil then
|
|
Exit;
|
|
|
|
Result := True;
|
|
It := ACollection.Last;
|
|
while It.HasPrevious do
|
|
Result := Insert(Index, It.Previous) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntegerArrayList.IsEmpty: Boolean;
|
|
begin
|
|
Result := FSize = 0;
|
|
end;
|
|
|
|
function TJclIntegerArrayList.Last: IJclIntegerIterator;
|
|
begin
|
|
Result := TJclIntegerArrayIterator.Create(Self, FSize - 1, False, isLast);
|
|
end;
|
|
|
|
function TJclIntegerArrayList.LastIndexOf(AValue: Integer): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := -1;
|
|
for I := FSize - 1 downto 0 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntegerArrayList.RaiseOutOfBoundsError: Integer;
|
|
begin
|
|
raise EJclOutOfBoundsError.Create;
|
|
end;
|
|
|
|
function TJclIntegerArrayList.Remove(AValue: Integer): Boolean;
|
|
var
|
|
Extracted: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := Extract(AValue);
|
|
if Result then
|
|
begin
|
|
Extracted := AValue;
|
|
FreeInteger(Extracted);
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntegerArrayList.RemoveAll(const ACollection: IJclIntegerCollection): Boolean;
|
|
var
|
|
It: IJclIntegerIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Remove(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntegerArrayList.RetainAll(const ACollection: IJclIntegerCollection): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
for I := FSize - 1 downto 0 do
|
|
if not ACollection.Contains(FElementData[I]) then
|
|
Delete(I);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclIntegerArrayList.SetCapacity(Value: Integer);
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if Value >= FSize then
|
|
begin
|
|
SetLength(FElementData, Value);
|
|
inherited SetCapacity(Value);
|
|
end
|
|
else
|
|
raise EJclOutOfBoundsError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclIntegerArrayList.SetValue(Index: Integer; AValue: Integer);
|
|
var
|
|
ReplaceItem: Boolean;
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (Index < 0) or (Index >= FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
ReplaceItem := FAllowDefaultElements or not ItemsEqual(AValue, 0);
|
|
if ReplaceItem then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
ReplaceItem := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
if ReplaceItem then
|
|
begin
|
|
FreeInteger(FElementData[Index]);
|
|
FElementData[Index] := AValue;
|
|
end;
|
|
end;
|
|
if not ReplaceItem then
|
|
Delete(Index);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntegerArrayList.Size: Integer;
|
|
begin
|
|
Result := FSize;
|
|
end;
|
|
|
|
function TJclIntegerArrayList.SubList(First, Count: Integer): IJclIntegerList;
|
|
var
|
|
I: Integer;
|
|
Last: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Last := First + Count - 1;
|
|
if Last >= FSize then
|
|
Last := FSize - 1;
|
|
Result := CreateEmptyContainer as IJclIntegerList;
|
|
for I := First to Last do
|
|
Result.Add(FElementData[I]);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntegerArrayList.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclIntegerArrayList.Create(FSize);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
//=== { TJclIntegerArrayIterator } ===============================================================
|
|
|
|
constructor TJclIntegerArrayIterator.Create(const AOwnList: IJclIntegerList; ACursor: Integer; AValid: Boolean; AStart: TItrStart);
|
|
begin
|
|
inherited Create(AValid);
|
|
FOwnList := AOwnList;
|
|
FStart := AStart;
|
|
FCursor := ACursor;
|
|
end;
|
|
|
|
function TJclIntegerArrayIterator.Add(AValue: Integer): Boolean;
|
|
begin
|
|
Result := FOwnList.Add(AValue);
|
|
end;
|
|
|
|
procedure TJclIntegerArrayIterator.AssignPropertiesTo(Dest: TJclAbstractIterator);
|
|
var
|
|
ADest: TJclIntegerArrayIterator;
|
|
begin
|
|
inherited AssignPropertiesTo(Dest);
|
|
if Dest is TJclIntegerArrayIterator then
|
|
begin
|
|
ADest := TJclIntegerArrayIterator(Dest);
|
|
ADest.FOwnList := FOwnList;
|
|
ADest.FCursor := FCursor;
|
|
ADest.FStart := FStart;
|
|
end;
|
|
end;
|
|
|
|
function TJclIntegerArrayIterator.CreateEmptyIterator: TJclAbstractIterator;
|
|
begin
|
|
Result := TJclIntegerArrayIterator.Create(FOwnList, FCursor, Valid, FStart);
|
|
end;
|
|
|
|
procedure TJclIntegerArrayIterator.Extract;
|
|
begin
|
|
CheckValid;
|
|
Valid := False;
|
|
FOwnList.ExtractIndex(FCursor);
|
|
end;
|
|
|
|
function TJclIntegerArrayIterator.GetValue: Integer;
|
|
begin
|
|
CheckValid;
|
|
Result := FOwnList.GetValue(FCursor);
|
|
end;
|
|
|
|
function TJclIntegerArrayIterator.HasNext: Boolean;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor < (FOwnList.Size - 1)
|
|
else
|
|
Result := FCursor < FOwnList.Size;
|
|
end;
|
|
|
|
function TJclIntegerArrayIterator.HasPrevious: Boolean;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor > 0
|
|
else
|
|
Result := FCursor >= 0;
|
|
end;
|
|
|
|
function TJclIntegerArrayIterator.Insert(AValue: Integer): Boolean;
|
|
begin
|
|
CheckValid;
|
|
Result := FOwnList.Insert(FCursor, AValue);
|
|
end;
|
|
|
|
function TJclIntegerArrayIterator.IteratorEquals(const AIterator: IJclIntegerIterator): Boolean;
|
|
var
|
|
Obj: TObject;
|
|
ItrObj: TJclIntegerArrayIterator;
|
|
begin
|
|
Result := False;
|
|
if AIterator = nil then
|
|
Exit;
|
|
Obj := AIterator.GetIteratorReference;
|
|
if Obj is TJclIntegerArrayIterator then
|
|
begin
|
|
ItrObj := TJclIntegerArrayIterator(Obj);
|
|
Result := (FOwnList = ItrObj.FOwnList) and (FCursor = ItrObj.FCursor) and (Valid = ItrObj.Valid);
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function TJclIntegerArrayIterator.MoveNext: Boolean;
|
|
begin
|
|
if Valid then
|
|
Inc(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FCursor < FOwnList.Size;
|
|
end;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
|
|
function TJclIntegerArrayIterator.Next: Integer;
|
|
begin
|
|
if Valid then
|
|
Inc(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FOwnList.GetValue(FCursor);
|
|
end;
|
|
|
|
function TJclIntegerArrayIterator.NextIndex: Integer;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor + 1
|
|
else
|
|
Result := FCursor;
|
|
end;
|
|
|
|
function TJclIntegerArrayIterator.Previous: Integer;
|
|
begin
|
|
if Valid then
|
|
Dec(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FOwnList.GetValue(FCursor);
|
|
end;
|
|
|
|
function TJclIntegerArrayIterator.PreviousIndex: Integer;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor - 1
|
|
else
|
|
Result := FCursor;
|
|
end;
|
|
|
|
procedure TJclIntegerArrayIterator.Remove;
|
|
begin
|
|
CheckValid;
|
|
Valid := False;
|
|
FOwnList.Delete(FCursor);
|
|
end;
|
|
|
|
procedure TJclIntegerArrayIterator.Reset;
|
|
begin
|
|
Valid := False;
|
|
case FStart of
|
|
isFirst:
|
|
FCursor := 0;
|
|
isLast:
|
|
FCursor := FOwnList.Size - 1;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclIntegerArrayIterator.SetValue(AValue: Integer);
|
|
begin
|
|
CheckValid;
|
|
FOwnList.SetValue(FCursor, AValue);
|
|
end;
|
|
|
|
//=== { TJclCardinalArrayList } ======================================================
|
|
|
|
constructor TJclCardinalArrayList.Create(ACapacity: Integer);
|
|
begin
|
|
inherited Create();
|
|
SetCapacity(ACapacity);
|
|
end;
|
|
|
|
constructor TJclCardinalArrayList.Create(const ACollection: IJclCardinalCollection);
|
|
begin
|
|
inherited Create();
|
|
if ACollection = nil then
|
|
raise EJclNoCollectionError.Create;
|
|
SetCapacity(ACollection.Size);
|
|
AddAll(ACollection);
|
|
end;
|
|
|
|
destructor TJclCardinalArrayList.Destroy;
|
|
begin
|
|
FReadOnly := False;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJclCardinalArrayList.Add(AValue: Cardinal): Boolean;
|
|
var
|
|
Index: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FAllowDefaultElements or not ItemsEqual(AValue, 0);
|
|
if Result then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for Index := 0 to FSize - 1 do
|
|
if ItemsEqual(AValue, FElementData[Index]) then
|
|
begin
|
|
Result := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
if FSize = FCapacity then
|
|
AutoGrow;
|
|
Result := FSize < FCapacity;
|
|
if Result then
|
|
begin
|
|
FElementData[FSize] := AValue;
|
|
Inc(FSize);
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclCardinalArrayList.AddAll(const ACollection: IJclCardinalCollection): Boolean;
|
|
var
|
|
It: IJclCardinalIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Add(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclCardinalArrayList.AssignDataTo(Dest: TJclAbstractContainerBase);
|
|
var
|
|
ADest: TJclCardinalArrayList;
|
|
ACollection: IJclCardinalCollection;
|
|
begin
|
|
inherited AssignDataTo(Dest);
|
|
if Dest is TJclCardinalArrayList then
|
|
begin
|
|
ADest := TJclCardinalArrayList(Dest);
|
|
ADest.Clear;
|
|
ADest.AddAll(Self);
|
|
end
|
|
else
|
|
if Supports(IInterface(Dest), IJclCardinalCollection, ACollection) then
|
|
begin
|
|
ACollection.Clear;
|
|
ACollection.AddAll(Self);
|
|
end;
|
|
end;
|
|
|
|
procedure TJclCardinalArrayList.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
for I := 0 to FSize - 1 do
|
|
FreeCardinal(FElementData[I]);
|
|
FSize := 0;
|
|
AutoPack;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclCardinalArrayList.CollectionEquals(const ACollection: IJclCardinalCollection): Boolean;
|
|
var
|
|
I: Integer;
|
|
It: IJclCardinalIterator;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$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 not ItemsEqual(FElementData[I], It.Next) then
|
|
Exit;
|
|
Result := True;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclCardinalArrayList.Contains(AValue: Cardinal): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclCardinalArrayList.ContainsAll(const ACollection: IJclCardinalCollection): Boolean;
|
|
var
|
|
It: IJclCardinalIterator;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := True;
|
|
if ACollection = nil then
|
|
Exit;
|
|
It := ACollection.First;
|
|
while Result and It.HasNext do
|
|
Result := Contains(It.Next);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclCardinalArrayList.Delete(Index: Integer): Cardinal;
|
|
var
|
|
Extracted: Cardinal;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Extracted := ExtractIndex(Index);
|
|
Result := FreeCardinal(Extracted);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclCardinalArrayList.Extract(AValue: Cardinal): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
for I := FSize - 1 downto 0 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
FElementData[I] := 0;
|
|
if I < (FSize - 1) then
|
|
MoveArray(FElementData, I + 1, I, FSize - I);
|
|
Dec(FSize);
|
|
Result := True;
|
|
if FRemoveSingleElement then
|
|
Break;
|
|
end;
|
|
AutoPack;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclCardinalArrayList.ExtractAll(const ACollection: IJclCardinalCollection): Boolean;
|
|
var
|
|
It: IJclCardinalIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Extract(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclCardinalArrayList.ExtractIndex(Index: Integer): Cardinal;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (Index >= 0) and (Index < FSize) then
|
|
begin
|
|
Result := FElementData[Index];
|
|
if Index < (FSize - 1) then
|
|
MoveArray(FElementData, Index + 1, Index, FSize - Index);
|
|
Dec(FSize);
|
|
AutoPack;
|
|
end
|
|
else
|
|
Result := RaiseOutOfBoundsError;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclCardinalArrayList.First: IJclCardinalIterator;
|
|
begin
|
|
Result := TJclCardinalArrayIterator.Create(Self, 0, False, isFirst);
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function TJclCardinalArrayList.GetEnumerator: IJclCardinalIterator;
|
|
begin
|
|
Result := TJclCardinalArrayIterator.Create(Self, 0, False, isFirst);
|
|
end;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
|
|
function TJclCardinalArrayList.GetValue(Index: Integer): Cardinal;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := 0;
|
|
if (Index >= 0) and (Index < FSize) then
|
|
Result := FElementData[Index]
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create(IntToStr(Index));
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclCardinalArrayList.IndexOf(AValue: Cardinal): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := -1;
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclCardinalArrayList.Insert(Index: Integer; AValue: Cardinal): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FAllowDefaultElements or not ItemsEqual(AValue, 0);
|
|
|
|
if (Index < 0) or (Index > FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
|
|
if Result then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(AValue, FElementData[I]) then
|
|
begin
|
|
Result := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
if FSize = FCapacity then
|
|
AutoGrow;
|
|
Result := FSize < FCapacity;
|
|
if Result then
|
|
begin
|
|
if Index < FSize then
|
|
MoveArray(FElementData, Index, Index + 1, FSize - Index);
|
|
FElementData[Index] := AValue;
|
|
Inc(FSize);
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclCardinalArrayList.InsertAll(Index: Integer; const ACollection: IJclCardinalCollection): Boolean;
|
|
var
|
|
It: IJclCardinalIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if (Index < 0) or (Index > FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
if ACollection = nil then
|
|
Exit;
|
|
|
|
Result := True;
|
|
It := ACollection.Last;
|
|
while It.HasPrevious do
|
|
Result := Insert(Index, It.Previous) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclCardinalArrayList.IsEmpty: Boolean;
|
|
begin
|
|
Result := FSize = 0;
|
|
end;
|
|
|
|
function TJclCardinalArrayList.Last: IJclCardinalIterator;
|
|
begin
|
|
Result := TJclCardinalArrayIterator.Create(Self, FSize - 1, False, isLast);
|
|
end;
|
|
|
|
function TJclCardinalArrayList.LastIndexOf(AValue: Cardinal): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := -1;
|
|
for I := FSize - 1 downto 0 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclCardinalArrayList.RaiseOutOfBoundsError: Cardinal;
|
|
begin
|
|
raise EJclOutOfBoundsError.Create;
|
|
end;
|
|
|
|
function TJclCardinalArrayList.Remove(AValue: Cardinal): Boolean;
|
|
var
|
|
Extracted: Cardinal;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := Extract(AValue);
|
|
if Result then
|
|
begin
|
|
Extracted := AValue;
|
|
FreeCardinal(Extracted);
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclCardinalArrayList.RemoveAll(const ACollection: IJclCardinalCollection): Boolean;
|
|
var
|
|
It: IJclCardinalIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Remove(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclCardinalArrayList.RetainAll(const ACollection: IJclCardinalCollection): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
for I := FSize - 1 downto 0 do
|
|
if not ACollection.Contains(FElementData[I]) then
|
|
Delete(I);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclCardinalArrayList.SetCapacity(Value: Integer);
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if Value >= FSize then
|
|
begin
|
|
SetLength(FElementData, Value);
|
|
inherited SetCapacity(Value);
|
|
end
|
|
else
|
|
raise EJclOutOfBoundsError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclCardinalArrayList.SetValue(Index: Integer; AValue: Cardinal);
|
|
var
|
|
ReplaceItem: Boolean;
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (Index < 0) or (Index >= FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
ReplaceItem := FAllowDefaultElements or not ItemsEqual(AValue, 0);
|
|
if ReplaceItem then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
ReplaceItem := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
if ReplaceItem then
|
|
begin
|
|
FreeCardinal(FElementData[Index]);
|
|
FElementData[Index] := AValue;
|
|
end;
|
|
end;
|
|
if not ReplaceItem then
|
|
Delete(Index);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclCardinalArrayList.Size: Integer;
|
|
begin
|
|
Result := FSize;
|
|
end;
|
|
|
|
function TJclCardinalArrayList.SubList(First, Count: Integer): IJclCardinalList;
|
|
var
|
|
I: Integer;
|
|
Last: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Last := First + Count - 1;
|
|
if Last >= FSize then
|
|
Last := FSize - 1;
|
|
Result := CreateEmptyContainer as IJclCardinalList;
|
|
for I := First to Last do
|
|
Result.Add(FElementData[I]);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclCardinalArrayList.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclCardinalArrayList.Create(FSize);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
//=== { TJclCardinalArrayIterator } ===============================================================
|
|
|
|
constructor TJclCardinalArrayIterator.Create(const AOwnList: IJclCardinalList; ACursor: Integer; AValid: Boolean; AStart: TItrStart);
|
|
begin
|
|
inherited Create(AValid);
|
|
FOwnList := AOwnList;
|
|
FStart := AStart;
|
|
FCursor := ACursor;
|
|
end;
|
|
|
|
function TJclCardinalArrayIterator.Add(AValue: Cardinal): Boolean;
|
|
begin
|
|
Result := FOwnList.Add(AValue);
|
|
end;
|
|
|
|
procedure TJclCardinalArrayIterator.AssignPropertiesTo(Dest: TJclAbstractIterator);
|
|
var
|
|
ADest: TJclCardinalArrayIterator;
|
|
begin
|
|
inherited AssignPropertiesTo(Dest);
|
|
if Dest is TJclCardinalArrayIterator then
|
|
begin
|
|
ADest := TJclCardinalArrayIterator(Dest);
|
|
ADest.FOwnList := FOwnList;
|
|
ADest.FCursor := FCursor;
|
|
ADest.FStart := FStart;
|
|
end;
|
|
end;
|
|
|
|
function TJclCardinalArrayIterator.CreateEmptyIterator: TJclAbstractIterator;
|
|
begin
|
|
Result := TJclCardinalArrayIterator.Create(FOwnList, FCursor, Valid, FStart);
|
|
end;
|
|
|
|
procedure TJclCardinalArrayIterator.Extract;
|
|
begin
|
|
CheckValid;
|
|
Valid := False;
|
|
FOwnList.ExtractIndex(FCursor);
|
|
end;
|
|
|
|
function TJclCardinalArrayIterator.GetValue: Cardinal;
|
|
begin
|
|
CheckValid;
|
|
Result := FOwnList.GetValue(FCursor);
|
|
end;
|
|
|
|
function TJclCardinalArrayIterator.HasNext: Boolean;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor < (FOwnList.Size - 1)
|
|
else
|
|
Result := FCursor < FOwnList.Size;
|
|
end;
|
|
|
|
function TJclCardinalArrayIterator.HasPrevious: Boolean;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor > 0
|
|
else
|
|
Result := FCursor >= 0;
|
|
end;
|
|
|
|
function TJclCardinalArrayIterator.Insert(AValue: Cardinal): Boolean;
|
|
begin
|
|
CheckValid;
|
|
Result := FOwnList.Insert(FCursor, AValue);
|
|
end;
|
|
|
|
function TJclCardinalArrayIterator.IteratorEquals(const AIterator: IJclCardinalIterator): Boolean;
|
|
var
|
|
Obj: TObject;
|
|
ItrObj: TJclCardinalArrayIterator;
|
|
begin
|
|
Result := False;
|
|
if AIterator = nil then
|
|
Exit;
|
|
Obj := AIterator.GetIteratorReference;
|
|
if Obj is TJclCardinalArrayIterator then
|
|
begin
|
|
ItrObj := TJclCardinalArrayIterator(Obj);
|
|
Result := (FOwnList = ItrObj.FOwnList) and (FCursor = ItrObj.FCursor) and (Valid = ItrObj.Valid);
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function TJclCardinalArrayIterator.MoveNext: Boolean;
|
|
begin
|
|
if Valid then
|
|
Inc(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FCursor < FOwnList.Size;
|
|
end;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
|
|
function TJclCardinalArrayIterator.Next: Cardinal;
|
|
begin
|
|
if Valid then
|
|
Inc(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FOwnList.GetValue(FCursor);
|
|
end;
|
|
|
|
function TJclCardinalArrayIterator.NextIndex: Integer;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor + 1
|
|
else
|
|
Result := FCursor;
|
|
end;
|
|
|
|
function TJclCardinalArrayIterator.Previous: Cardinal;
|
|
begin
|
|
if Valid then
|
|
Dec(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FOwnList.GetValue(FCursor);
|
|
end;
|
|
|
|
function TJclCardinalArrayIterator.PreviousIndex: Integer;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor - 1
|
|
else
|
|
Result := FCursor;
|
|
end;
|
|
|
|
procedure TJclCardinalArrayIterator.Remove;
|
|
begin
|
|
CheckValid;
|
|
Valid := False;
|
|
FOwnList.Delete(FCursor);
|
|
end;
|
|
|
|
procedure TJclCardinalArrayIterator.Reset;
|
|
begin
|
|
Valid := False;
|
|
case FStart of
|
|
isFirst:
|
|
FCursor := 0;
|
|
isLast:
|
|
FCursor := FOwnList.Size - 1;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclCardinalArrayIterator.SetValue(AValue: Cardinal);
|
|
begin
|
|
CheckValid;
|
|
FOwnList.SetValue(FCursor, AValue);
|
|
end;
|
|
|
|
//=== { TJclInt64ArrayList } ======================================================
|
|
|
|
constructor TJclInt64ArrayList.Create(ACapacity: Integer);
|
|
begin
|
|
inherited Create();
|
|
SetCapacity(ACapacity);
|
|
end;
|
|
|
|
constructor TJclInt64ArrayList.Create(const ACollection: IJclInt64Collection);
|
|
begin
|
|
inherited Create();
|
|
if ACollection = nil then
|
|
raise EJclNoCollectionError.Create;
|
|
SetCapacity(ACollection.Size);
|
|
AddAll(ACollection);
|
|
end;
|
|
|
|
destructor TJclInt64ArrayList.Destroy;
|
|
begin
|
|
FReadOnly := False;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJclInt64ArrayList.Add(const AValue: Int64): Boolean;
|
|
var
|
|
Index: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FAllowDefaultElements or not ItemsEqual(AValue, 0);
|
|
if Result then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for Index := 0 to FSize - 1 do
|
|
if ItemsEqual(AValue, FElementData[Index]) then
|
|
begin
|
|
Result := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
if FSize = FCapacity then
|
|
AutoGrow;
|
|
Result := FSize < FCapacity;
|
|
if Result then
|
|
begin
|
|
FElementData[FSize] := AValue;
|
|
Inc(FSize);
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclInt64ArrayList.AddAll(const ACollection: IJclInt64Collection): Boolean;
|
|
var
|
|
It: IJclInt64Iterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Add(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclInt64ArrayList.AssignDataTo(Dest: TJclAbstractContainerBase);
|
|
var
|
|
ADest: TJclInt64ArrayList;
|
|
ACollection: IJclInt64Collection;
|
|
begin
|
|
inherited AssignDataTo(Dest);
|
|
if Dest is TJclInt64ArrayList then
|
|
begin
|
|
ADest := TJclInt64ArrayList(Dest);
|
|
ADest.Clear;
|
|
ADest.AddAll(Self);
|
|
end
|
|
else
|
|
if Supports(IInterface(Dest), IJclInt64Collection, ACollection) then
|
|
begin
|
|
ACollection.Clear;
|
|
ACollection.AddAll(Self);
|
|
end;
|
|
end;
|
|
|
|
procedure TJclInt64ArrayList.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
for I := 0 to FSize - 1 do
|
|
FreeInt64(FElementData[I]);
|
|
FSize := 0;
|
|
AutoPack;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclInt64ArrayList.CollectionEquals(const ACollection: IJclInt64Collection): Boolean;
|
|
var
|
|
I: Integer;
|
|
It: IJclInt64Iterator;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$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 not ItemsEqual(FElementData[I], It.Next) then
|
|
Exit;
|
|
Result := True;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclInt64ArrayList.Contains(const AValue: Int64): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclInt64ArrayList.ContainsAll(const ACollection: IJclInt64Collection): Boolean;
|
|
var
|
|
It: IJclInt64Iterator;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := True;
|
|
if ACollection = nil then
|
|
Exit;
|
|
It := ACollection.First;
|
|
while Result and It.HasNext do
|
|
Result := Contains(It.Next);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclInt64ArrayList.Delete(Index: Integer): Int64;
|
|
var
|
|
Extracted: Int64;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Extracted := ExtractIndex(Index);
|
|
Result := FreeInt64(Extracted);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclInt64ArrayList.Extract(const AValue: Int64): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
for I := FSize - 1 downto 0 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
FElementData[I] := 0;
|
|
if I < (FSize - 1) then
|
|
MoveArray(FElementData, I + 1, I, FSize - I);
|
|
Dec(FSize);
|
|
Result := True;
|
|
if FRemoveSingleElement then
|
|
Break;
|
|
end;
|
|
AutoPack;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclInt64ArrayList.ExtractAll(const ACollection: IJclInt64Collection): Boolean;
|
|
var
|
|
It: IJclInt64Iterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Extract(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclInt64ArrayList.ExtractIndex(Index: Integer): Int64;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (Index >= 0) and (Index < FSize) then
|
|
begin
|
|
Result := FElementData[Index];
|
|
if Index < (FSize - 1) then
|
|
MoveArray(FElementData, Index + 1, Index, FSize - Index);
|
|
Dec(FSize);
|
|
AutoPack;
|
|
end
|
|
else
|
|
Result := RaiseOutOfBoundsError;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclInt64ArrayList.First: IJclInt64Iterator;
|
|
begin
|
|
Result := TJclInt64ArrayIterator.Create(Self, 0, False, isFirst);
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function TJclInt64ArrayList.GetEnumerator: IJclInt64Iterator;
|
|
begin
|
|
Result := TJclInt64ArrayIterator.Create(Self, 0, False, isFirst);
|
|
end;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
|
|
function TJclInt64ArrayList.GetValue(Index: Integer): Int64;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := 0;
|
|
if (Index >= 0) and (Index < FSize) then
|
|
Result := FElementData[Index]
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create(IntToStr(Index));
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclInt64ArrayList.IndexOf(const AValue: Int64): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := -1;
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclInt64ArrayList.Insert(Index: Integer; const AValue: Int64): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FAllowDefaultElements or not ItemsEqual(AValue, 0);
|
|
|
|
if (Index < 0) or (Index > FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
|
|
if Result then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(AValue, FElementData[I]) then
|
|
begin
|
|
Result := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
if FSize = FCapacity then
|
|
AutoGrow;
|
|
Result := FSize < FCapacity;
|
|
if Result then
|
|
begin
|
|
if Index < FSize then
|
|
MoveArray(FElementData, Index, Index + 1, FSize - Index);
|
|
FElementData[Index] := AValue;
|
|
Inc(FSize);
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclInt64ArrayList.InsertAll(Index: Integer; const ACollection: IJclInt64Collection): Boolean;
|
|
var
|
|
It: IJclInt64Iterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if (Index < 0) or (Index > FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
if ACollection = nil then
|
|
Exit;
|
|
|
|
Result := True;
|
|
It := ACollection.Last;
|
|
while It.HasPrevious do
|
|
Result := Insert(Index, It.Previous) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclInt64ArrayList.IsEmpty: Boolean;
|
|
begin
|
|
Result := FSize = 0;
|
|
end;
|
|
|
|
function TJclInt64ArrayList.Last: IJclInt64Iterator;
|
|
begin
|
|
Result := TJclInt64ArrayIterator.Create(Self, FSize - 1, False, isLast);
|
|
end;
|
|
|
|
function TJclInt64ArrayList.LastIndexOf(const AValue: Int64): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := -1;
|
|
for I := FSize - 1 downto 0 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclInt64ArrayList.RaiseOutOfBoundsError: Int64;
|
|
begin
|
|
raise EJclOutOfBoundsError.Create;
|
|
end;
|
|
|
|
function TJclInt64ArrayList.Remove(const AValue: Int64): Boolean;
|
|
var
|
|
Extracted: Int64;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := Extract(AValue);
|
|
if Result then
|
|
begin
|
|
Extracted := AValue;
|
|
FreeInt64(Extracted);
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclInt64ArrayList.RemoveAll(const ACollection: IJclInt64Collection): Boolean;
|
|
var
|
|
It: IJclInt64Iterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Remove(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclInt64ArrayList.RetainAll(const ACollection: IJclInt64Collection): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
for I := FSize - 1 downto 0 do
|
|
if not ACollection.Contains(FElementData[I]) then
|
|
Delete(I);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclInt64ArrayList.SetCapacity(Value: Integer);
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if Value >= FSize then
|
|
begin
|
|
SetLength(FElementData, Value);
|
|
inherited SetCapacity(Value);
|
|
end
|
|
else
|
|
raise EJclOutOfBoundsError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclInt64ArrayList.SetValue(Index: Integer; const AValue: Int64);
|
|
var
|
|
ReplaceItem: Boolean;
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (Index < 0) or (Index >= FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
ReplaceItem := FAllowDefaultElements or not ItemsEqual(AValue, 0);
|
|
if ReplaceItem then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AValue) then
|
|
begin
|
|
ReplaceItem := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
if ReplaceItem then
|
|
begin
|
|
FreeInt64(FElementData[Index]);
|
|
FElementData[Index] := AValue;
|
|
end;
|
|
end;
|
|
if not ReplaceItem then
|
|
Delete(Index);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclInt64ArrayList.Size: Integer;
|
|
begin
|
|
Result := FSize;
|
|
end;
|
|
|
|
function TJclInt64ArrayList.SubList(First, Count: Integer): IJclInt64List;
|
|
var
|
|
I: Integer;
|
|
Last: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Last := First + Count - 1;
|
|
if Last >= FSize then
|
|
Last := FSize - 1;
|
|
Result := CreateEmptyContainer as IJclInt64List;
|
|
for I := First to Last do
|
|
Result.Add(FElementData[I]);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclInt64ArrayList.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclInt64ArrayList.Create(FSize);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
//=== { TJclInt64ArrayIterator } ===============================================================
|
|
|
|
constructor TJclInt64ArrayIterator.Create(const AOwnList: IJclInt64List; ACursor: Integer; AValid: Boolean; AStart: TItrStart);
|
|
begin
|
|
inherited Create(AValid);
|
|
FOwnList := AOwnList;
|
|
FStart := AStart;
|
|
FCursor := ACursor;
|
|
end;
|
|
|
|
function TJclInt64ArrayIterator.Add(const AValue: Int64): Boolean;
|
|
begin
|
|
Result := FOwnList.Add(AValue);
|
|
end;
|
|
|
|
procedure TJclInt64ArrayIterator.AssignPropertiesTo(Dest: TJclAbstractIterator);
|
|
var
|
|
ADest: TJclInt64ArrayIterator;
|
|
begin
|
|
inherited AssignPropertiesTo(Dest);
|
|
if Dest is TJclInt64ArrayIterator then
|
|
begin
|
|
ADest := TJclInt64ArrayIterator(Dest);
|
|
ADest.FOwnList := FOwnList;
|
|
ADest.FCursor := FCursor;
|
|
ADest.FStart := FStart;
|
|
end;
|
|
end;
|
|
|
|
function TJclInt64ArrayIterator.CreateEmptyIterator: TJclAbstractIterator;
|
|
begin
|
|
Result := TJclInt64ArrayIterator.Create(FOwnList, FCursor, Valid, FStart);
|
|
end;
|
|
|
|
procedure TJclInt64ArrayIterator.Extract;
|
|
begin
|
|
CheckValid;
|
|
Valid := False;
|
|
FOwnList.ExtractIndex(FCursor);
|
|
end;
|
|
|
|
function TJclInt64ArrayIterator.GetValue: Int64;
|
|
begin
|
|
CheckValid;
|
|
Result := FOwnList.GetValue(FCursor);
|
|
end;
|
|
|
|
function TJclInt64ArrayIterator.HasNext: Boolean;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor < (FOwnList.Size - 1)
|
|
else
|
|
Result := FCursor < FOwnList.Size;
|
|
end;
|
|
|
|
function TJclInt64ArrayIterator.HasPrevious: Boolean;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor > 0
|
|
else
|
|
Result := FCursor >= 0;
|
|
end;
|
|
|
|
function TJclInt64ArrayIterator.Insert(const AValue: Int64): Boolean;
|
|
begin
|
|
CheckValid;
|
|
Result := FOwnList.Insert(FCursor, AValue);
|
|
end;
|
|
|
|
function TJclInt64ArrayIterator.IteratorEquals(const AIterator: IJclInt64Iterator): Boolean;
|
|
var
|
|
Obj: TObject;
|
|
ItrObj: TJclInt64ArrayIterator;
|
|
begin
|
|
Result := False;
|
|
if AIterator = nil then
|
|
Exit;
|
|
Obj := AIterator.GetIteratorReference;
|
|
if Obj is TJclInt64ArrayIterator then
|
|
begin
|
|
ItrObj := TJclInt64ArrayIterator(Obj);
|
|
Result := (FOwnList = ItrObj.FOwnList) and (FCursor = ItrObj.FCursor) and (Valid = ItrObj.Valid);
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function TJclInt64ArrayIterator.MoveNext: Boolean;
|
|
begin
|
|
if Valid then
|
|
Inc(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FCursor < FOwnList.Size;
|
|
end;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
|
|
function TJclInt64ArrayIterator.Next: Int64;
|
|
begin
|
|
if Valid then
|
|
Inc(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FOwnList.GetValue(FCursor);
|
|
end;
|
|
|
|
function TJclInt64ArrayIterator.NextIndex: Integer;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor + 1
|
|
else
|
|
Result := FCursor;
|
|
end;
|
|
|
|
function TJclInt64ArrayIterator.Previous: Int64;
|
|
begin
|
|
if Valid then
|
|
Dec(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FOwnList.GetValue(FCursor);
|
|
end;
|
|
|
|
function TJclInt64ArrayIterator.PreviousIndex: Integer;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor - 1
|
|
else
|
|
Result := FCursor;
|
|
end;
|
|
|
|
procedure TJclInt64ArrayIterator.Remove;
|
|
begin
|
|
CheckValid;
|
|
Valid := False;
|
|
FOwnList.Delete(FCursor);
|
|
end;
|
|
|
|
procedure TJclInt64ArrayIterator.Reset;
|
|
begin
|
|
Valid := False;
|
|
case FStart of
|
|
isFirst:
|
|
FCursor := 0;
|
|
isLast:
|
|
FCursor := FOwnList.Size - 1;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclInt64ArrayIterator.SetValue(const AValue: Int64);
|
|
begin
|
|
CheckValid;
|
|
FOwnList.SetValue(FCursor, AValue);
|
|
end;
|
|
|
|
//=== { TJclPtrArrayList } ======================================================
|
|
|
|
constructor TJclPtrArrayList.Create(ACapacity: Integer);
|
|
begin
|
|
inherited Create();
|
|
SetCapacity(ACapacity);
|
|
end;
|
|
|
|
constructor TJclPtrArrayList.Create(const ACollection: IJclPtrCollection);
|
|
begin
|
|
inherited Create();
|
|
if ACollection = nil then
|
|
raise EJclNoCollectionError.Create;
|
|
SetCapacity(ACollection.Size);
|
|
AddAll(ACollection);
|
|
end;
|
|
|
|
destructor TJclPtrArrayList.Destroy;
|
|
begin
|
|
FReadOnly := False;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJclPtrArrayList.Add(APtr: Pointer): Boolean;
|
|
var
|
|
Index: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FAllowDefaultElements or not ItemsEqual(APtr, nil);
|
|
if Result then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for Index := 0 to FSize - 1 do
|
|
if ItemsEqual(APtr, FElementData[Index]) then
|
|
begin
|
|
Result := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
if FSize = FCapacity then
|
|
AutoGrow;
|
|
Result := FSize < FCapacity;
|
|
if Result then
|
|
begin
|
|
FElementData[FSize] := APtr;
|
|
Inc(FSize);
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclPtrArrayList.AddAll(const ACollection: IJclPtrCollection): Boolean;
|
|
var
|
|
It: IJclPtrIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Add(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclPtrArrayList.AssignDataTo(Dest: TJclAbstractContainerBase);
|
|
var
|
|
ADest: TJclPtrArrayList;
|
|
ACollection: IJclPtrCollection;
|
|
begin
|
|
inherited AssignDataTo(Dest);
|
|
if Dest is TJclPtrArrayList then
|
|
begin
|
|
ADest := TJclPtrArrayList(Dest);
|
|
ADest.Clear;
|
|
ADest.AddAll(Self);
|
|
end
|
|
else
|
|
if Supports(IInterface(Dest), IJclPtrCollection, ACollection) then
|
|
begin
|
|
ACollection.Clear;
|
|
ACollection.AddAll(Self);
|
|
end;
|
|
end;
|
|
|
|
procedure TJclPtrArrayList.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
for I := 0 to FSize - 1 do
|
|
FreePointer(FElementData[I]);
|
|
FSize := 0;
|
|
AutoPack;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclPtrArrayList.CollectionEquals(const ACollection: IJclPtrCollection): Boolean;
|
|
var
|
|
I: Integer;
|
|
It: IJclPtrIterator;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$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 not ItemsEqual(FElementData[I], It.Next) then
|
|
Exit;
|
|
Result := True;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclPtrArrayList.Contains(APtr: Pointer): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], APtr) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclPtrArrayList.ContainsAll(const ACollection: IJclPtrCollection): Boolean;
|
|
var
|
|
It: IJclPtrIterator;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := True;
|
|
if ACollection = nil then
|
|
Exit;
|
|
It := ACollection.First;
|
|
while Result and It.HasNext do
|
|
Result := Contains(It.Next);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclPtrArrayList.Delete(Index: Integer): Pointer;
|
|
var
|
|
Extracted: Pointer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Extracted := ExtractIndex(Index);
|
|
Result := FreePointer(Extracted);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclPtrArrayList.Extract(APtr: Pointer): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
for I := FSize - 1 downto 0 do
|
|
if ItemsEqual(FElementData[I], APtr) then
|
|
begin
|
|
FElementData[I] := nil;
|
|
if I < (FSize - 1) then
|
|
MoveArray(FElementData, I + 1, I, FSize - I);
|
|
Dec(FSize);
|
|
Result := True;
|
|
if FRemoveSingleElement then
|
|
Break;
|
|
end;
|
|
AutoPack;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclPtrArrayList.ExtractAll(const ACollection: IJclPtrCollection): Boolean;
|
|
var
|
|
It: IJclPtrIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Extract(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclPtrArrayList.ExtractIndex(Index: Integer): Pointer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (Index >= 0) and (Index < FSize) then
|
|
begin
|
|
Result := FElementData[Index];
|
|
if Index < (FSize - 1) then
|
|
MoveArray(FElementData, Index + 1, Index, FSize - Index);
|
|
Dec(FSize);
|
|
AutoPack;
|
|
end
|
|
else
|
|
Result := RaiseOutOfBoundsError;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclPtrArrayList.First: IJclPtrIterator;
|
|
begin
|
|
Result := TJclPtrArrayIterator.Create(Self, 0, False, isFirst);
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function TJclPtrArrayList.GetEnumerator: IJclPtrIterator;
|
|
begin
|
|
Result := TJclPtrArrayIterator.Create(Self, 0, False, isFirst);
|
|
end;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
|
|
function TJclPtrArrayList.GetPointer(Index: Integer): Pointer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := nil;
|
|
if (Index >= 0) and (Index < FSize) then
|
|
Result := FElementData[Index]
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create(IntToStr(Index));
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclPtrArrayList.IndexOf(APtr: Pointer): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := -1;
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], APtr) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclPtrArrayList.Insert(Index: Integer; APtr: Pointer): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FAllowDefaultElements or not ItemsEqual(APtr, nil);
|
|
|
|
if (Index < 0) or (Index > FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
|
|
if Result then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(APtr, FElementData[I]) then
|
|
begin
|
|
Result := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
if FSize = FCapacity then
|
|
AutoGrow;
|
|
Result := FSize < FCapacity;
|
|
if Result then
|
|
begin
|
|
if Index < FSize then
|
|
MoveArray(FElementData, Index, Index + 1, FSize - Index);
|
|
FElementData[Index] := APtr;
|
|
Inc(FSize);
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclPtrArrayList.InsertAll(Index: Integer; const ACollection: IJclPtrCollection): Boolean;
|
|
var
|
|
It: IJclPtrIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if (Index < 0) or (Index > FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
if ACollection = nil then
|
|
Exit;
|
|
|
|
Result := True;
|
|
It := ACollection.Last;
|
|
while It.HasPrevious do
|
|
Result := Insert(Index, It.Previous) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclPtrArrayList.IsEmpty: Boolean;
|
|
begin
|
|
Result := FSize = 0;
|
|
end;
|
|
|
|
function TJclPtrArrayList.Last: IJclPtrIterator;
|
|
begin
|
|
Result := TJclPtrArrayIterator.Create(Self, FSize - 1, False, isLast);
|
|
end;
|
|
|
|
function TJclPtrArrayList.LastIndexOf(APtr: Pointer): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := -1;
|
|
for I := FSize - 1 downto 0 do
|
|
if ItemsEqual(FElementData[I], APtr) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclPtrArrayList.RaiseOutOfBoundsError: Pointer;
|
|
begin
|
|
raise EJclOutOfBoundsError.Create;
|
|
end;
|
|
|
|
function TJclPtrArrayList.Remove(APtr: Pointer): Boolean;
|
|
var
|
|
Extracted: Pointer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := Extract(APtr);
|
|
if Result then
|
|
begin
|
|
Extracted := APtr;
|
|
FreePointer(Extracted);
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclPtrArrayList.RemoveAll(const ACollection: IJclPtrCollection): Boolean;
|
|
var
|
|
It: IJclPtrIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Remove(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclPtrArrayList.RetainAll(const ACollection: IJclPtrCollection): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
for I := FSize - 1 downto 0 do
|
|
if not ACollection.Contains(FElementData[I]) then
|
|
Delete(I);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclPtrArrayList.SetCapacity(Value: Integer);
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if Value >= FSize then
|
|
begin
|
|
SetLength(FElementData, Value);
|
|
inherited SetCapacity(Value);
|
|
end
|
|
else
|
|
raise EJclOutOfBoundsError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclPtrArrayList.SetPointer(Index: Integer; APtr: Pointer);
|
|
var
|
|
ReplaceItem: Boolean;
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (Index < 0) or (Index >= FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
ReplaceItem := FAllowDefaultElements or not ItemsEqual(APtr, nil);
|
|
if ReplaceItem then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], APtr) then
|
|
begin
|
|
ReplaceItem := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
if ReplaceItem then
|
|
begin
|
|
FreePointer(FElementData[Index]);
|
|
FElementData[Index] := APtr;
|
|
end;
|
|
end;
|
|
if not ReplaceItem then
|
|
Delete(Index);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclPtrArrayList.Size: Integer;
|
|
begin
|
|
Result := FSize;
|
|
end;
|
|
|
|
function TJclPtrArrayList.SubList(First, Count: Integer): IJclPtrList;
|
|
var
|
|
I: Integer;
|
|
Last: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Last := First + Count - 1;
|
|
if Last >= FSize then
|
|
Last := FSize - 1;
|
|
Result := CreateEmptyContainer as IJclPtrList;
|
|
for I := First to Last do
|
|
Result.Add(FElementData[I]);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclPtrArrayList.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclPtrArrayList.Create(FSize);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
//=== { TJclPtrArrayIterator } ===============================================================
|
|
|
|
constructor TJclPtrArrayIterator.Create(const AOwnList: IJclPtrList; ACursor: Integer; AValid: Boolean; AStart: TItrStart);
|
|
begin
|
|
inherited Create(AValid);
|
|
FOwnList := AOwnList;
|
|
FStart := AStart;
|
|
FCursor := ACursor;
|
|
end;
|
|
|
|
function TJclPtrArrayIterator.Add(APtr: Pointer): Boolean;
|
|
begin
|
|
Result := FOwnList.Add(APtr);
|
|
end;
|
|
|
|
procedure TJclPtrArrayIterator.AssignPropertiesTo(Dest: TJclAbstractIterator);
|
|
var
|
|
ADest: TJclPtrArrayIterator;
|
|
begin
|
|
inherited AssignPropertiesTo(Dest);
|
|
if Dest is TJclPtrArrayIterator then
|
|
begin
|
|
ADest := TJclPtrArrayIterator(Dest);
|
|
ADest.FOwnList := FOwnList;
|
|
ADest.FCursor := FCursor;
|
|
ADest.FStart := FStart;
|
|
end;
|
|
end;
|
|
|
|
function TJclPtrArrayIterator.CreateEmptyIterator: TJclAbstractIterator;
|
|
begin
|
|
Result := TJclPtrArrayIterator.Create(FOwnList, FCursor, Valid, FStart);
|
|
end;
|
|
|
|
procedure TJclPtrArrayIterator.Extract;
|
|
begin
|
|
CheckValid;
|
|
Valid := False;
|
|
FOwnList.ExtractIndex(FCursor);
|
|
end;
|
|
|
|
function TJclPtrArrayIterator.GetPointer: Pointer;
|
|
begin
|
|
CheckValid;
|
|
Result := FOwnList.GetPointer(FCursor);
|
|
end;
|
|
|
|
function TJclPtrArrayIterator.HasNext: Boolean;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor < (FOwnList.Size - 1)
|
|
else
|
|
Result := FCursor < FOwnList.Size;
|
|
end;
|
|
|
|
function TJclPtrArrayIterator.HasPrevious: Boolean;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor > 0
|
|
else
|
|
Result := FCursor >= 0;
|
|
end;
|
|
|
|
function TJclPtrArrayIterator.Insert(APtr: Pointer): Boolean;
|
|
begin
|
|
CheckValid;
|
|
Result := FOwnList.Insert(FCursor, APtr);
|
|
end;
|
|
|
|
function TJclPtrArrayIterator.IteratorEquals(const AIterator: IJclPtrIterator): Boolean;
|
|
var
|
|
Obj: TObject;
|
|
ItrObj: TJclPtrArrayIterator;
|
|
begin
|
|
Result := False;
|
|
if AIterator = nil then
|
|
Exit;
|
|
Obj := AIterator.GetIteratorReference;
|
|
if Obj is TJclPtrArrayIterator then
|
|
begin
|
|
ItrObj := TJclPtrArrayIterator(Obj);
|
|
Result := (FOwnList = ItrObj.FOwnList) and (FCursor = ItrObj.FCursor) and (Valid = ItrObj.Valid);
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function TJclPtrArrayIterator.MoveNext: Boolean;
|
|
begin
|
|
if Valid then
|
|
Inc(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FCursor < FOwnList.Size;
|
|
end;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
|
|
function TJclPtrArrayIterator.Next: Pointer;
|
|
begin
|
|
if Valid then
|
|
Inc(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FOwnList.GetPointer(FCursor);
|
|
end;
|
|
|
|
function TJclPtrArrayIterator.NextIndex: Integer;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor + 1
|
|
else
|
|
Result := FCursor;
|
|
end;
|
|
|
|
function TJclPtrArrayIterator.Previous: Pointer;
|
|
begin
|
|
if Valid then
|
|
Dec(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FOwnList.GetPointer(FCursor);
|
|
end;
|
|
|
|
function TJclPtrArrayIterator.PreviousIndex: Integer;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor - 1
|
|
else
|
|
Result := FCursor;
|
|
end;
|
|
|
|
procedure TJclPtrArrayIterator.Remove;
|
|
begin
|
|
CheckValid;
|
|
Valid := False;
|
|
FOwnList.Delete(FCursor);
|
|
end;
|
|
|
|
procedure TJclPtrArrayIterator.Reset;
|
|
begin
|
|
Valid := False;
|
|
case FStart of
|
|
isFirst:
|
|
FCursor := 0;
|
|
isLast:
|
|
FCursor := FOwnList.Size - 1;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclPtrArrayIterator.SetPointer(APtr: Pointer);
|
|
begin
|
|
CheckValid;
|
|
FOwnList.SetPointer(FCursor, APtr);
|
|
end;
|
|
|
|
//=== { TJclArrayList } ======================================================
|
|
|
|
constructor TJclArrayList.Create(ACapacity: Integer; AOwnsObjects: Boolean);
|
|
begin
|
|
inherited Create(AOwnsObjects);
|
|
SetCapacity(ACapacity);
|
|
end;
|
|
|
|
constructor TJclArrayList.Create(const ACollection: IJclCollection; AOwnsObjects: Boolean);
|
|
begin
|
|
inherited Create(AOwnsObjects);
|
|
if ACollection = nil then
|
|
raise EJclNoCollectionError.Create;
|
|
SetCapacity(ACollection.Size);
|
|
AddAll(ACollection);
|
|
end;
|
|
|
|
destructor TJclArrayList.Destroy;
|
|
begin
|
|
FReadOnly := False;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJclArrayList.Add(AObject: TObject): Boolean;
|
|
var
|
|
Index: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FAllowDefaultElements or not ItemsEqual(AObject, nil);
|
|
if Result then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for Index := 0 to FSize - 1 do
|
|
if ItemsEqual(AObject, FElementData[Index]) then
|
|
begin
|
|
Result := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
if FSize = FCapacity then
|
|
AutoGrow;
|
|
Result := FSize < FCapacity;
|
|
if Result then
|
|
begin
|
|
FElementData[FSize] := AObject;
|
|
Inc(FSize);
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList.AddAll(const ACollection: IJclCollection): Boolean;
|
|
var
|
|
It: IJclIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Add(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclArrayList.AssignDataTo(Dest: TJclAbstractContainerBase);
|
|
var
|
|
ADest: TJclArrayList;
|
|
ACollection: IJclCollection;
|
|
begin
|
|
inherited AssignDataTo(Dest);
|
|
if Dest is TJclArrayList then
|
|
begin
|
|
ADest := TJclArrayList(Dest);
|
|
ADest.Clear;
|
|
ADest.AddAll(Self);
|
|
end
|
|
else
|
|
if Supports(IInterface(Dest), IJclCollection, ACollection) then
|
|
begin
|
|
ACollection.Clear;
|
|
ACollection.AddAll(Self);
|
|
end;
|
|
end;
|
|
|
|
procedure TJclArrayList.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
for I := 0 to FSize - 1 do
|
|
FreeObject(FElementData[I]);
|
|
FSize := 0;
|
|
AutoPack;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList.CollectionEquals(const ACollection: IJclCollection): Boolean;
|
|
var
|
|
I: Integer;
|
|
It: IJclIterator;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$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 not ItemsEqual(FElementData[I], It.Next) then
|
|
Exit;
|
|
Result := True;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList.Contains(AObject: TObject): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AObject) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList.ContainsAll(const ACollection: IJclCollection): Boolean;
|
|
var
|
|
It: IJclIterator;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := True;
|
|
if ACollection = nil then
|
|
Exit;
|
|
It := ACollection.First;
|
|
while Result and It.HasNext do
|
|
Result := Contains(It.Next);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList.Delete(Index: Integer): TObject;
|
|
var
|
|
Extracted: TObject;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Extracted := ExtractIndex(Index);
|
|
Result := FreeObject(Extracted);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList.Extract(AObject: TObject): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
for I := FSize - 1 downto 0 do
|
|
if ItemsEqual(FElementData[I], AObject) then
|
|
begin
|
|
FElementData[I] := nil;
|
|
if I < (FSize - 1) then
|
|
MoveArray(FElementData, I + 1, I, FSize - I);
|
|
Dec(FSize);
|
|
Result := True;
|
|
if FRemoveSingleElement then
|
|
Break;
|
|
end;
|
|
AutoPack;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList.ExtractAll(const ACollection: IJclCollection): Boolean;
|
|
var
|
|
It: IJclIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Extract(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList.ExtractIndex(Index: Integer): TObject;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (Index >= 0) and (Index < FSize) then
|
|
begin
|
|
Result := FElementData[Index];
|
|
if Index < (FSize - 1) then
|
|
MoveArray(FElementData, Index + 1, Index, FSize - Index);
|
|
Dec(FSize);
|
|
AutoPack;
|
|
end
|
|
else
|
|
Result := RaiseOutOfBoundsError;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList.First: IJclIterator;
|
|
begin
|
|
Result := TJclArrayIterator.Create(Self, 0, False, isFirst);
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function TJclArrayList.GetEnumerator: IJclIterator;
|
|
begin
|
|
Result := TJclArrayIterator.Create(Self, 0, False, isFirst);
|
|
end;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
|
|
function TJclArrayList.GetObject(Index: Integer): TObject;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := nil;
|
|
if (Index >= 0) and (Index < FSize) then
|
|
Result := FElementData[Index]
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create(IntToStr(Index));
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList.IndexOf(AObject: TObject): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := -1;
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AObject) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList.Insert(Index: Integer; AObject: TObject): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FAllowDefaultElements or not ItemsEqual(AObject, nil);
|
|
|
|
if (Index < 0) or (Index > FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
|
|
if Result then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(AObject, FElementData[I]) then
|
|
begin
|
|
Result := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
if FSize = FCapacity then
|
|
AutoGrow;
|
|
Result := FSize < FCapacity;
|
|
if Result then
|
|
begin
|
|
if Index < FSize then
|
|
MoveArray(FElementData, Index, Index + 1, FSize - Index);
|
|
FElementData[Index] := AObject;
|
|
Inc(FSize);
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList.InsertAll(Index: Integer; const ACollection: IJclCollection): Boolean;
|
|
var
|
|
It: IJclIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if (Index < 0) or (Index > FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
if ACollection = nil then
|
|
Exit;
|
|
|
|
Result := True;
|
|
It := ACollection.Last;
|
|
while It.HasPrevious do
|
|
Result := Insert(Index, It.Previous) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList.IsEmpty: Boolean;
|
|
begin
|
|
Result := FSize = 0;
|
|
end;
|
|
|
|
function TJclArrayList.Last: IJclIterator;
|
|
begin
|
|
Result := TJclArrayIterator.Create(Self, FSize - 1, False, isLast);
|
|
end;
|
|
|
|
function TJclArrayList.LastIndexOf(AObject: TObject): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := -1;
|
|
for I := FSize - 1 downto 0 do
|
|
if ItemsEqual(FElementData[I], AObject) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList.RaiseOutOfBoundsError: TObject;
|
|
begin
|
|
raise EJclOutOfBoundsError.Create;
|
|
end;
|
|
|
|
function TJclArrayList.Remove(AObject: TObject): Boolean;
|
|
var
|
|
Extracted: TObject;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := Extract(AObject);
|
|
if Result then
|
|
begin
|
|
Extracted := AObject;
|
|
FreeObject(Extracted);
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList.RemoveAll(const ACollection: IJclCollection): Boolean;
|
|
var
|
|
It: IJclIterator;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Remove(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList.RetainAll(const ACollection: IJclCollection): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
for I := FSize - 1 downto 0 do
|
|
if not ACollection.Contains(FElementData[I]) then
|
|
Delete(I);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclArrayList.SetCapacity(Value: Integer);
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if Value >= FSize then
|
|
begin
|
|
SetLength(FElementData, Value);
|
|
inherited SetCapacity(Value);
|
|
end
|
|
else
|
|
raise EJclOutOfBoundsError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclArrayList.SetObject(Index: Integer; AObject: TObject);
|
|
var
|
|
ReplaceItem: Boolean;
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (Index < 0) or (Index >= FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
ReplaceItem := FAllowDefaultElements or not ItemsEqual(AObject, nil);
|
|
if ReplaceItem then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AObject) then
|
|
begin
|
|
ReplaceItem := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
if ReplaceItem then
|
|
begin
|
|
FreeObject(FElementData[Index]);
|
|
FElementData[Index] := AObject;
|
|
end;
|
|
end;
|
|
if not ReplaceItem then
|
|
Delete(Index);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList.Size: Integer;
|
|
begin
|
|
Result := FSize;
|
|
end;
|
|
|
|
function TJclArrayList.SubList(First, Count: Integer): IJclList;
|
|
var
|
|
I: Integer;
|
|
Last: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Last := First + Count - 1;
|
|
if Last >= FSize then
|
|
Last := FSize - 1;
|
|
Result := CreateEmptyContainer as IJclList;
|
|
for I := First to Last do
|
|
Result.Add(FElementData[I]);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclArrayList.Create(FSize, False);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
//=== { TJclArrayIterator } ===============================================================
|
|
|
|
constructor TJclArrayIterator.Create(const AOwnList: IJclList; ACursor: Integer; AValid: Boolean; AStart: TItrStart);
|
|
begin
|
|
inherited Create(AValid);
|
|
FOwnList := AOwnList;
|
|
FStart := AStart;
|
|
FCursor := ACursor;
|
|
end;
|
|
|
|
function TJclArrayIterator.Add(AObject: TObject): Boolean;
|
|
begin
|
|
Result := FOwnList.Add(AObject);
|
|
end;
|
|
|
|
procedure TJclArrayIterator.AssignPropertiesTo(Dest: TJclAbstractIterator);
|
|
var
|
|
ADest: TJclArrayIterator;
|
|
begin
|
|
inherited AssignPropertiesTo(Dest);
|
|
if Dest is TJclArrayIterator then
|
|
begin
|
|
ADest := TJclArrayIterator(Dest);
|
|
ADest.FOwnList := FOwnList;
|
|
ADest.FCursor := FCursor;
|
|
ADest.FStart := FStart;
|
|
end;
|
|
end;
|
|
|
|
function TJclArrayIterator.CreateEmptyIterator: TJclAbstractIterator;
|
|
begin
|
|
Result := TJclArrayIterator.Create(FOwnList, FCursor, Valid, FStart);
|
|
end;
|
|
|
|
procedure TJclArrayIterator.Extract;
|
|
begin
|
|
CheckValid;
|
|
Valid := False;
|
|
FOwnList.ExtractIndex(FCursor);
|
|
end;
|
|
|
|
function TJclArrayIterator.GetObject: TObject;
|
|
begin
|
|
CheckValid;
|
|
Result := FOwnList.GetObject(FCursor);
|
|
end;
|
|
|
|
function TJclArrayIterator.HasNext: Boolean;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor < (FOwnList.Size - 1)
|
|
else
|
|
Result := FCursor < FOwnList.Size;
|
|
end;
|
|
|
|
function TJclArrayIterator.HasPrevious: Boolean;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor > 0
|
|
else
|
|
Result := FCursor >= 0;
|
|
end;
|
|
|
|
function TJclArrayIterator.Insert(AObject: TObject): Boolean;
|
|
begin
|
|
CheckValid;
|
|
Result := FOwnList.Insert(FCursor, AObject);
|
|
end;
|
|
|
|
function TJclArrayIterator.IteratorEquals(const AIterator: IJclIterator): Boolean;
|
|
var
|
|
Obj: TObject;
|
|
ItrObj: TJclArrayIterator;
|
|
begin
|
|
Result := False;
|
|
if AIterator = nil then
|
|
Exit;
|
|
Obj := AIterator.GetIteratorReference;
|
|
if Obj is TJclArrayIterator then
|
|
begin
|
|
ItrObj := TJclArrayIterator(Obj);
|
|
Result := (FOwnList = ItrObj.FOwnList) and (FCursor = ItrObj.FCursor) and (Valid = ItrObj.Valid);
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function TJclArrayIterator.MoveNext: Boolean;
|
|
begin
|
|
if Valid then
|
|
Inc(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FCursor < FOwnList.Size;
|
|
end;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
|
|
function TJclArrayIterator.Next: TObject;
|
|
begin
|
|
if Valid then
|
|
Inc(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FOwnList.GetObject(FCursor);
|
|
end;
|
|
|
|
function TJclArrayIterator.NextIndex: Integer;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor + 1
|
|
else
|
|
Result := FCursor;
|
|
end;
|
|
|
|
function TJclArrayIterator.Previous: TObject;
|
|
begin
|
|
if Valid then
|
|
Dec(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FOwnList.GetObject(FCursor);
|
|
end;
|
|
|
|
function TJclArrayIterator.PreviousIndex: Integer;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor - 1
|
|
else
|
|
Result := FCursor;
|
|
end;
|
|
|
|
procedure TJclArrayIterator.Remove;
|
|
begin
|
|
CheckValid;
|
|
Valid := False;
|
|
FOwnList.Delete(FCursor);
|
|
end;
|
|
|
|
procedure TJclArrayIterator.Reset;
|
|
begin
|
|
Valid := False;
|
|
case FStart of
|
|
isFirst:
|
|
FCursor := 0;
|
|
isLast:
|
|
FCursor := FOwnList.Size - 1;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclArrayIterator.SetObject(AObject: TObject);
|
|
begin
|
|
CheckValid;
|
|
FOwnList.SetObject(FCursor, AObject);
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_GENERICS}
|
|
|
|
//=== { TJclArrayList<T> } ======================================================
|
|
|
|
constructor TJclArrayList<T>.Create(ACapacity: Integer; AOwnsItems: Boolean);
|
|
begin
|
|
inherited Create(AOwnsItems);
|
|
SetCapacity(ACapacity);
|
|
end;
|
|
|
|
constructor TJclArrayList<T>.Create(const ACollection: IJclCollection<T>; AOwnsItems: Boolean);
|
|
begin
|
|
inherited Create(AOwnsItems);
|
|
if ACollection = nil then
|
|
raise EJclNoCollectionError.Create;
|
|
SetCapacity(ACollection.Size);
|
|
AddAll(ACollection);
|
|
end;
|
|
|
|
destructor TJclArrayList<T>.Destroy;
|
|
begin
|
|
FReadOnly := False;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJclArrayList<T>.Add(const AItem: T): Boolean;
|
|
var
|
|
Index: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FAllowDefaultElements or not ItemsEqual(AItem, Default(T));
|
|
if Result then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for Index := 0 to FSize - 1 do
|
|
if ItemsEqual(AItem, FElementData[Index]) then
|
|
begin
|
|
Result := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
if FSize = FCapacity then
|
|
AutoGrow;
|
|
Result := FSize < FCapacity;
|
|
if Result then
|
|
begin
|
|
FElementData[FSize] := AItem;
|
|
Inc(FSize);
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList<T>.AddAll(const ACollection: IJclCollection<T>): Boolean;
|
|
var
|
|
It: IJclIterator<T>;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Add(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclArrayList<T>.AssignDataTo(Dest: TJclAbstractContainerBase);
|
|
var
|
|
ADest: TJclArrayList<T>;
|
|
ACollection: IJclCollection<T>;
|
|
begin
|
|
inherited AssignDataTo(Dest);
|
|
if Dest is TJclArrayList<T> then
|
|
begin
|
|
ADest := TJclArrayList<T>(Dest);
|
|
ADest.Clear;
|
|
ADest.AddAll(Self);
|
|
end
|
|
else
|
|
if Supports(IInterface(Dest), IJclCollection<T>, ACollection) then
|
|
begin
|
|
ACollection.Clear;
|
|
ACollection.AddAll(Self);
|
|
end;
|
|
end;
|
|
|
|
procedure TJclArrayList<T>.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
for I := 0 to FSize - 1 do
|
|
FreeItem(FElementData[I]);
|
|
FSize := 0;
|
|
AutoPack;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList<T>.CollectionEquals(const ACollection: IJclCollection<T>): Boolean;
|
|
var
|
|
I: Integer;
|
|
It: IJclIterator<T>;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$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 not ItemsEqual(FElementData[I], It.Next) then
|
|
Exit;
|
|
Result := True;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList<T>.Contains(const AItem: T): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AItem) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList<T>.ContainsAll(const ACollection: IJclCollection<T>): Boolean;
|
|
var
|
|
It: IJclIterator<T>;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := True;
|
|
if ACollection = nil then
|
|
Exit;
|
|
It := ACollection.First;
|
|
while Result and It.HasNext do
|
|
Result := Contains(It.Next);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList<T>.Delete(Index: Integer): T;
|
|
var
|
|
Extracted: T;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Extracted := ExtractIndex(Index);
|
|
Result := FreeItem(Extracted);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList<T>.Extract(const AItem: T): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
for I := FSize - 1 downto 0 do
|
|
if ItemsEqual(FElementData[I], AItem) then
|
|
begin
|
|
FElementData[I] := Default(T);
|
|
if I < (FSize - 1) then
|
|
MoveArray(FElementData, I + 1, I, FSize - I);
|
|
Dec(FSize);
|
|
Result := True;
|
|
if FRemoveSingleElement then
|
|
Break;
|
|
end;
|
|
AutoPack;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList<T>.ExtractAll(const ACollection: IJclCollection<T>): Boolean;
|
|
var
|
|
It: IJclIterator<T>;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Extract(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList<T>.ExtractIndex(Index: Integer): T;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (Index >= 0) and (Index < FSize) then
|
|
begin
|
|
Result := FElementData[Index];
|
|
if Index < (FSize - 1) then
|
|
MoveArray(FElementData, Index + 1, Index, FSize - Index);
|
|
Dec(FSize);
|
|
AutoPack;
|
|
end
|
|
else
|
|
Result := RaiseOutOfBoundsError;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList<T>.First: IJclIterator<T>;
|
|
begin
|
|
Result := TArrayIterator.Create(Self, 0, False, isFirst);
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function TJclArrayList<T>.GetEnumerator: IJclIterator<T>;
|
|
begin
|
|
Result := TArrayIterator.Create(Self, 0, False, isFirst);
|
|
end;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
|
|
function TJclArrayList<T>.GetItem(Index: Integer): T;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := Default(T);
|
|
if (Index >= 0) and (Index < FSize) then
|
|
Result := FElementData[Index]
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create(IntToStr(Index));
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList<T>.IndexOf(const AItem: T): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := -1;
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AItem) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList<T>.Insert(Index: Integer; const AItem: T): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FAllowDefaultElements or not ItemsEqual(AItem, Default(T));
|
|
|
|
if (Index < 0) or (Index > FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
|
|
if Result then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(AItem, FElementData[I]) then
|
|
begin
|
|
Result := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
if FSize = FCapacity then
|
|
AutoGrow;
|
|
Result := FSize < FCapacity;
|
|
if Result then
|
|
begin
|
|
if Index < FSize then
|
|
MoveArray(FElementData, Index, Index + 1, FSize - Index);
|
|
FElementData[Index] := AItem;
|
|
Inc(FSize);
|
|
end;
|
|
end;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList<T>.InsertAll(Index: Integer; const ACollection: IJclCollection<T>): Boolean;
|
|
var
|
|
It: IJclIterator<T>;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if (Index < 0) or (Index > FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
if ACollection = nil then
|
|
Exit;
|
|
|
|
Result := True;
|
|
It := ACollection.Last;
|
|
while It.HasPrevious do
|
|
Result := Insert(Index, It.Previous) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList<T>.IsEmpty: Boolean;
|
|
begin
|
|
Result := FSize = 0;
|
|
end;
|
|
|
|
function TJclArrayList<T>.Last: IJclIterator<T>;
|
|
begin
|
|
Result := TArrayIterator.Create(Self, FSize - 1, False, isLast);
|
|
end;
|
|
|
|
function TJclArrayList<T>.LastIndexOf(const AItem: T): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := -1;
|
|
for I := FSize - 1 downto 0 do
|
|
if ItemsEqual(FElementData[I], AItem) then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList<T>.RaiseOutOfBoundsError: T;
|
|
begin
|
|
raise EJclOutOfBoundsError.Create;
|
|
end;
|
|
|
|
function TJclArrayList<T>.Remove(const AItem: T): Boolean;
|
|
var
|
|
Extracted: T;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := Extract(AItem);
|
|
if Result then
|
|
begin
|
|
Extracted := AItem;
|
|
FreeItem(Extracted);
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList<T>.RemoveAll(const ACollection: IJclCollection<T>): Boolean;
|
|
var
|
|
It: IJclIterator<T>;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
It := ACollection.First;
|
|
while It.HasNext do
|
|
Result := Remove(It.Next) and Result;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList<T>.RetainAll(const ACollection: IJclCollection<T>): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
if ACollection = nil then
|
|
Exit;
|
|
Result := True;
|
|
for I := FSize - 1 downto 0 do
|
|
if not ACollection.Contains(FElementData[I]) then
|
|
Delete(I);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclArrayList<T>.SetCapacity(Value: Integer);
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if Value >= FSize then
|
|
begin
|
|
SetLength(FElementData, Value);
|
|
inherited SetCapacity(Value);
|
|
end
|
|
else
|
|
raise EJclOutOfBoundsError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclArrayList<T>.SetItem(Index: Integer; const AItem: T);
|
|
var
|
|
ReplaceItem: Boolean;
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (Index < 0) or (Index >= FSize) then
|
|
raise EJclOutOfBoundsError.Create;
|
|
ReplaceItem := FAllowDefaultElements or not ItemsEqual(AItem, Default(T));
|
|
if ReplaceItem then
|
|
begin
|
|
if FDuplicates <> dupAccept then
|
|
for I := 0 to FSize - 1 do
|
|
if ItemsEqual(FElementData[I], AItem) then
|
|
begin
|
|
ReplaceItem := CheckDuplicate;
|
|
Break;
|
|
end;
|
|
if ReplaceItem then
|
|
begin
|
|
FreeItem(FElementData[Index]);
|
|
FElementData[Index] := AItem;
|
|
end;
|
|
end;
|
|
if not ReplaceItem then
|
|
Delete(Index);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclArrayList<T>.Size: Integer;
|
|
begin
|
|
Result := FSize;
|
|
end;
|
|
|
|
function TJclArrayList<T>.SubList(First, Count: Integer): IJclList<T>;
|
|
var
|
|
I: Integer;
|
|
Last: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Last := First + Count - 1;
|
|
if Last >= FSize then
|
|
Last := FSize - 1;
|
|
Result := CreateEmptyContainer as IJclList<T>;
|
|
for I := First to Last do
|
|
Result.Add(FElementData[I]);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
//=== { TJclArrayIterator<T> } ===============================================================
|
|
|
|
constructor TJclArrayIterator<T>.Create(const AOwnList: IJclList<T>; ACursor: Integer; AValid: Boolean; AStart: TItrStart);
|
|
begin
|
|
inherited Create(AValid);
|
|
FOwnList := AOwnList;
|
|
FStart := AStart;
|
|
FCursor := ACursor;
|
|
end;
|
|
|
|
function TJclArrayIterator<T>.Add(const AItem: T): Boolean;
|
|
begin
|
|
Result := FOwnList.Add(AItem);
|
|
end;
|
|
|
|
procedure TJclArrayIterator<T>.AssignPropertiesTo(Dest: TJclAbstractIterator);
|
|
var
|
|
ADest: TJclArrayIterator<T>;
|
|
begin
|
|
inherited AssignPropertiesTo(Dest);
|
|
if Dest is TJclArrayIterator<T> then
|
|
begin
|
|
ADest := TJclArrayIterator<T>(Dest);
|
|
ADest.FOwnList := FOwnList;
|
|
ADest.FCursor := FCursor;
|
|
ADest.FStart := FStart;
|
|
end;
|
|
end;
|
|
|
|
function TJclArrayIterator<T>.CreateEmptyIterator: TJclAbstractIterator;
|
|
begin
|
|
Result := TJclArrayIterator<T>.Create(FOwnList, FCursor, Valid, FStart);
|
|
end;
|
|
|
|
procedure TJclArrayIterator<T>.Extract;
|
|
begin
|
|
CheckValid;
|
|
Valid := False;
|
|
FOwnList.ExtractIndex(FCursor);
|
|
end;
|
|
|
|
function TJclArrayIterator<T>.GetItem: T;
|
|
begin
|
|
CheckValid;
|
|
Result := FOwnList.GetItem(FCursor);
|
|
end;
|
|
|
|
function TJclArrayIterator<T>.HasNext: Boolean;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor < (FOwnList.Size - 1)
|
|
else
|
|
Result := FCursor < FOwnList.Size;
|
|
end;
|
|
|
|
function TJclArrayIterator<T>.HasPrevious: Boolean;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor > 0
|
|
else
|
|
Result := FCursor >= 0;
|
|
end;
|
|
|
|
function TJclArrayIterator<T>.Insert(const AItem: T): Boolean;
|
|
begin
|
|
CheckValid;
|
|
Result := FOwnList.Insert(FCursor, AItem);
|
|
end;
|
|
|
|
function TJclArrayIterator<T>.IteratorEquals(const AIterator: IJclIterator<T>): Boolean;
|
|
var
|
|
Obj: TObject;
|
|
ItrObj: TJclArrayIterator<T>;
|
|
begin
|
|
Result := False;
|
|
if AIterator = nil then
|
|
Exit;
|
|
Obj := AIterator.GetIteratorReference;
|
|
if Obj is TJclArrayIterator<T> then
|
|
begin
|
|
ItrObj := TJclArrayIterator<T>(Obj);
|
|
Result := (FOwnList = ItrObj.FOwnList) and (FCursor = ItrObj.FCursor) and (Valid = ItrObj.Valid);
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_FOR_IN}
|
|
function TJclArrayIterator<T>.MoveNext: Boolean;
|
|
begin
|
|
if Valid then
|
|
Inc(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FCursor < FOwnList.Size;
|
|
end;
|
|
{$ENDIF SUPPORTS_FOR_IN}
|
|
|
|
function TJclArrayIterator<T>.Next: T;
|
|
begin
|
|
if Valid then
|
|
Inc(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FOwnList.GetItem(FCursor);
|
|
end;
|
|
|
|
function TJclArrayIterator<T>.NextIndex: Integer;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor + 1
|
|
else
|
|
Result := FCursor;
|
|
end;
|
|
|
|
function TJclArrayIterator<T>.Previous: T;
|
|
begin
|
|
if Valid then
|
|
Dec(FCursor)
|
|
else
|
|
Valid := True;
|
|
Result := FOwnList.GetItem(FCursor);
|
|
end;
|
|
|
|
function TJclArrayIterator<T>.PreviousIndex: Integer;
|
|
begin
|
|
if Valid then
|
|
Result := FCursor - 1
|
|
else
|
|
Result := FCursor;
|
|
end;
|
|
|
|
procedure TJclArrayIterator<T>.Remove;
|
|
begin
|
|
CheckValid;
|
|
Valid := False;
|
|
FOwnList.Delete(FCursor);
|
|
end;
|
|
|
|
procedure TJclArrayIterator<T>.Reset;
|
|
begin
|
|
Valid := False;
|
|
case FStart of
|
|
isFirst:
|
|
FCursor := 0;
|
|
isLast:
|
|
FCursor := FOwnList.Size - 1;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclArrayIterator<T>.SetItem(const AItem: T);
|
|
begin
|
|
CheckValid;
|
|
FOwnList.SetItem(FCursor, AItem);
|
|
end;
|
|
|
|
procedure TJclArrayList<T>.MoveArray(var List: TDynArray; FromIndex, ToIndex, Count: Integer);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if FromIndex < ToIndex then
|
|
begin
|
|
for I := Count - 1 downto 0 do
|
|
List[ToIndex + I] := List[FromIndex + I];
|
|
|
|
if (ToIndex - FromIndex) < Count then
|
|
// overlapped source and target
|
|
for I := 0 to ToIndex - FromIndex - 1 do
|
|
List[FromIndex + I] := Default(T)
|
|
else
|
|
// independant
|
|
for I := 0 to Count - 1 do
|
|
List[FromIndex + I] := Default(T);
|
|
end
|
|
else
|
|
begin
|
|
for I := 0 to Count - 1 do
|
|
List[ToIndex + I] := List[FromIndex + I];
|
|
|
|
if (FromIndex - ToIndex) < Count then
|
|
// overlapped source and target
|
|
for I := Count - FromIndex + ToIndex to Count - 1 do
|
|
List[FromIndex + I] := Default(T)
|
|
else
|
|
// independant
|
|
for I := 0 to Count - 1 do
|
|
List[FromIndex + I] := Default(T);
|
|
end;
|
|
end;
|
|
|
|
//=== { TJclArrayListE<T> } ==================================================
|
|
|
|
constructor TJclArrayListE<T>.Create(const AEqualityComparer: IJclEqualityComparer<T>; ACapacity: Integer;
|
|
AOwnsItems: Boolean);
|
|
begin
|
|
inherited Create(ACapacity, AOwnsItems);
|
|
FEqualityComparer := AEqualityComparer;
|
|
end;
|
|
|
|
constructor TJclArrayListE<T>.Create(const AEqualityComparer: IJclEqualityComparer<T>;
|
|
const ACollection: IJclCollection<T>; AOwnsItems: Boolean);
|
|
begin
|
|
inherited Create(ACollection, AOwnsItems);
|
|
FEqualityComparer := AEqualityComparer;
|
|
end;
|
|
|
|
procedure TJclArrayListE<T>.AssignPropertiesTo(Dest: TJclAbstractContainerBase);
|
|
begin
|
|
inherited AssignPropertiesTo(Dest);
|
|
if Dest is TJclArrayListE<T> then
|
|
TJclArrayListE<T>(Dest).FEqualityComparer := FEqualityComparer;
|
|
end;
|
|
|
|
function TJclArrayListE<T>.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclArrayListE<T>.Create(EqualityComparer, FSize, False);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
function TJclArrayListE<T>.ItemsEqual(const A, B: T): Boolean;
|
|
begin
|
|
if EqualityComparer <> nil then
|
|
Result := EqualityComparer.ItemsEqual(A, B)
|
|
else
|
|
Result := inherited ItemsEqual(A, B);
|
|
end;
|
|
|
|
//=== { TJclArrayListF<T> } ==================================================
|
|
|
|
constructor TJclArrayListF<T>.Create(const AEqualityCompare: TEqualityCompare<T>;
|
|
ACapacity: Integer; AOwnsItems: Boolean);
|
|
begin
|
|
inherited Create(ACapacity, AOwnsItems);
|
|
SetEqualityCompare(AEqualityCompare);
|
|
end;
|
|
|
|
constructor TJclArrayListF<T>.Create(const AEqualityCompare: TEqualityCompare<T>; const ACollection: IJclCollection<T>;
|
|
AOwnsItems: Boolean);
|
|
begin
|
|
inherited Create(ACollection, AOwnsItems);
|
|
SetEqualityCompare(AEqualityCompare);
|
|
end;
|
|
|
|
function TJclArrayListF<T>.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclArrayListF<T>.Create(EqualityCompare, FSize, False);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
//=== { TJclArrayListI<T> } ==================================================
|
|
|
|
function TJclArrayListI<T>.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclArrayListI<T>.Create(FSize, False);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
function TJclArrayListI<T>.ItemsEqual(const A, B: T): Boolean;
|
|
begin
|
|
if Assigned(FEqualityCompare) then
|
|
Result := FEqualityCompare(A, B)
|
|
else
|
|
if Assigned(FCompare) then
|
|
Result := FCompare(A, B) = 0
|
|
else
|
|
Result := A.Equals(B);
|
|
end;
|
|
|
|
{$ENDIF SUPPORTS_GENERICS}
|
|
|
|
{$IFDEF UNITVERSIONING}
|
|
initialization
|
|
RegisterUnitVersion(HInstance, UnitVersioning);
|
|
|
|
finalization
|
|
UnregisterUnitVersion(HInstance);
|
|
{$ENDIF UNITVERSIONING}
|
|
|
|
end.
|
|
|