git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.jcl@20 c37d764d-f447-7644-a108-883140d013fb
4270 lines
102 KiB
ObjectPascal
4270 lines
102 KiB
ObjectPascal
{**************************************************************************************************}
|
|
{ WARNING: JEDI preprocessor generated unit. Do not edit. }
|
|
{**************************************************************************************************}
|
|
|
|
{**************************************************************************************************}
|
|
{ }
|
|
{ Project JEDI Code Library (JCL) }
|
|
{ }
|
|
{ The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); }
|
|
{ you may not use this file except in compliance with the License. You may obtain a copy of the }
|
|
{ License at http://www.mozilla.org/MPL/ }
|
|
{ }
|
|
{ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF }
|
|
{ ANY KIND, either express or implied. See the License for the specific language governing rights }
|
|
{ and limitations under the License. }
|
|
{ }
|
|
{ The Original Code is Queue.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-09-12 14:21:23 +0200 (sam., 12 sept. 2009) $ }
|
|
{ Revision: $Rev:: 2997 $ }
|
|
{ Author: $Author:: outchy $ }
|
|
{ }
|
|
{**************************************************************************************************}
|
|
|
|
unit JclQueues;
|
|
|
|
{$I jcl.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFDEF UNITVERSIONING}
|
|
JclUnitVersioning,
|
|
{$ENDIF UNITVERSIONING}
|
|
{$IFDEF SUPPORTS_GENERICS}
|
|
JclAlgorithms,
|
|
{$ENDIF SUPPORTS_GENERICS}
|
|
JclBase, JclAbstractContainers, JclContainerIntf, JclSynch;
|
|
|
|
|
|
type
|
|
TJclIntfQueue = class(TJclIntfAbstractContainer, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclIntfEqualityComparer,
|
|
IJclIntfQueue)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
private
|
|
FElements: TDynIInterfaceArray;
|
|
FHead: Integer;
|
|
FTail: Integer;
|
|
protected
|
|
procedure AssignDataTo(Dest: TJclAbstractContainerBase); override;
|
|
public
|
|
constructor Create(ACapacity: Integer);
|
|
destructor Destroy; override;
|
|
{ IJclPackable }
|
|
procedure Pack; override;
|
|
procedure SetCapacity(Value: Integer); override;
|
|
{ IJclIntfQueue }
|
|
procedure Clear;
|
|
function Contains(const AInterface: IInterface): Boolean;
|
|
function Dequeue: IInterface;
|
|
function Empty: Boolean;
|
|
function Enqueue(const AInterface: IInterface): Boolean;
|
|
function Peek: IInterface;
|
|
function Size: Integer;
|
|
end;
|
|
|
|
TJclAnsiStrQueue = class(TJclAnsiStrAbstractContainer, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclStrContainer, IJclAnsiStrContainer, IJclAnsiStrEqualityComparer,
|
|
IJclAnsiStrQueue)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
private
|
|
FElements: TDynAnsiStringArray;
|
|
FHead: Integer;
|
|
FTail: Integer;
|
|
protected
|
|
procedure AssignDataTo(Dest: TJclAbstractContainerBase); override;
|
|
public
|
|
constructor Create(ACapacity: Integer);
|
|
destructor Destroy; override;
|
|
{ IJclPackable }
|
|
procedure Pack; override;
|
|
procedure SetCapacity(Value: Integer); override;
|
|
{ IJclAnsiStrQueue }
|
|
procedure Clear;
|
|
function Contains(const AString: AnsiString): Boolean;
|
|
function Dequeue: AnsiString;
|
|
function Empty: Boolean;
|
|
function Enqueue(const AString: AnsiString): Boolean;
|
|
function Peek: AnsiString;
|
|
function Size: Integer;
|
|
end;
|
|
|
|
TJclWideStrQueue = class(TJclWideStrAbstractContainer, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclStrContainer, IJclWideStrContainer, IJclWideStrEqualityComparer,
|
|
IJclWideStrQueue)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
private
|
|
FElements: TDynWideStringArray;
|
|
FHead: Integer;
|
|
FTail: Integer;
|
|
protected
|
|
procedure AssignDataTo(Dest: TJclAbstractContainerBase); override;
|
|
public
|
|
constructor Create(ACapacity: Integer);
|
|
destructor Destroy; override;
|
|
{ IJclPackable }
|
|
procedure Pack; override;
|
|
procedure SetCapacity(Value: Integer); override;
|
|
{ IJclWideStrQueue }
|
|
procedure Clear;
|
|
function Contains(const AString: WideString): Boolean;
|
|
function Dequeue: WideString;
|
|
function Empty: Boolean;
|
|
function Enqueue(const AString: WideString): Boolean;
|
|
function Peek: WideString;
|
|
function Size: Integer;
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_UNICODE_STRING}
|
|
TJclUnicodeStrQueue = class(TJclUnicodeStrAbstractContainer, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclStrContainer, IJclUnicodeStrContainer, IJclUnicodeStrEqualityComparer,
|
|
IJclUnicodeStrQueue)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
private
|
|
FElements: TDynUnicodeStringArray;
|
|
FHead: Integer;
|
|
FTail: Integer;
|
|
protected
|
|
procedure AssignDataTo(Dest: TJclAbstractContainerBase); override;
|
|
public
|
|
constructor Create(ACapacity: Integer);
|
|
destructor Destroy; override;
|
|
{ IJclPackable }
|
|
procedure Pack; override;
|
|
procedure SetCapacity(Value: Integer); override;
|
|
{ IJclUnicodeStrQueue }
|
|
procedure Clear;
|
|
function Contains(const AString: UnicodeString): Boolean;
|
|
function Dequeue: UnicodeString;
|
|
function Empty: Boolean;
|
|
function Enqueue(const AString: UnicodeString): Boolean;
|
|
function Peek: UnicodeString;
|
|
function Size: Integer;
|
|
end;
|
|
{$ENDIF SUPPORTS_UNICODE_STRING}
|
|
|
|
{$IFDEF CONTAINER_ANSISTR}
|
|
TJclStrQueue = TJclAnsiStrQueue;
|
|
{$ENDIF CONTAINER_ANSISTR}
|
|
{$IFDEF CONTAINER_WIDESTR}
|
|
TJclStrQueue = TJclWideStrQueue;
|
|
{$ENDIF CONTAINER_WIDESTR}
|
|
{$IFDEF CONTAINER_UNICODESTR}
|
|
TJclStrQueue = TJclUnicodeStrQueue;
|
|
{$ENDIF CONTAINER_UNICODESTR}
|
|
|
|
TJclSingleQueue = class(TJclSingleAbstractContainer, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclSingleContainer, IJclSingleEqualityComparer,
|
|
IJclSingleQueue)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
private
|
|
FElements: TDynSingleArray;
|
|
FHead: Integer;
|
|
FTail: Integer;
|
|
protected
|
|
procedure AssignDataTo(Dest: TJclAbstractContainerBase); override;
|
|
public
|
|
constructor Create(ACapacity: Integer);
|
|
destructor Destroy; override;
|
|
{ IJclPackable }
|
|
procedure Pack; override;
|
|
procedure SetCapacity(Value: Integer); override;
|
|
{ IJclSingleQueue }
|
|
procedure Clear;
|
|
function Contains(const AValue: Single): Boolean;
|
|
function Dequeue: Single;
|
|
function Empty: Boolean;
|
|
function Enqueue(const AValue: Single): Boolean;
|
|
function Peek: Single;
|
|
function Size: Integer;
|
|
end;
|
|
|
|
TJclDoubleQueue = class(TJclDoubleAbstractContainer, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclDoubleContainer, IJclDoubleEqualityComparer,
|
|
IJclDoubleQueue)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
private
|
|
FElements: TDynDoubleArray;
|
|
FHead: Integer;
|
|
FTail: Integer;
|
|
protected
|
|
procedure AssignDataTo(Dest: TJclAbstractContainerBase); override;
|
|
public
|
|
constructor Create(ACapacity: Integer);
|
|
destructor Destroy; override;
|
|
{ IJclPackable }
|
|
procedure Pack; override;
|
|
procedure SetCapacity(Value: Integer); override;
|
|
{ IJclDoubleQueue }
|
|
procedure Clear;
|
|
function Contains(const AValue: Double): Boolean;
|
|
function Dequeue: Double;
|
|
function Empty: Boolean;
|
|
function Enqueue(const AValue: Double): Boolean;
|
|
function Peek: Double;
|
|
function Size: Integer;
|
|
end;
|
|
|
|
TJclExtendedQueue = class(TJclExtendedAbstractContainer, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclExtendedContainer, IJclExtendedEqualityComparer,
|
|
IJclExtendedQueue)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
private
|
|
FElements: TDynExtendedArray;
|
|
FHead: Integer;
|
|
FTail: Integer;
|
|
protected
|
|
procedure AssignDataTo(Dest: TJclAbstractContainerBase); override;
|
|
public
|
|
constructor Create(ACapacity: Integer);
|
|
destructor Destroy; override;
|
|
{ IJclPackable }
|
|
procedure Pack; override;
|
|
procedure SetCapacity(Value: Integer); override;
|
|
{ IJclExtendedQueue }
|
|
procedure Clear;
|
|
function Contains(const AValue: Extended): Boolean;
|
|
function Dequeue: Extended;
|
|
function Empty: Boolean;
|
|
function Enqueue(const AValue: Extended): Boolean;
|
|
function Peek: Extended;
|
|
function Size: Integer;
|
|
end;
|
|
|
|
{$IFDEF MATH_EXTENDED_PRECISION}
|
|
TJclFloatQueue = TJclExtendedQueue;
|
|
{$ENDIF MATH_EXTENDED_PRECISION}
|
|
{$IFDEF MATH_DOUBLE_PRECISION}
|
|
TJclFloatQueue = TJclDoubleQueue;
|
|
{$ENDIF MATH_DOUBLE_PRECISION}
|
|
{$IFDEF MATH_SINGLE_PRECISION}
|
|
TJclFloatQueue = TJclSingleQueue;
|
|
{$ENDIF MATH_SINGLE_PRECISION}
|
|
|
|
TJclIntegerQueue = class(TJclIntegerAbstractContainer, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclIntegerEqualityComparer,
|
|
IJclIntegerQueue)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
private
|
|
FElements: TDynIntegerArray;
|
|
FHead: Integer;
|
|
FTail: Integer;
|
|
protected
|
|
procedure AssignDataTo(Dest: TJclAbstractContainerBase); override;
|
|
public
|
|
constructor Create(ACapacity: Integer);
|
|
destructor Destroy; override;
|
|
{ IJclPackable }
|
|
procedure Pack; override;
|
|
procedure SetCapacity(Value: Integer); override;
|
|
{ IJclIntegerQueue }
|
|
procedure Clear;
|
|
function Contains(AValue: Integer): Boolean;
|
|
function Dequeue: Integer;
|
|
function Empty: Boolean;
|
|
function Enqueue(AValue: Integer): Boolean;
|
|
function Peek: Integer;
|
|
function Size: Integer;
|
|
end;
|
|
|
|
TJclCardinalQueue = class(TJclCardinalAbstractContainer, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclCardinalEqualityComparer,
|
|
IJclCardinalQueue)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
private
|
|
FElements: TDynCardinalArray;
|
|
FHead: Integer;
|
|
FTail: Integer;
|
|
protected
|
|
procedure AssignDataTo(Dest: TJclAbstractContainerBase); override;
|
|
public
|
|
constructor Create(ACapacity: Integer);
|
|
destructor Destroy; override;
|
|
{ IJclPackable }
|
|
procedure Pack; override;
|
|
procedure SetCapacity(Value: Integer); override;
|
|
{ IJclCardinalQueue }
|
|
procedure Clear;
|
|
function Contains(AValue: Cardinal): Boolean;
|
|
function Dequeue: Cardinal;
|
|
function Empty: Boolean;
|
|
function Enqueue(AValue: Cardinal): Boolean;
|
|
function Peek: Cardinal;
|
|
function Size: Integer;
|
|
end;
|
|
|
|
TJclInt64Queue = class(TJclInt64AbstractContainer, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclInt64EqualityComparer,
|
|
IJclInt64Queue)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
private
|
|
FElements: TDynInt64Array;
|
|
FHead: Integer;
|
|
FTail: Integer;
|
|
protected
|
|
procedure AssignDataTo(Dest: TJclAbstractContainerBase); override;
|
|
public
|
|
constructor Create(ACapacity: Integer);
|
|
destructor Destroy; override;
|
|
{ IJclPackable }
|
|
procedure Pack; override;
|
|
procedure SetCapacity(Value: Integer); override;
|
|
{ IJclInt64Queue }
|
|
procedure Clear;
|
|
function Contains(const AValue: Int64): Boolean;
|
|
function Dequeue: Int64;
|
|
function Empty: Boolean;
|
|
function Enqueue(const AValue: Int64): Boolean;
|
|
function Peek: Int64;
|
|
function Size: Integer;
|
|
end;
|
|
|
|
TJclPtrQueue = class(TJclPtrAbstractContainer, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclPtrEqualityComparer,
|
|
IJclPtrQueue)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
private
|
|
FElements: TDynPointerArray;
|
|
FHead: Integer;
|
|
FTail: Integer;
|
|
protected
|
|
procedure AssignDataTo(Dest: TJclAbstractContainerBase); override;
|
|
public
|
|
constructor Create(ACapacity: Integer);
|
|
destructor Destroy; override;
|
|
{ IJclPackable }
|
|
procedure Pack; override;
|
|
procedure SetCapacity(Value: Integer); override;
|
|
{ IJclPtrQueue }
|
|
procedure Clear;
|
|
function Contains(APtr: Pointer): Boolean;
|
|
function Dequeue: Pointer;
|
|
function Empty: Boolean;
|
|
function Enqueue(APtr: Pointer): Boolean;
|
|
function Peek: Pointer;
|
|
function Size: Integer;
|
|
end;
|
|
|
|
TJclQueue = class(TJclAbstractContainer, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclEqualityComparer, IJclObjectOwner,
|
|
IJclQueue)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
private
|
|
FElements: TDynObjectArray;
|
|
FHead: Integer;
|
|
FTail: Integer;
|
|
protected
|
|
procedure AssignDataTo(Dest: TJclAbstractContainerBase); override;
|
|
public
|
|
constructor Create(ACapacity: Integer; AOwnsObjects: Boolean);
|
|
destructor Destroy; override;
|
|
{ IJclPackable }
|
|
procedure Pack; override;
|
|
procedure SetCapacity(Value: Integer); override;
|
|
{ IJclQueue }
|
|
procedure Clear;
|
|
function Contains(AObject: TObject): Boolean;
|
|
function Dequeue: TObject;
|
|
function Empty: Boolean;
|
|
function Enqueue(AObject: TObject): Boolean;
|
|
function Peek: TObject;
|
|
function Size: Integer;
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_GENERICS}
|
|
|
|
TJclQueue<T> = class(TJclAbstractContainer<T>, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclEqualityComparer<T>, IJclItemOwner<T>,
|
|
IJclQueue<T>)
|
|
protected
|
|
type
|
|
TDynArray = array of T;
|
|
procedure MoveArray(var List: TDynArray; FromIndex, ToIndex, Count: Integer);
|
|
private
|
|
FElements: TDynArray;
|
|
FHead: Integer;
|
|
FTail: Integer;
|
|
protected
|
|
procedure AssignDataTo(Dest: TJclAbstractContainerBase); override;
|
|
public
|
|
constructor Create(ACapacity: Integer; AOwnsItems: Boolean);
|
|
destructor Destroy; override;
|
|
{ IJclPackable }
|
|
procedure Pack; override;
|
|
procedure SetCapacity(Value: Integer); override;
|
|
{ IJclQueue<T> }
|
|
procedure Clear;
|
|
function Contains(const AItem: T): Boolean;
|
|
function Dequeue: T;
|
|
function Empty: Boolean;
|
|
function Enqueue(const AItem: T): Boolean;
|
|
function Peek: T;
|
|
function Size: Integer;
|
|
end;
|
|
|
|
// E = external helper to compare items for equality (GetHashCode is not used)
|
|
TJclQueueE<T> = class(TJclQueue<T>, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclQueue<T>, IJclItemOwner<T>)
|
|
private
|
|
FEqualityComparer: IEqualityComparer<T>;
|
|
protected
|
|
procedure AssignPropertiesTo(Dest: TJclAbstractContainerBase); override;
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
public
|
|
constructor Create(const AEqualityComparer: IEqualityComparer<T>; ACapacity: Integer; AOwnsItems: Boolean);
|
|
{ IJclEqualityComparer<T> }
|
|
function ItemsEqual(const A, B: T): Boolean; override;
|
|
property EqualityComparer: IEqualityComparer<T> read FEqualityComparer write FEqualityComparer;
|
|
end;
|
|
|
|
// F = function to compare items for equality
|
|
TJclQueueF<T> = class(TJclQueue<T>, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclQueue<T>, IJclItemOwner<T>)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
public
|
|
constructor Create(AEqualityCompare: TEqualityCompare<T>; ACapacity: Integer; AOwnsItems: Boolean);
|
|
end;
|
|
|
|
// I = items can compare themselves to an other
|
|
TJclQueueI<T: IEquatable<T>> = class(TJclQueue<T>, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE}
|
|
IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclQueue<T>, IJclItemOwner<T>)
|
|
protected
|
|
function CreateEmptyContainer: TJclAbstractContainerBase; override;
|
|
public
|
|
{ IJclEqualityComparer<T> }
|
|
function ItemsEqual(const A, B: T): Boolean; override;
|
|
end;
|
|
{$ENDIF SUPPORTS_GENERICS}
|
|
|
|
{$IFDEF UNITVERSIONING}
|
|
const
|
|
UnitVersioning: TUnitVersionInfo = (
|
|
RCSfile: '$URL: https://jcl.svn.sourceforge.net/svnroot/jcl/tags/JCL-2.1-Build3536/jcl/source/common/JclQueues.pas $';
|
|
Revision: '$Revision: 2997 $';
|
|
Date: '$Date: 2009-09-12 14:21:23 +0200 (sam., 12 sept. 2009) $';
|
|
LogPath: 'JCL\source\common';
|
|
Extra: '';
|
|
Data: nil
|
|
);
|
|
{$ENDIF UNITVERSIONING}
|
|
|
|
implementation
|
|
|
|
uses
|
|
SysUtils;
|
|
|
|
//=== { TJclIntfQueue } =======================================================
|
|
|
|
constructor TJclIntfQueue.Create(ACapacity: Integer);
|
|
begin
|
|
inherited Create();
|
|
FHead := 0;
|
|
FTail := 0;
|
|
SetCapacity(ACapacity);
|
|
end;
|
|
|
|
destructor TJclIntfQueue.Destroy;
|
|
begin
|
|
FReadOnly := False;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJclIntfQueue.AssignDataTo(Dest: TJclAbstractContainerBase);
|
|
var
|
|
ADest: TJclIntfQueue;
|
|
I: Integer;
|
|
begin
|
|
inherited AssignDataTo(Dest);
|
|
if Dest is TJclIntfQueue then
|
|
begin
|
|
ADest := TJclIntfQueue(Dest);
|
|
ADest.Clear;
|
|
ADest.SetCapacity(Size + 1);
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
ADest.Enqueue(FElements[I]);
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclIntfQueue.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
FreeObject(FElements[I]);
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
FHead := 0;
|
|
FTail := 0;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntfQueue.Contains(const AInterface: IInterface): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
if ItemsEqual(FElements[I], AInterface) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntfQueue.Dequeue: IInterface;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := nil;
|
|
if FTail <> FHead then
|
|
begin
|
|
Result := FElements[FHead];
|
|
FElements[FHead] := nil;
|
|
Inc(FHead);
|
|
if FHead = FCapacity then
|
|
FHead := 0;
|
|
AutoPack;
|
|
end
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create('');
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntfQueue.Empty: Boolean;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FTail = FHead;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntfQueue.Enqueue(const AInterface: IInterface): Boolean;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (FTail = (FHead - 1)) or (FTail = (FHead + FCapacity - 1)) then
|
|
AutoGrow;
|
|
Result := (FTail <> (FHead - 1)) and (FTail <> (FHead + FCapacity - 1));
|
|
if Result then
|
|
begin
|
|
FElements[FTail] := AInterface;
|
|
Inc(FTail);
|
|
if FTail = FCapacity then
|
|
FTail := 0;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclIntfQueue.Pack;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
SetCapacity(Size + 1);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntfQueue.Peek: IInterface;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := nil;
|
|
if FTail <> FHead then
|
|
Result := FElements[FHead]
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create('');
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclIntfQueue.SetCapacity(Value: Integer);
|
|
var
|
|
NewHead: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if Value < 1 then
|
|
raise EJclIllegalQueueCapacityError.Create;
|
|
if Value <= Size then
|
|
raise EJclOutOfBoundsError.Create;
|
|
|
|
if FHead > FTail then // looped
|
|
begin
|
|
NewHead := FHead + Value - FCapacity;
|
|
if Value > FCapacity then
|
|
// growing
|
|
SetLength(FElements, Value);
|
|
MoveArray(FElements, FHead, NewHead, FCapacity - FHead);
|
|
if FCapacity > Value then
|
|
// packing
|
|
SetLength(FElements, Value);
|
|
FHead := NewHead;
|
|
end
|
|
else
|
|
begin
|
|
// unlooped
|
|
if Value < FCapacity then
|
|
begin
|
|
MoveArray(FElements, FHead, 0, FTail - FHead);
|
|
Dec(FTail, FHead);
|
|
FHead := 0;
|
|
end;
|
|
SetLength(FElements, Value);
|
|
end;
|
|
inherited SetCapacity(Value);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntfQueue.Size: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if FHead > FTail then
|
|
Result := FCapacity - FHead + FTail // looped
|
|
else
|
|
Result := FTail - FHead;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntfQueue.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclIntfQueue.Create(Size + 1);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
//=== { TJclAnsiStrQueue } =======================================================
|
|
|
|
constructor TJclAnsiStrQueue.Create(ACapacity: Integer);
|
|
begin
|
|
inherited Create();
|
|
FHead := 0;
|
|
FTail := 0;
|
|
SetCapacity(ACapacity);
|
|
end;
|
|
|
|
destructor TJclAnsiStrQueue.Destroy;
|
|
begin
|
|
FReadOnly := False;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJclAnsiStrQueue.AssignDataTo(Dest: TJclAbstractContainerBase);
|
|
var
|
|
ADest: TJclAnsiStrQueue;
|
|
I: Integer;
|
|
begin
|
|
inherited AssignDataTo(Dest);
|
|
if Dest is TJclAnsiStrQueue then
|
|
begin
|
|
ADest := TJclAnsiStrQueue(Dest);
|
|
ADest.Clear;
|
|
ADest.SetCapacity(Size + 1);
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
ADest.Enqueue(FElements[I]);
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclAnsiStrQueue.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
FreeString(FElements[I]);
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
FHead := 0;
|
|
FTail := 0;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclAnsiStrQueue.Contains(const AString: AnsiString): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
if ItemsEqual(FElements[I], AString) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclAnsiStrQueue.Dequeue: AnsiString;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := '';
|
|
if FTail <> FHead then
|
|
begin
|
|
Result := FElements[FHead];
|
|
FElements[FHead] := '';
|
|
Inc(FHead);
|
|
if FHead = FCapacity then
|
|
FHead := 0;
|
|
AutoPack;
|
|
end
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create('');
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclAnsiStrQueue.Empty: Boolean;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FTail = FHead;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclAnsiStrQueue.Enqueue(const AString: AnsiString): Boolean;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (FTail = (FHead - 1)) or (FTail = (FHead + FCapacity - 1)) then
|
|
AutoGrow;
|
|
Result := (FTail <> (FHead - 1)) and (FTail <> (FHead + FCapacity - 1));
|
|
if Result then
|
|
begin
|
|
FElements[FTail] := AString;
|
|
Inc(FTail);
|
|
if FTail = FCapacity then
|
|
FTail := 0;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclAnsiStrQueue.Pack;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
SetCapacity(Size + 1);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclAnsiStrQueue.Peek: AnsiString;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := '';
|
|
if FTail <> FHead then
|
|
Result := FElements[FHead]
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create('');
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclAnsiStrQueue.SetCapacity(Value: Integer);
|
|
var
|
|
NewHead: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if Value < 1 then
|
|
raise EJclIllegalQueueCapacityError.Create;
|
|
if Value <= Size then
|
|
raise EJclOutOfBoundsError.Create;
|
|
|
|
if FHead > FTail then // looped
|
|
begin
|
|
NewHead := FHead + Value - FCapacity;
|
|
if Value > FCapacity then
|
|
// growing
|
|
SetLength(FElements, Value);
|
|
MoveArray(FElements, FHead, NewHead, FCapacity - FHead);
|
|
if FCapacity > Value then
|
|
// packing
|
|
SetLength(FElements, Value);
|
|
FHead := NewHead;
|
|
end
|
|
else
|
|
begin
|
|
// unlooped
|
|
if Value < FCapacity then
|
|
begin
|
|
MoveArray(FElements, FHead, 0, FTail - FHead);
|
|
Dec(FTail, FHead);
|
|
FHead := 0;
|
|
end;
|
|
SetLength(FElements, Value);
|
|
end;
|
|
inherited SetCapacity(Value);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclAnsiStrQueue.Size: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if FHead > FTail then
|
|
Result := FCapacity - FHead + FTail // looped
|
|
else
|
|
Result := FTail - FHead;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclAnsiStrQueue.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclAnsiStrQueue.Create(Size + 1);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
//=== { TJclWideStrQueue } =======================================================
|
|
|
|
constructor TJclWideStrQueue.Create(ACapacity: Integer);
|
|
begin
|
|
inherited Create();
|
|
FHead := 0;
|
|
FTail := 0;
|
|
SetCapacity(ACapacity);
|
|
end;
|
|
|
|
destructor TJclWideStrQueue.Destroy;
|
|
begin
|
|
FReadOnly := False;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJclWideStrQueue.AssignDataTo(Dest: TJclAbstractContainerBase);
|
|
var
|
|
ADest: TJclWideStrQueue;
|
|
I: Integer;
|
|
begin
|
|
inherited AssignDataTo(Dest);
|
|
if Dest is TJclWideStrQueue then
|
|
begin
|
|
ADest := TJclWideStrQueue(Dest);
|
|
ADest.Clear;
|
|
ADest.SetCapacity(Size + 1);
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
ADest.Enqueue(FElements[I]);
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclWideStrQueue.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
FreeString(FElements[I]);
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
FHead := 0;
|
|
FTail := 0;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclWideStrQueue.Contains(const AString: WideString): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
if ItemsEqual(FElements[I], AString) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclWideStrQueue.Dequeue: WideString;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := '';
|
|
if FTail <> FHead then
|
|
begin
|
|
Result := FElements[FHead];
|
|
FElements[FHead] := '';
|
|
Inc(FHead);
|
|
if FHead = FCapacity then
|
|
FHead := 0;
|
|
AutoPack;
|
|
end
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create('');
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclWideStrQueue.Empty: Boolean;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FTail = FHead;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclWideStrQueue.Enqueue(const AString: WideString): Boolean;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (FTail = (FHead - 1)) or (FTail = (FHead + FCapacity - 1)) then
|
|
AutoGrow;
|
|
Result := (FTail <> (FHead - 1)) and (FTail <> (FHead + FCapacity - 1));
|
|
if Result then
|
|
begin
|
|
FElements[FTail] := AString;
|
|
Inc(FTail);
|
|
if FTail = FCapacity then
|
|
FTail := 0;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclWideStrQueue.Pack;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
SetCapacity(Size + 1);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclWideStrQueue.Peek: WideString;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := '';
|
|
if FTail <> FHead then
|
|
Result := FElements[FHead]
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create('');
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclWideStrQueue.SetCapacity(Value: Integer);
|
|
var
|
|
NewHead: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if Value < 1 then
|
|
raise EJclIllegalQueueCapacityError.Create;
|
|
if Value <= Size then
|
|
raise EJclOutOfBoundsError.Create;
|
|
|
|
if FHead > FTail then // looped
|
|
begin
|
|
NewHead := FHead + Value - FCapacity;
|
|
if Value > FCapacity then
|
|
// growing
|
|
SetLength(FElements, Value);
|
|
MoveArray(FElements, FHead, NewHead, FCapacity - FHead);
|
|
if FCapacity > Value then
|
|
// packing
|
|
SetLength(FElements, Value);
|
|
FHead := NewHead;
|
|
end
|
|
else
|
|
begin
|
|
// unlooped
|
|
if Value < FCapacity then
|
|
begin
|
|
MoveArray(FElements, FHead, 0, FTail - FHead);
|
|
Dec(FTail, FHead);
|
|
FHead := 0;
|
|
end;
|
|
SetLength(FElements, Value);
|
|
end;
|
|
inherited SetCapacity(Value);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclWideStrQueue.Size: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if FHead > FTail then
|
|
Result := FCapacity - FHead + FTail // looped
|
|
else
|
|
Result := FTail - FHead;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclWideStrQueue.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclWideStrQueue.Create(Size + 1);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_UNICODE_STRING}
|
|
//=== { TJclUnicodeStrQueue } =======================================================
|
|
|
|
constructor TJclUnicodeStrQueue.Create(ACapacity: Integer);
|
|
begin
|
|
inherited Create();
|
|
FHead := 0;
|
|
FTail := 0;
|
|
SetCapacity(ACapacity);
|
|
end;
|
|
|
|
destructor TJclUnicodeStrQueue.Destroy;
|
|
begin
|
|
FReadOnly := False;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJclUnicodeStrQueue.AssignDataTo(Dest: TJclAbstractContainerBase);
|
|
var
|
|
ADest: TJclUnicodeStrQueue;
|
|
I: Integer;
|
|
begin
|
|
inherited AssignDataTo(Dest);
|
|
if Dest is TJclUnicodeStrQueue then
|
|
begin
|
|
ADest := TJclUnicodeStrQueue(Dest);
|
|
ADest.Clear;
|
|
ADest.SetCapacity(Size + 1);
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
ADest.Enqueue(FElements[I]);
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclUnicodeStrQueue.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
FreeString(FElements[I]);
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
FHead := 0;
|
|
FTail := 0;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclUnicodeStrQueue.Contains(const AString: UnicodeString): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
if ItemsEqual(FElements[I], AString) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclUnicodeStrQueue.Dequeue: UnicodeString;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := '';
|
|
if FTail <> FHead then
|
|
begin
|
|
Result := FElements[FHead];
|
|
FElements[FHead] := '';
|
|
Inc(FHead);
|
|
if FHead = FCapacity then
|
|
FHead := 0;
|
|
AutoPack;
|
|
end
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create('');
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclUnicodeStrQueue.Empty: Boolean;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FTail = FHead;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclUnicodeStrQueue.Enqueue(const AString: UnicodeString): Boolean;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (FTail = (FHead - 1)) or (FTail = (FHead + FCapacity - 1)) then
|
|
AutoGrow;
|
|
Result := (FTail <> (FHead - 1)) and (FTail <> (FHead + FCapacity - 1));
|
|
if Result then
|
|
begin
|
|
FElements[FTail] := AString;
|
|
Inc(FTail);
|
|
if FTail = FCapacity then
|
|
FTail := 0;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclUnicodeStrQueue.Pack;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
SetCapacity(Size + 1);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclUnicodeStrQueue.Peek: UnicodeString;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := '';
|
|
if FTail <> FHead then
|
|
Result := FElements[FHead]
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create('');
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclUnicodeStrQueue.SetCapacity(Value: Integer);
|
|
var
|
|
NewHead: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if Value < 1 then
|
|
raise EJclIllegalQueueCapacityError.Create;
|
|
if Value <= Size then
|
|
raise EJclOutOfBoundsError.Create;
|
|
|
|
if FHead > FTail then // looped
|
|
begin
|
|
NewHead := FHead + Value - FCapacity;
|
|
if Value > FCapacity then
|
|
// growing
|
|
SetLength(FElements, Value);
|
|
MoveArray(FElements, FHead, NewHead, FCapacity - FHead);
|
|
if FCapacity > Value then
|
|
// packing
|
|
SetLength(FElements, Value);
|
|
FHead := NewHead;
|
|
end
|
|
else
|
|
begin
|
|
// unlooped
|
|
if Value < FCapacity then
|
|
begin
|
|
MoveArray(FElements, FHead, 0, FTail - FHead);
|
|
Dec(FTail, FHead);
|
|
FHead := 0;
|
|
end;
|
|
SetLength(FElements, Value);
|
|
end;
|
|
inherited SetCapacity(Value);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclUnicodeStrQueue.Size: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if FHead > FTail then
|
|
Result := FCapacity - FHead + FTail // looped
|
|
else
|
|
Result := FTail - FHead;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclUnicodeStrQueue.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclUnicodeStrQueue.Create(Size + 1);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
{$ENDIF SUPPORTS_UNICODE_STRING}
|
|
|
|
//=== { TJclSingleQueue } =======================================================
|
|
|
|
constructor TJclSingleQueue.Create(ACapacity: Integer);
|
|
begin
|
|
inherited Create();
|
|
FHead := 0;
|
|
FTail := 0;
|
|
SetCapacity(ACapacity);
|
|
end;
|
|
|
|
destructor TJclSingleQueue.Destroy;
|
|
begin
|
|
FReadOnly := False;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJclSingleQueue.AssignDataTo(Dest: TJclAbstractContainerBase);
|
|
var
|
|
ADest: TJclSingleQueue;
|
|
I: Integer;
|
|
begin
|
|
inherited AssignDataTo(Dest);
|
|
if Dest is TJclSingleQueue then
|
|
begin
|
|
ADest := TJclSingleQueue(Dest);
|
|
ADest.Clear;
|
|
ADest.SetCapacity(Size + 1);
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
ADest.Enqueue(FElements[I]);
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclSingleQueue.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
FreeSingle(FElements[I]);
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
FHead := 0;
|
|
FTail := 0;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclSingleQueue.Contains(const AValue: Single): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
if ItemsEqual(FElements[I], AValue) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclSingleQueue.Dequeue: Single;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := 0.0;
|
|
if FTail <> FHead then
|
|
begin
|
|
Result := FElements[FHead];
|
|
FElements[FHead] := 0.0;
|
|
Inc(FHead);
|
|
if FHead = FCapacity then
|
|
FHead := 0;
|
|
AutoPack;
|
|
end
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create('');
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclSingleQueue.Empty: Boolean;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FTail = FHead;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclSingleQueue.Enqueue(const AValue: Single): Boolean;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (FTail = (FHead - 1)) or (FTail = (FHead + FCapacity - 1)) then
|
|
AutoGrow;
|
|
Result := (FTail <> (FHead - 1)) and (FTail <> (FHead + FCapacity - 1));
|
|
if Result then
|
|
begin
|
|
FElements[FTail] := AValue;
|
|
Inc(FTail);
|
|
if FTail = FCapacity then
|
|
FTail := 0;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclSingleQueue.Pack;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
SetCapacity(Size + 1);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclSingleQueue.Peek: Single;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := 0.0;
|
|
if FTail <> FHead then
|
|
Result := FElements[FHead]
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create('');
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclSingleQueue.SetCapacity(Value: Integer);
|
|
var
|
|
NewHead: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if Value < 1 then
|
|
raise EJclIllegalQueueCapacityError.Create;
|
|
if Value <= Size then
|
|
raise EJclOutOfBoundsError.Create;
|
|
|
|
if FHead > FTail then // looped
|
|
begin
|
|
NewHead := FHead + Value - FCapacity;
|
|
if Value > FCapacity then
|
|
// growing
|
|
SetLength(FElements, Value);
|
|
MoveArray(FElements, FHead, NewHead, FCapacity - FHead);
|
|
if FCapacity > Value then
|
|
// packing
|
|
SetLength(FElements, Value);
|
|
FHead := NewHead;
|
|
end
|
|
else
|
|
begin
|
|
// unlooped
|
|
if Value < FCapacity then
|
|
begin
|
|
MoveArray(FElements, FHead, 0, FTail - FHead);
|
|
Dec(FTail, FHead);
|
|
FHead := 0;
|
|
end;
|
|
SetLength(FElements, Value);
|
|
end;
|
|
inherited SetCapacity(Value);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclSingleQueue.Size: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if FHead > FTail then
|
|
Result := FCapacity - FHead + FTail // looped
|
|
else
|
|
Result := FTail - FHead;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclSingleQueue.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclSingleQueue.Create(Size + 1);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
//=== { TJclDoubleQueue } =======================================================
|
|
|
|
constructor TJclDoubleQueue.Create(ACapacity: Integer);
|
|
begin
|
|
inherited Create();
|
|
FHead := 0;
|
|
FTail := 0;
|
|
SetCapacity(ACapacity);
|
|
end;
|
|
|
|
destructor TJclDoubleQueue.Destroy;
|
|
begin
|
|
FReadOnly := False;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJclDoubleQueue.AssignDataTo(Dest: TJclAbstractContainerBase);
|
|
var
|
|
ADest: TJclDoubleQueue;
|
|
I: Integer;
|
|
begin
|
|
inherited AssignDataTo(Dest);
|
|
if Dest is TJclDoubleQueue then
|
|
begin
|
|
ADest := TJclDoubleQueue(Dest);
|
|
ADest.Clear;
|
|
ADest.SetCapacity(Size + 1);
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
ADest.Enqueue(FElements[I]);
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclDoubleQueue.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
FreeDouble(FElements[I]);
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
FHead := 0;
|
|
FTail := 0;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclDoubleQueue.Contains(const AValue: Double): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
if ItemsEqual(FElements[I], AValue) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclDoubleQueue.Dequeue: Double;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := 0.0;
|
|
if FTail <> FHead then
|
|
begin
|
|
Result := FElements[FHead];
|
|
FElements[FHead] := 0.0;
|
|
Inc(FHead);
|
|
if FHead = FCapacity then
|
|
FHead := 0;
|
|
AutoPack;
|
|
end
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create('');
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclDoubleQueue.Empty: Boolean;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FTail = FHead;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclDoubleQueue.Enqueue(const AValue: Double): Boolean;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (FTail = (FHead - 1)) or (FTail = (FHead + FCapacity - 1)) then
|
|
AutoGrow;
|
|
Result := (FTail <> (FHead - 1)) and (FTail <> (FHead + FCapacity - 1));
|
|
if Result then
|
|
begin
|
|
FElements[FTail] := AValue;
|
|
Inc(FTail);
|
|
if FTail = FCapacity then
|
|
FTail := 0;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclDoubleQueue.Pack;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
SetCapacity(Size + 1);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclDoubleQueue.Peek: Double;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := 0.0;
|
|
if FTail <> FHead then
|
|
Result := FElements[FHead]
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create('');
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclDoubleQueue.SetCapacity(Value: Integer);
|
|
var
|
|
NewHead: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if Value < 1 then
|
|
raise EJclIllegalQueueCapacityError.Create;
|
|
if Value <= Size then
|
|
raise EJclOutOfBoundsError.Create;
|
|
|
|
if FHead > FTail then // looped
|
|
begin
|
|
NewHead := FHead + Value - FCapacity;
|
|
if Value > FCapacity then
|
|
// growing
|
|
SetLength(FElements, Value);
|
|
MoveArray(FElements, FHead, NewHead, FCapacity - FHead);
|
|
if FCapacity > Value then
|
|
// packing
|
|
SetLength(FElements, Value);
|
|
FHead := NewHead;
|
|
end
|
|
else
|
|
begin
|
|
// unlooped
|
|
if Value < FCapacity then
|
|
begin
|
|
MoveArray(FElements, FHead, 0, FTail - FHead);
|
|
Dec(FTail, FHead);
|
|
FHead := 0;
|
|
end;
|
|
SetLength(FElements, Value);
|
|
end;
|
|
inherited SetCapacity(Value);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclDoubleQueue.Size: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if FHead > FTail then
|
|
Result := FCapacity - FHead + FTail // looped
|
|
else
|
|
Result := FTail - FHead;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclDoubleQueue.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclDoubleQueue.Create(Size + 1);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
//=== { TJclExtendedQueue } =======================================================
|
|
|
|
constructor TJclExtendedQueue.Create(ACapacity: Integer);
|
|
begin
|
|
inherited Create();
|
|
FHead := 0;
|
|
FTail := 0;
|
|
SetCapacity(ACapacity);
|
|
end;
|
|
|
|
destructor TJclExtendedQueue.Destroy;
|
|
begin
|
|
FReadOnly := False;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJclExtendedQueue.AssignDataTo(Dest: TJclAbstractContainerBase);
|
|
var
|
|
ADest: TJclExtendedQueue;
|
|
I: Integer;
|
|
begin
|
|
inherited AssignDataTo(Dest);
|
|
if Dest is TJclExtendedQueue then
|
|
begin
|
|
ADest := TJclExtendedQueue(Dest);
|
|
ADest.Clear;
|
|
ADest.SetCapacity(Size + 1);
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
ADest.Enqueue(FElements[I]);
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclExtendedQueue.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
FreeExtended(FElements[I]);
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
FHead := 0;
|
|
FTail := 0;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclExtendedQueue.Contains(const AValue: Extended): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
if ItemsEqual(FElements[I], AValue) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclExtendedQueue.Dequeue: Extended;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := 0.0;
|
|
if FTail <> FHead then
|
|
begin
|
|
Result := FElements[FHead];
|
|
FElements[FHead] := 0.0;
|
|
Inc(FHead);
|
|
if FHead = FCapacity then
|
|
FHead := 0;
|
|
AutoPack;
|
|
end
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create('');
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclExtendedQueue.Empty: Boolean;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FTail = FHead;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclExtendedQueue.Enqueue(const AValue: Extended): Boolean;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (FTail = (FHead - 1)) or (FTail = (FHead + FCapacity - 1)) then
|
|
AutoGrow;
|
|
Result := (FTail <> (FHead - 1)) and (FTail <> (FHead + FCapacity - 1));
|
|
if Result then
|
|
begin
|
|
FElements[FTail] := AValue;
|
|
Inc(FTail);
|
|
if FTail = FCapacity then
|
|
FTail := 0;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclExtendedQueue.Pack;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
SetCapacity(Size + 1);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclExtendedQueue.Peek: Extended;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := 0.0;
|
|
if FTail <> FHead then
|
|
Result := FElements[FHead]
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create('');
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclExtendedQueue.SetCapacity(Value: Integer);
|
|
var
|
|
NewHead: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if Value < 1 then
|
|
raise EJclIllegalQueueCapacityError.Create;
|
|
if Value <= Size then
|
|
raise EJclOutOfBoundsError.Create;
|
|
|
|
if FHead > FTail then // looped
|
|
begin
|
|
NewHead := FHead + Value - FCapacity;
|
|
if Value > FCapacity then
|
|
// growing
|
|
SetLength(FElements, Value);
|
|
MoveArray(FElements, FHead, NewHead, FCapacity - FHead);
|
|
if FCapacity > Value then
|
|
// packing
|
|
SetLength(FElements, Value);
|
|
FHead := NewHead;
|
|
end
|
|
else
|
|
begin
|
|
// unlooped
|
|
if Value < FCapacity then
|
|
begin
|
|
MoveArray(FElements, FHead, 0, FTail - FHead);
|
|
Dec(FTail, FHead);
|
|
FHead := 0;
|
|
end;
|
|
SetLength(FElements, Value);
|
|
end;
|
|
inherited SetCapacity(Value);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclExtendedQueue.Size: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if FHead > FTail then
|
|
Result := FCapacity - FHead + FTail // looped
|
|
else
|
|
Result := FTail - FHead;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclExtendedQueue.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclExtendedQueue.Create(Size + 1);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
//=== { TJclIntegerQueue } =======================================================
|
|
|
|
constructor TJclIntegerQueue.Create(ACapacity: Integer);
|
|
begin
|
|
inherited Create();
|
|
FHead := 0;
|
|
FTail := 0;
|
|
SetCapacity(ACapacity);
|
|
end;
|
|
|
|
destructor TJclIntegerQueue.Destroy;
|
|
begin
|
|
FReadOnly := False;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJclIntegerQueue.AssignDataTo(Dest: TJclAbstractContainerBase);
|
|
var
|
|
ADest: TJclIntegerQueue;
|
|
I: Integer;
|
|
begin
|
|
inherited AssignDataTo(Dest);
|
|
if Dest is TJclIntegerQueue then
|
|
begin
|
|
ADest := TJclIntegerQueue(Dest);
|
|
ADest.Clear;
|
|
ADest.SetCapacity(Size + 1);
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
ADest.Enqueue(FElements[I]);
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclIntegerQueue.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
FreeInteger(FElements[I]);
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
FHead := 0;
|
|
FTail := 0;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntegerQueue.Contains(AValue: Integer): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
if ItemsEqual(FElements[I], AValue) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntegerQueue.Dequeue: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := 0;
|
|
if FTail <> FHead then
|
|
begin
|
|
Result := FElements[FHead];
|
|
FElements[FHead] := 0;
|
|
Inc(FHead);
|
|
if FHead = FCapacity then
|
|
FHead := 0;
|
|
AutoPack;
|
|
end
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create('');
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntegerQueue.Empty: Boolean;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FTail = FHead;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntegerQueue.Enqueue(AValue: Integer): Boolean;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (FTail = (FHead - 1)) or (FTail = (FHead + FCapacity - 1)) then
|
|
AutoGrow;
|
|
Result := (FTail <> (FHead - 1)) and (FTail <> (FHead + FCapacity - 1));
|
|
if Result then
|
|
begin
|
|
FElements[FTail] := AValue;
|
|
Inc(FTail);
|
|
if FTail = FCapacity then
|
|
FTail := 0;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclIntegerQueue.Pack;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
SetCapacity(Size + 1);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntegerQueue.Peek: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := 0;
|
|
if FTail <> FHead then
|
|
Result := FElements[FHead]
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create('');
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclIntegerQueue.SetCapacity(Value: Integer);
|
|
var
|
|
NewHead: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if Value < 1 then
|
|
raise EJclIllegalQueueCapacityError.Create;
|
|
if Value <= Size then
|
|
raise EJclOutOfBoundsError.Create;
|
|
|
|
if FHead > FTail then // looped
|
|
begin
|
|
NewHead := FHead + Value - FCapacity;
|
|
if Value > FCapacity then
|
|
// growing
|
|
SetLength(FElements, Value);
|
|
MoveArray(FElements, FHead, NewHead, FCapacity - FHead);
|
|
if FCapacity > Value then
|
|
// packing
|
|
SetLength(FElements, Value);
|
|
FHead := NewHead;
|
|
end
|
|
else
|
|
begin
|
|
// unlooped
|
|
if Value < FCapacity then
|
|
begin
|
|
MoveArray(FElements, FHead, 0, FTail - FHead);
|
|
Dec(FTail, FHead);
|
|
FHead := 0;
|
|
end;
|
|
SetLength(FElements, Value);
|
|
end;
|
|
inherited SetCapacity(Value);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntegerQueue.Size: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if FHead > FTail then
|
|
Result := FCapacity - FHead + FTail // looped
|
|
else
|
|
Result := FTail - FHead;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclIntegerQueue.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclIntegerQueue.Create(Size + 1);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
//=== { TJclCardinalQueue } =======================================================
|
|
|
|
constructor TJclCardinalQueue.Create(ACapacity: Integer);
|
|
begin
|
|
inherited Create();
|
|
FHead := 0;
|
|
FTail := 0;
|
|
SetCapacity(ACapacity);
|
|
end;
|
|
|
|
destructor TJclCardinalQueue.Destroy;
|
|
begin
|
|
FReadOnly := False;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJclCardinalQueue.AssignDataTo(Dest: TJclAbstractContainerBase);
|
|
var
|
|
ADest: TJclCardinalQueue;
|
|
I: Integer;
|
|
begin
|
|
inherited AssignDataTo(Dest);
|
|
if Dest is TJclCardinalQueue then
|
|
begin
|
|
ADest := TJclCardinalQueue(Dest);
|
|
ADest.Clear;
|
|
ADest.SetCapacity(Size + 1);
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
ADest.Enqueue(FElements[I]);
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclCardinalQueue.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
FreeCardinal(FElements[I]);
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
FHead := 0;
|
|
FTail := 0;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclCardinalQueue.Contains(AValue: Cardinal): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
if ItemsEqual(FElements[I], AValue) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclCardinalQueue.Dequeue: Cardinal;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := 0;
|
|
if FTail <> FHead then
|
|
begin
|
|
Result := FElements[FHead];
|
|
FElements[FHead] := 0;
|
|
Inc(FHead);
|
|
if FHead = FCapacity then
|
|
FHead := 0;
|
|
AutoPack;
|
|
end
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create('');
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclCardinalQueue.Empty: Boolean;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FTail = FHead;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclCardinalQueue.Enqueue(AValue: Cardinal): Boolean;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (FTail = (FHead - 1)) or (FTail = (FHead + FCapacity - 1)) then
|
|
AutoGrow;
|
|
Result := (FTail <> (FHead - 1)) and (FTail <> (FHead + FCapacity - 1));
|
|
if Result then
|
|
begin
|
|
FElements[FTail] := AValue;
|
|
Inc(FTail);
|
|
if FTail = FCapacity then
|
|
FTail := 0;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclCardinalQueue.Pack;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
SetCapacity(Size + 1);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclCardinalQueue.Peek: Cardinal;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := 0;
|
|
if FTail <> FHead then
|
|
Result := FElements[FHead]
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create('');
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclCardinalQueue.SetCapacity(Value: Integer);
|
|
var
|
|
NewHead: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if Value < 1 then
|
|
raise EJclIllegalQueueCapacityError.Create;
|
|
if Value <= Size then
|
|
raise EJclOutOfBoundsError.Create;
|
|
|
|
if FHead > FTail then // looped
|
|
begin
|
|
NewHead := FHead + Value - FCapacity;
|
|
if Value > FCapacity then
|
|
// growing
|
|
SetLength(FElements, Value);
|
|
MoveArray(FElements, FHead, NewHead, FCapacity - FHead);
|
|
if FCapacity > Value then
|
|
// packing
|
|
SetLength(FElements, Value);
|
|
FHead := NewHead;
|
|
end
|
|
else
|
|
begin
|
|
// unlooped
|
|
if Value < FCapacity then
|
|
begin
|
|
MoveArray(FElements, FHead, 0, FTail - FHead);
|
|
Dec(FTail, FHead);
|
|
FHead := 0;
|
|
end;
|
|
SetLength(FElements, Value);
|
|
end;
|
|
inherited SetCapacity(Value);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclCardinalQueue.Size: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if FHead > FTail then
|
|
Result := FCapacity - FHead + FTail // looped
|
|
else
|
|
Result := FTail - FHead;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclCardinalQueue.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclCardinalQueue.Create(Size + 1);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
//=== { TJclInt64Queue } =======================================================
|
|
|
|
constructor TJclInt64Queue.Create(ACapacity: Integer);
|
|
begin
|
|
inherited Create();
|
|
FHead := 0;
|
|
FTail := 0;
|
|
SetCapacity(ACapacity);
|
|
end;
|
|
|
|
destructor TJclInt64Queue.Destroy;
|
|
begin
|
|
FReadOnly := False;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJclInt64Queue.AssignDataTo(Dest: TJclAbstractContainerBase);
|
|
var
|
|
ADest: TJclInt64Queue;
|
|
I: Integer;
|
|
begin
|
|
inherited AssignDataTo(Dest);
|
|
if Dest is TJclInt64Queue then
|
|
begin
|
|
ADest := TJclInt64Queue(Dest);
|
|
ADest.Clear;
|
|
ADest.SetCapacity(Size + 1);
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
ADest.Enqueue(FElements[I]);
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclInt64Queue.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
FreeInt64(FElements[I]);
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
FHead := 0;
|
|
FTail := 0;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclInt64Queue.Contains(const AValue: Int64): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
if ItemsEqual(FElements[I], AValue) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclInt64Queue.Dequeue: Int64;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := 0;
|
|
if FTail <> FHead then
|
|
begin
|
|
Result := FElements[FHead];
|
|
FElements[FHead] := 0;
|
|
Inc(FHead);
|
|
if FHead = FCapacity then
|
|
FHead := 0;
|
|
AutoPack;
|
|
end
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create('');
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclInt64Queue.Empty: Boolean;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FTail = FHead;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclInt64Queue.Enqueue(const AValue: Int64): Boolean;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (FTail = (FHead - 1)) or (FTail = (FHead + FCapacity - 1)) then
|
|
AutoGrow;
|
|
Result := (FTail <> (FHead - 1)) and (FTail <> (FHead + FCapacity - 1));
|
|
if Result then
|
|
begin
|
|
FElements[FTail] := AValue;
|
|
Inc(FTail);
|
|
if FTail = FCapacity then
|
|
FTail := 0;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclInt64Queue.Pack;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
SetCapacity(Size + 1);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclInt64Queue.Peek: Int64;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := 0;
|
|
if FTail <> FHead then
|
|
Result := FElements[FHead]
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create('');
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclInt64Queue.SetCapacity(Value: Integer);
|
|
var
|
|
NewHead: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if Value < 1 then
|
|
raise EJclIllegalQueueCapacityError.Create;
|
|
if Value <= Size then
|
|
raise EJclOutOfBoundsError.Create;
|
|
|
|
if FHead > FTail then // looped
|
|
begin
|
|
NewHead := FHead + Value - FCapacity;
|
|
if Value > FCapacity then
|
|
// growing
|
|
SetLength(FElements, Value);
|
|
MoveArray(FElements, FHead, NewHead, FCapacity - FHead);
|
|
if FCapacity > Value then
|
|
// packing
|
|
SetLength(FElements, Value);
|
|
FHead := NewHead;
|
|
end
|
|
else
|
|
begin
|
|
// unlooped
|
|
if Value < FCapacity then
|
|
begin
|
|
MoveArray(FElements, FHead, 0, FTail - FHead);
|
|
Dec(FTail, FHead);
|
|
FHead := 0;
|
|
end;
|
|
SetLength(FElements, Value);
|
|
end;
|
|
inherited SetCapacity(Value);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclInt64Queue.Size: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if FHead > FTail then
|
|
Result := FCapacity - FHead + FTail // looped
|
|
else
|
|
Result := FTail - FHead;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclInt64Queue.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclInt64Queue.Create(Size + 1);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
//=== { TJclPtrQueue } =======================================================
|
|
|
|
constructor TJclPtrQueue.Create(ACapacity: Integer);
|
|
begin
|
|
inherited Create();
|
|
FHead := 0;
|
|
FTail := 0;
|
|
SetCapacity(ACapacity);
|
|
end;
|
|
|
|
destructor TJclPtrQueue.Destroy;
|
|
begin
|
|
FReadOnly := False;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJclPtrQueue.AssignDataTo(Dest: TJclAbstractContainerBase);
|
|
var
|
|
ADest: TJclPtrQueue;
|
|
I: Integer;
|
|
begin
|
|
inherited AssignDataTo(Dest);
|
|
if Dest is TJclPtrQueue then
|
|
begin
|
|
ADest := TJclPtrQueue(Dest);
|
|
ADest.Clear;
|
|
ADest.SetCapacity(Size + 1);
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
ADest.Enqueue(FElements[I]);
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclPtrQueue.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
FreePointer(FElements[I]);
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
FHead := 0;
|
|
FTail := 0;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclPtrQueue.Contains(APtr: Pointer): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
if ItemsEqual(FElements[I], APtr) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclPtrQueue.Dequeue: Pointer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := nil;
|
|
if FTail <> FHead then
|
|
begin
|
|
Result := FElements[FHead];
|
|
FElements[FHead] := nil;
|
|
Inc(FHead);
|
|
if FHead = FCapacity then
|
|
FHead := 0;
|
|
AutoPack;
|
|
end
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create('');
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclPtrQueue.Empty: Boolean;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FTail = FHead;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclPtrQueue.Enqueue(APtr: Pointer): Boolean;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (FTail = (FHead - 1)) or (FTail = (FHead + FCapacity - 1)) then
|
|
AutoGrow;
|
|
Result := (FTail <> (FHead - 1)) and (FTail <> (FHead + FCapacity - 1));
|
|
if Result then
|
|
begin
|
|
FElements[FTail] := APtr;
|
|
Inc(FTail);
|
|
if FTail = FCapacity then
|
|
FTail := 0;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclPtrQueue.Pack;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
SetCapacity(Size + 1);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclPtrQueue.Peek: Pointer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := nil;
|
|
if FTail <> FHead then
|
|
Result := FElements[FHead]
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create('');
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclPtrQueue.SetCapacity(Value: Integer);
|
|
var
|
|
NewHead: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if Value < 1 then
|
|
raise EJclIllegalQueueCapacityError.Create;
|
|
if Value <= Size then
|
|
raise EJclOutOfBoundsError.Create;
|
|
|
|
if FHead > FTail then // looped
|
|
begin
|
|
NewHead := FHead + Value - FCapacity;
|
|
if Value > FCapacity then
|
|
// growing
|
|
SetLength(FElements, Value);
|
|
MoveArray(FElements, FHead, NewHead, FCapacity - FHead);
|
|
if FCapacity > Value then
|
|
// packing
|
|
SetLength(FElements, Value);
|
|
FHead := NewHead;
|
|
end
|
|
else
|
|
begin
|
|
// unlooped
|
|
if Value < FCapacity then
|
|
begin
|
|
MoveArray(FElements, FHead, 0, FTail - FHead);
|
|
Dec(FTail, FHead);
|
|
FHead := 0;
|
|
end;
|
|
SetLength(FElements, Value);
|
|
end;
|
|
inherited SetCapacity(Value);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclPtrQueue.Size: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if FHead > FTail then
|
|
Result := FCapacity - FHead + FTail // looped
|
|
else
|
|
Result := FTail - FHead;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclPtrQueue.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclPtrQueue.Create(Size + 1);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
//=== { TJclQueue } =======================================================
|
|
|
|
constructor TJclQueue.Create(ACapacity: Integer; AOwnsObjects: Boolean);
|
|
begin
|
|
inherited Create(AOwnsObjects);
|
|
FHead := 0;
|
|
FTail := 0;
|
|
SetCapacity(ACapacity);
|
|
end;
|
|
|
|
destructor TJclQueue.Destroy;
|
|
begin
|
|
FReadOnly := False;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJclQueue.AssignDataTo(Dest: TJclAbstractContainerBase);
|
|
var
|
|
ADest: TJclQueue;
|
|
I: Integer;
|
|
begin
|
|
inherited AssignDataTo(Dest);
|
|
if Dest is TJclQueue then
|
|
begin
|
|
ADest := TJclQueue(Dest);
|
|
ADest.Clear;
|
|
ADest.SetCapacity(Size + 1);
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
ADest.Enqueue(FElements[I]);
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclQueue.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
FreeObject(FElements[I]);
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
FHead := 0;
|
|
FTail := 0;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclQueue.Contains(AObject: TObject): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
if ItemsEqual(FElements[I], AObject) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclQueue.Dequeue: TObject;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := nil;
|
|
if FTail <> FHead then
|
|
begin
|
|
Result := FElements[FHead];
|
|
FElements[FHead] := nil;
|
|
Inc(FHead);
|
|
if FHead = FCapacity then
|
|
FHead := 0;
|
|
AutoPack;
|
|
end
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create('');
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclQueue.Empty: Boolean;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FTail = FHead;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclQueue.Enqueue(AObject: TObject): Boolean;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (FTail = (FHead - 1)) or (FTail = (FHead + FCapacity - 1)) then
|
|
AutoGrow;
|
|
Result := (FTail <> (FHead - 1)) and (FTail <> (FHead + FCapacity - 1));
|
|
if Result then
|
|
begin
|
|
FElements[FTail] := AObject;
|
|
Inc(FTail);
|
|
if FTail = FCapacity then
|
|
FTail := 0;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclQueue.Pack;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
SetCapacity(Size + 1);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclQueue.Peek: TObject;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := nil;
|
|
if FTail <> FHead then
|
|
Result := FElements[FHead]
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create('');
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclQueue.SetCapacity(Value: Integer);
|
|
var
|
|
NewHead: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if Value < 1 then
|
|
raise EJclIllegalQueueCapacityError.Create;
|
|
if Value <= Size then
|
|
raise EJclOutOfBoundsError.Create;
|
|
|
|
if FHead > FTail then // looped
|
|
begin
|
|
NewHead := FHead + Value - FCapacity;
|
|
if Value > FCapacity then
|
|
// growing
|
|
SetLength(FElements, Value);
|
|
MoveArray(FElements, FHead, NewHead, FCapacity - FHead);
|
|
if FCapacity > Value then
|
|
// packing
|
|
SetLength(FElements, Value);
|
|
FHead := NewHead;
|
|
end
|
|
else
|
|
begin
|
|
// unlooped
|
|
if Value < FCapacity then
|
|
begin
|
|
MoveArray(FElements, FHead, 0, FTail - FHead);
|
|
Dec(FTail, FHead);
|
|
FHead := 0;
|
|
end;
|
|
SetLength(FElements, Value);
|
|
end;
|
|
inherited SetCapacity(Value);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclQueue.Size: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if FHead > FTail then
|
|
Result := FCapacity - FHead + FTail // looped
|
|
else
|
|
Result := FTail - FHead;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclQueue.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclQueue.Create(Size + 1, False);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
{$IFDEF SUPPORTS_GENERICS}
|
|
|
|
//=== { TJclQueue<T> } =======================================================
|
|
|
|
constructor TJclQueue<T>.Create(ACapacity: Integer; AOwnsItems: Boolean);
|
|
begin
|
|
inherited Create(AOwnsItems);
|
|
FHead := 0;
|
|
FTail := 0;
|
|
SetCapacity(ACapacity);
|
|
end;
|
|
|
|
destructor TJclQueue<T>.Destroy;
|
|
begin
|
|
FReadOnly := False;
|
|
Clear;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJclQueue<T>.AssignDataTo(Dest: TJclAbstractContainerBase);
|
|
var
|
|
ADest: TJclQueue<T>;
|
|
I: Integer;
|
|
begin
|
|
inherited AssignDataTo(Dest);
|
|
if Dest is TJclQueue<T> then
|
|
begin
|
|
ADest := TJclQueue<T>(Dest);
|
|
ADest.Clear;
|
|
ADest.SetCapacity(Size + 1);
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
ADest.Enqueue(FElements[I]);
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclQueue<T>.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
FreeItem(FElements[I]);
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
FHead := 0;
|
|
FTail := 0;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclQueue<T>.Contains(const AItem: T): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := False;
|
|
I := FHead;
|
|
while I <> FTail do
|
|
begin
|
|
if ItemsEqual(FElements[I], AItem) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
Inc(I);
|
|
if I = FCapacity then
|
|
I := 0;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclQueue<T>.Dequeue: T;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := Default(T);
|
|
if FTail <> FHead then
|
|
begin
|
|
Result := FElements[FHead];
|
|
FElements[FHead] := Default(T);
|
|
Inc(FHead);
|
|
if FHead = FCapacity then
|
|
FHead := 0;
|
|
AutoPack;
|
|
end
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create('');
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclQueue<T>.Empty: Boolean;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := FTail = FHead;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclQueue<T>.Enqueue(const AItem: T): Boolean;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if (FTail = (FHead - 1)) or (FTail = (FHead + FCapacity - 1)) then
|
|
AutoGrow;
|
|
Result := (FTail <> (FHead - 1)) and (FTail <> (FHead + FCapacity - 1));
|
|
if Result then
|
|
begin
|
|
FElements[FTail] := AItem;
|
|
Inc(FTail);
|
|
if FTail = FCapacity then
|
|
FTail := 0;
|
|
end;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclQueue<T>.Pack;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
SetCapacity(Size + 1);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclQueue<T>.Peek: T;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
Result := Default(T);
|
|
if FTail <> FHead then
|
|
Result := FElements[FHead]
|
|
else
|
|
if not FReturnDefaultElements then
|
|
raise EJclNoSuchElementError.Create('');
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclQueue<T>.SetCapacity(Value: Integer);
|
|
var
|
|
NewHead: Integer;
|
|
begin
|
|
if ReadOnly then
|
|
raise EJclReadOnlyError.Create;
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginWrite;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if Value < 1 then
|
|
raise EJclIllegalQueueCapacityError.Create;
|
|
if Value <= Size then
|
|
raise EJclOutOfBoundsError.Create;
|
|
|
|
if FHead > FTail then // looped
|
|
begin
|
|
NewHead := FHead + Value - FCapacity;
|
|
if Value > FCapacity then
|
|
// growing
|
|
SetLength(FElements, Value);
|
|
MoveArray(FElements, FHead, NewHead, FCapacity - FHead);
|
|
if FCapacity > Value then
|
|
// packing
|
|
SetLength(FElements, Value);
|
|
FHead := NewHead;
|
|
end
|
|
else
|
|
begin
|
|
// unlooped
|
|
if Value < FCapacity then
|
|
begin
|
|
MoveArray(FElements, FHead, 0, FTail - FHead);
|
|
Dec(FTail, FHead);
|
|
FHead := 0;
|
|
end;
|
|
SetLength(FElements, Value);
|
|
end;
|
|
inherited SetCapacity(Value);
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndWrite;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
function TJclQueue<T>.Size: Integer;
|
|
begin
|
|
{$IFDEF THREADSAFE}
|
|
if FThreadSafe then
|
|
SyncReaderWriter.BeginRead;
|
|
try
|
|
{$ENDIF THREADSAFE}
|
|
if FHead > FTail then
|
|
Result := FCapacity - FHead + FTail // looped
|
|
else
|
|
Result := FTail - FHead;
|
|
{$IFDEF THREADSAFE}
|
|
finally
|
|
if FThreadSafe then
|
|
SyncReaderWriter.EndRead;
|
|
end;
|
|
{$ENDIF THREADSAFE}
|
|
end;
|
|
|
|
procedure TJclQueue<T>.MoveArray(var List: TDynArray; FromIndex, ToIndex, Count: Integer);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if FromIndex < ToIndex then
|
|
begin
|
|
for I := Count - 1 downto 0 do
|
|
List[ToIndex + I] := List[FromIndex + I];
|
|
|
|
if (ToIndex - FromIndex) < Count then
|
|
// overlapped source and target
|
|
for I := 0 to ToIndex - FromIndex - 1 do
|
|
List[FromIndex + I] := Default(T)
|
|
else
|
|
// independant
|
|
for I := 0 to Count - 1 do
|
|
List[FromIndex + I] := Default(T);
|
|
end
|
|
else
|
|
begin
|
|
for I := 0 to Count - 1 do
|
|
List[ToIndex + I] := List[FromIndex + I];
|
|
|
|
if (FromIndex - ToIndex) < Count then
|
|
// overlapped source and target
|
|
for I := Count - FromIndex + ToIndex to Count - 1 do
|
|
List[FromIndex + I] := Default(T)
|
|
else
|
|
// independant
|
|
for I := 0 to Count - 1 do
|
|
List[FromIndex + I] := Default(T);
|
|
end;
|
|
end;
|
|
|
|
//=== { TJclQueueE<T> } ======================================================
|
|
|
|
constructor TJclQueueE<T>.Create(const AEqualityComparer: IEqualityComparer<T>;
|
|
ACapacity: Integer; AOwnsItems: Boolean);
|
|
begin
|
|
inherited Create(ACapacity, AOwnsItems);
|
|
FEqualityComparer := AEqualityComparer;
|
|
end;
|
|
|
|
procedure TJclQueueE<T>.AssignPropertiesTo(Dest: TJclAbstractContainerBase);
|
|
begin
|
|
inherited AssignPropertiesTo(Dest);
|
|
if Dest is TJclQueueE<T> then
|
|
TJclQueueE<T>(Dest).FEqualityComparer := FEqualityComparer;
|
|
end;
|
|
|
|
function TJclQueueE<T>.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclQueueE<T>.Create(EqualityComparer, Size + 1, False);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
function TJclQueueE<T>.ItemsEqual(const A, B: T): Boolean;
|
|
begin
|
|
if EqualityComparer <> nil then
|
|
Result := EqualityComparer.Equals(A, B)
|
|
else
|
|
Result := inherited ItemsEqual(A, B);
|
|
end;
|
|
|
|
//=== { TJclQueueF<T> } ======================================================
|
|
|
|
constructor TJclQueueF<T>.Create(AEqualityCompare: TEqualityCompare<T>;
|
|
ACapacity: Integer; AOwnsItems: Boolean);
|
|
begin
|
|
inherited Create(ACapacity, AOwnsItems);
|
|
SetEqualityCompare(AEqualityCompare);
|
|
end;
|
|
|
|
function TJclQueueF<T>.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclQueueF<T>.Create(EqualityCompare, Size + 1, False);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
//=== { TJclQueueI<T> } ======================================================
|
|
|
|
function TJclQueueI<T>.CreateEmptyContainer: TJclAbstractContainerBase;
|
|
begin
|
|
Result := TJclQueueI<T>.Create(Size + 1, False);
|
|
AssignPropertiesTo(Result);
|
|
end;
|
|
|
|
function TJclQueueI<T>.ItemsEqual(const A, B: T): Boolean;
|
|
begin
|
|
if Assigned(FEqualityCompare) then
|
|
Result := FEqualityCompare(A, B)
|
|
else
|
|
if Assigned(FCompare) then
|
|
Result := FCompare(A, B) = 0
|
|
else
|
|
Result := A.Equals(B);
|
|
end;
|
|
|
|
{$ENDIF SUPPORTS_GENERICS}
|
|
|
|
{$IFDEF UNITVERSIONING}
|
|
initialization
|
|
RegisterUnitVersion(HInstance, UnitVersioning);
|
|
|
|
finalization
|
|
UnregisterUnitVersion(HInstance);
|
|
{$ENDIF UNITVERSIONING}
|
|
|
|
end.
|