{**************************************************************************************************} { 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 = class; TJclArrayList = class(TJclAbstractContainer, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE} IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclItemOwner, IJclEqualityComparer, IJclCollection, IJclList, IJclArray) protected type TDynArray = array of T; TArrayIterator = TJclArrayIterator; 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; AOwnsItems: Boolean); overload; destructor Destroy; override; { IJclPackable } procedure SetCapacity(Value: Integer); override; { IJclCollection } function Add(const AItem: T): Boolean; function AddAll(const ACollection: IJclCollection): Boolean; procedure Clear; function Contains(const AItem: T): Boolean; function ContainsAll(const ACollection: IJclCollection): Boolean; function CollectionEquals(const ACollection: IJclCollection): Boolean; function Extract(const AItem: T): Boolean; function ExtractAll(const ACollection: IJclCollection): Boolean; function First: IJclIterator; function IsEmpty: Boolean; function Last: IJclIterator; function Remove(const AItem: T): 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): 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): Boolean; function LastIndexOf(const AItem: T): Integer; procedure SetItem(Index: Integer; const AItem: T); 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(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): 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 = class(TJclArrayList, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE} IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclItemOwner, IJclEqualityComparer, IJclCollection, IJclList, IJclArray) private FEqualityComparer: IJclEqualityComparer; protected procedure AssignPropertiesTo(Dest: TJclAbstractContainerBase); override; function CreateEmptyContainer: TJclAbstractContainerBase; override; public constructor Create(const AEqualityComparer: IJclEqualityComparer; ACapacity: Integer; AOwnsItems: Boolean); overload; constructor Create(const AEqualityComparer: IJclEqualityComparer; const ACollection: IJclCollection; AOwnsItems: Boolean); overload; { IJclEqualityComparer } function ItemsEqual(const A, B: T): Boolean; override; property EqualityComparer: IJclEqualityComparer read FEqualityComparer write FEqualityComparer; end; // F = Function to compare items for equality TJclArrayListF = class(TJclArrayList, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE} IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclItemOwner, IJclEqualityComparer, IJclCollection, IJclList, IJclArray) protected function CreateEmptyContainer: TJclAbstractContainerBase; override; public constructor Create(const AEqualityCompare: TEqualityCompare; ACapacity: Integer; AOwnsItems: Boolean); overload; constructor Create(const AEqualityCompare: TEqualityCompare; const ACollection: IJclCollection; AOwnsItems: Boolean); overload; end; // I = Items can compare themselves to others TJclArrayListI> = class(TJclArrayList, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE} IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclItemOwner, IJclEqualityComparer, IJclCollection, IJclList, IJclArray) protected function CreateEmptyContainer: TJclAbstractContainerBase; override; public { IJclEqualityComparer } 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 } ====================================================== constructor TJclArrayList.Create(ACapacity: Integer; AOwnsItems: Boolean); begin inherited Create(AOwnsItems); SetCapacity(ACapacity); end; constructor TJclArrayList.Create(const ACollection: IJclCollection; AOwnsItems: Boolean); begin inherited Create(AOwnsItems); 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(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.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 FreeItem(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(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.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): 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.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.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): 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.First: IJclIterator; begin Result := TArrayIterator.Create(Self, 0, False, isFirst); end; {$IFDEF SUPPORTS_FOR_IN} function TJclArrayList.GetEnumerator: IJclIterator; begin Result := TArrayIterator.Create(Self, 0, False, isFirst); end; {$ENDIF SUPPORTS_FOR_IN} function TJclArrayList.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.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.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.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 := TArrayIterator.Create(Self, FSize - 1, False, isLast); end; function TJclArrayList.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.RaiseOutOfBoundsError: T; begin raise EJclOutOfBoundsError.Create; end; function TJclArrayList.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.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.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.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; //=== { 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(const AItem: T): Boolean; begin Result := FOwnList.Add(AItem); 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.GetItem: T; begin CheckValid; Result := FOwnList.GetItem(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(const AItem: T): Boolean; begin CheckValid; Result := FOwnList.Insert(FCursor, AItem); 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: T; begin if Valid then Inc(FCursor) else Valid := True; Result := FOwnList.GetItem(FCursor); end; function TJclArrayIterator.NextIndex: Integer; begin if Valid then Result := FCursor + 1 else Result := FCursor; end; function TJclArrayIterator.Previous: T; begin if Valid then Dec(FCursor) else Valid := True; Result := FOwnList.GetItem(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.SetItem(const AItem: T); begin CheckValid; FOwnList.SetItem(FCursor, AItem); end; procedure TJclArrayList.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 } ================================================== constructor TJclArrayListE.Create(const AEqualityComparer: IJclEqualityComparer; ACapacity: Integer; AOwnsItems: Boolean); begin inherited Create(ACapacity, AOwnsItems); FEqualityComparer := AEqualityComparer; end; constructor TJclArrayListE.Create(const AEqualityComparer: IJclEqualityComparer; const ACollection: IJclCollection; AOwnsItems: Boolean); begin inherited Create(ACollection, AOwnsItems); FEqualityComparer := AEqualityComparer; end; procedure TJclArrayListE.AssignPropertiesTo(Dest: TJclAbstractContainerBase); begin inherited AssignPropertiesTo(Dest); if Dest is TJclArrayListE then TJclArrayListE(Dest).FEqualityComparer := FEqualityComparer; end; function TJclArrayListE.CreateEmptyContainer: TJclAbstractContainerBase; begin Result := TJclArrayListE.Create(EqualityComparer, FSize, False); AssignPropertiesTo(Result); end; function TJclArrayListE.ItemsEqual(const A, B: T): Boolean; begin if EqualityComparer <> nil then Result := EqualityComparer.ItemsEqual(A, B) else Result := inherited ItemsEqual(A, B); end; //=== { TJclArrayListF } ================================================== constructor TJclArrayListF.Create(const AEqualityCompare: TEqualityCompare; ACapacity: Integer; AOwnsItems: Boolean); begin inherited Create(ACapacity, AOwnsItems); SetEqualityCompare(AEqualityCompare); end; constructor TJclArrayListF.Create(const AEqualityCompare: TEqualityCompare; const ACollection: IJclCollection; AOwnsItems: Boolean); begin inherited Create(ACollection, AOwnsItems); SetEqualityCompare(AEqualityCompare); end; function TJclArrayListF.CreateEmptyContainer: TJclAbstractContainerBase; begin Result := TJclArrayListF.Create(EqualityCompare, FSize, False); AssignPropertiesTo(Result); end; //=== { TJclArrayListI } ================================================== function TJclArrayListI.CreateEmptyContainer: TJclAbstractContainerBase; begin Result := TJclArrayListI.Create(FSize, False); AssignPropertiesTo(Result); end; function TJclArrayListI.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.