{**************************************************************************************************} { 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 = class(TJclAbstractContainer, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE} IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclEqualityComparer, IJclItemOwner, IJclQueue) 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 } 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 = class(TJclQueue, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE} IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclQueue, IJclItemOwner) private FEqualityComparer: IEqualityComparer; protected procedure AssignPropertiesTo(Dest: TJclAbstractContainerBase); override; function CreateEmptyContainer: TJclAbstractContainerBase; override; public constructor Create(const AEqualityComparer: IEqualityComparer; ACapacity: Integer; AOwnsItems: Boolean); { IJclEqualityComparer } function ItemsEqual(const A, B: T): Boolean; override; property EqualityComparer: IEqualityComparer read FEqualityComparer write FEqualityComparer; end; // F = function to compare items for equality TJclQueueF = class(TJclQueue, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE} IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclQueue, IJclItemOwner) protected function CreateEmptyContainer: TJclAbstractContainerBase; override; public constructor Create(AEqualityCompare: TEqualityCompare; ACapacity: Integer; AOwnsItems: Boolean); end; // I = items can compare themselves to an other TJclQueueI> = class(TJclQueue, {$IFDEF THREADSAFE} IJclLockable, {$ENDIF THREADSAFE} IJclIntfCloneable, IJclCloneable, IJclPackable, IJclGrowable, IJclContainer, IJclQueue, IJclItemOwner) protected function CreateEmptyContainer: TJclAbstractContainerBase; override; public { IJclEqualityComparer } function ItemsEqual(const A, B: T): Boolean; override; end; {$ENDIF SUPPORTS_GENERICS} {$IFDEF UNITVERSIONING} const UnitVersioning: TUnitVersionInfo = ( RCSfile: '$URL: https://jcl.svn.sourceforge.net/svnroot/jcl/tags/JCL-2.1-Build3536/jcl/source/common/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 } ======================================================= constructor TJclQueue.Create(ACapacity: Integer; AOwnsItems: Boolean); begin inherited Create(AOwnsItems); 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 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.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.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.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(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.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: 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.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; procedure TJclQueue.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 } ====================================================== constructor TJclQueueE.Create(const AEqualityComparer: IEqualityComparer; ACapacity: Integer; AOwnsItems: Boolean); begin inherited Create(ACapacity, AOwnsItems); FEqualityComparer := AEqualityComparer; end; procedure TJclQueueE.AssignPropertiesTo(Dest: TJclAbstractContainerBase); begin inherited AssignPropertiesTo(Dest); if Dest is TJclQueueE then TJclQueueE(Dest).FEqualityComparer := FEqualityComparer; end; function TJclQueueE.CreateEmptyContainer: TJclAbstractContainerBase; begin Result := TJclQueueE.Create(EqualityComparer, Size + 1, False); AssignPropertiesTo(Result); end; function TJclQueueE.ItemsEqual(const A, B: T): Boolean; begin if EqualityComparer <> nil then Result := EqualityComparer.Equals(A, B) else Result := inherited ItemsEqual(A, B); end; //=== { TJclQueueF } ====================================================== constructor TJclQueueF.Create(AEqualityCompare: TEqualityCompare; ACapacity: Integer; AOwnsItems: Boolean); begin inherited Create(ACapacity, AOwnsItems); SetEqualityCompare(AEqualityCompare); end; function TJclQueueF.CreateEmptyContainer: TJclAbstractContainerBase; begin Result := TJclQueueF.Create(EqualityCompare, Size + 1, False); AssignPropertiesTo(Result); end; //=== { TJclQueueI } ====================================================== function TJclQueueI.CreateEmptyContainer: TJclAbstractContainerBase; begin Result := TJclQueueI.Create(Size + 1, False); AssignPropertiesTo(Result); end; function TJclQueueI.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.