Скачиваний:
16
Добавлен:
01.05.2014
Размер:
17.06 Кб
Скачать
unit FastVector;

interface

uses
Classes,
DmmConstants,
DmmTypes,
StandardObject,
StandardSerializableObject,
SysUtils;

type
{Класс итератор, для перебора объетов TDMFastVector}
TDMFastVectorEnumeration = class;
{Класс, который позволяет хранить динамический массив объектов
типа TObject}
TDMFastVector = class( TDMStandardSerializableObject )
protected
m_Objects : TDMObjectArray;
m_Size : Integer;
m_Capacity : Integer;
m_ElementMemoryManagement : Boolean;

procedure freeRange( const index1, index2 : Integer );
procedure insertAtHead( element : TObject );

public
constructor Create; overload;
constructor Create( const capacity : Integer ); overload;

function elementMemoryManagement : Boolean; overload;
procedure elementMemoryManagement( flagValue : Boolean ); overload;

procedure addElement( element : TObject );
procedure insertElementAt( element : TObject; const index : Integer );
procedure appendElements( toappend : TDMFastVector );
procedure setElementAt( const index : Integer; element : TObject );
procedure removeElementAt( const index : Integer );
procedure removeAndClearElementAt( const index : Integer );
procedure removeAllElements;
procedure removeAndClearAllElements;

function elementAt( const index : Integer ) : TObject;
function firstElement : TObject;
function lastElement : TObject;
function contains( element : TObject ) : Boolean;
function indexOf( element : TObject ) : Integer;

function capacity : Integer;
procedure setCapacity( const capacity : Integer );
function size : Integer;

function copyObject : TObject; override;
function cloneObject : TObject; override;
function equals( otherObject : TObject ) : Boolean; override;

procedure trimToSize( const size : Integer ); overload;
procedure trimToSize(); overload;

function toArray : TDMObjectArray;

procedure swap( const index1, index2 : Integer );

procedure serializeObject( ostream : TStream ); override;
procedure deserializeObject( istream : TStream ); override;

function toString : AnsiString; override;

destructor Destroy; override;
end;

TDMFastVectorEnumeration = class( TDMStandardSerializableObject )
protected

m_Counter : Integer;
m_FastVector : TDMFastVector;
m_SpecialElement : Integer;

public
constructor Create( fastVector : TDMFastVector ); overload;
constructor Create( fastVector : TDMFastVector; const specialElement : Integer ); overload;

function hasMoreElements : Boolean; virtual;
function nextElement : TObject; virtual;

function cloneObject : TObject; override;
function copyObject : TObject; override;

procedure serializeObject( ostream : TStream ); override;
procedure deserializeObject( istream : TStream ); override;

destructor Destroy; override;
end;

TDMFastVectorArray = array of TDMFastVector;

implementation

constructor TDMFastVector.Create;
begin
SetLength( m_Objects, 0 );
m_Capacity := 0;
m_Size := 0;
m_ElementMemoryManagement := true;
end;

constructor TDMFastVector.Create( const capacity : Integer );
begin
if capacity >= 0 then
begin
SetLength( m_Objects, capacity );
m_Capacity := capacity;
m_Size := 0;
m_ElementMemoryManagement := true;
end;
end;

function TDMFastVector.elementMemoryManagement : Boolean;
begin
Result := m_ElementMemoryManagement;
end;

procedure TDMFastVector.elementMemoryManagement( flagValue : Boolean );
begin
m_ElementMemoryManagement := flagValue;
end;

procedure TDMFastVector.freeRange( const index1, index2 : Integer );
var
i : Integer;
begin
for i := index1 to index2 do
begin
if ( m_Objects[ i ] <> nil ) then m_Objects[ i ].Free;
end;
end;

procedure TDMFastVector.insertAtHead( element : TObject );
var
i,n1 : Integer;
begin
n1 := m_Size - 1;
for i := n1 downto 0 do
m_Objects[ i + 1 ] := m_Objects[ i ];
m_Objects[ 0 ] := element;
end;

function TDMFastVector.capacity : Integer;
begin
Result := m_Capacity;
end;

function TDMFastVector.size : Integer;
begin
Result := m_Size;
end;

function TDMFastVector.cloneObject : TObject;
var
rvector : TDMFastVector;
begin
rvector := TDMFastVector.Create;
rvector.m_Capacity := m_Capacity;
rvector.m_Objects := Copy( m_Objects );
rvector.m_Size := m_Size;
rvector.m_ElementMemoryManagement := m_ElementMemoryManagement;
Result := rvector;
end;

function TDMFastVector.copyObject : TObject;
var
i, n1 : Integer;
rvector : TDMFastVector;
cobject : TObject;
cstdobject : TDMStandardObject;
begin
rvector := TDMFastVector.Create;
rvector.m_Capacity := m_Capacity;
SetLength( rvector.m_Objects, m_Capacity );
n1 := m_Size - 1;
for i := 0 to n1 do
begin
cobject := Self.m_Objects[ i ];
if ( cobject <> nil ) then
if ( cobject is TDMStandardObject ) then
begin
cstdobject := cobject as TDMStandardObject;
rvector.m_Objects[ i ] := cstdobject.copyObject;
end;
end;
rvector.m_Size := m_Size;
rvector.m_ElementMemoryManagement := m_ElementMemoryManagement;
Result := rvector;
end;

procedure TDMFastVector.swap( const index1, index2 : Integer );
var
cobject : TObject;
begin
if ( index1 >= 0 ) and ( index1 < m_Size )
and ( index2 >= 0 ) and ( index2 < m_Size ) then
begin
cobject := m_Objects[ index1 ];
m_Objects[ index1 ] := m_Objects[ index2 ];
m_Objects[ index2 ] := cobject;
end;
end;

procedure TDMFastVector.setElementAt( const index : Integer; element : TObject );
begin
if ( index >= 0 ) and ( index < m_Size ) then
begin
if ( m_ElementMemoryManagement ) and ( m_Objects[ index ] <> nil ) then
m_Objects[ index ].Free;

m_Objects[ index ] := element;
end;
end;

procedure TDMFastVector.addElement( element : TObject );
begin
if ( m_Size = m_Capacity ) then
begin
m_Capacity := FAST_VECTOR_CAPACITY_MULTIPLIER *
( m_Capacity + FAST_VECTOR_CAPACITY_INCREMENT );

SetLength( m_Objects, m_Capacity );
end;
m_Objects[ m_Size ] := element;
m_Size := m_Size + 1;
end;

procedure TDMFastVector.insertElementAt( element : TObject; const index : Integer );
var
i, n1 : Integer;
begin
if ( m_Size = m_Capacity ) then
begin
m_Capacity := FAST_VECTOR_CAPACITY_MULTIPLIER *
( m_Capacity + FAST_VECTOR_CAPACITY_INCREMENT );
SetLength( m_Objects, m_Capacity );
end;
if ( index >= 0 ) then
begin
if ( index < m_Size ) then
begin
n1 := m_Size - 1;
for i := n1 downto index do
begin
m_Objects[ i + 1 ] := m_Objects[ i ];
end;
m_Objects[ index ] := element;
end
else m_Objects[ m_Size ] := element;
end
else insertAtHead( element );
m_Size := m_Size + 1;
end;

function TDMFastVector.indexOf( element : TObject ) : Integer;
var
i, n1 : Integer;
ielem : TObject;
celem : TDMStandardObject;
begin
Result := -1;
if ( element <> nil ) then
begin
n1 := m_Size - 1;
for i := 0 to n1 do
begin
ielem := m_Objects[ i ];
if ( ielem <> nil ) then
if ( ielem is TDMStandardObject ) then
begin
celem := ielem as TDMStandardObject;
if ( celem.equals( element ) ) then
begin
Result := i;
Break;
end;
end
else
if ( ielem = element ) then
begin
Result := i;
Break;
end;
end;
end;
end;

function TDMFastVector.firstElement : TObject;
begin
Result := m_Objects[ 0 ];
end;

function TDMFastVector.lastElement : TObject;
begin
Result := m_Objects[ m_Size - 1 ];
end;

procedure TDMFastVector.appendElements( toappend : TDMFastVector );
var
i, j, n1, s1, s11 : Integer;
begin
s1 := m_Size + toappend.m_Size;
s11 := s1 - 1;
setCapacity( s1 );
n1 := m_Size - 1;
j := 0;
for i := n1 to s11 do
begin
m_Objects[ i ] := toappend.m_Objects[ j ];
j := j + 1;
end;
m_Size := s1;
end;

procedure TDMFastVector.removeElementAt( const index : Integer );
var
i, n1 : Integer;
begin
if ( index >= 0 ) and ( index < m_Size ) and ( m_Size > 0 ) then
begin
if index = m_Size - 1 then m_Size := m_Size - 1
else
begin
n1 := m_Size - 1;
for i := index + 1 to n1 do
begin
m_Objects[ i - 1 ] := m_Objects[ i ];
end;
m_Size := m_Size - 1;
end;
end;
end;

procedure TDMFastVector.removeAndClearElementAt( const index : Integer );
var
i, n1 : Integer;
begin
if ( index >= 0 ) and ( index < m_Size ) and ( m_Size > 0 ) then
begin
if index = m_Size - 1 then m_Size := m_Size - 1
else
begin
if ( m_ElementMemoryManagement ) and ( m_Objects[ index ] <> nil ) then
m_Objects[ index ].Free;
n1 := m_Size - 1;
for i := index + 1 to n1 do
begin
m_Objects[ i - 1 ] := m_Objects[ i ];
end;
m_Size := m_Size - 1;
end;
end;
end;

procedure TDMFastVector.removeAllElements;
begin
SetLength( m_Objects, 0 );
m_Capacity := 0;
m_Size := 0;
end;

procedure TDMFastVector.removeAndClearAllElements;
begin
if ( m_ElementMemoryManagement ) then freeRange( 0, m_Size - 1 );
SetLength( m_Objects, 0 );
m_Capacity := 0;
m_Size := 0;
end;

function TDMFastVector.toArray : TDMObjectArray;
var
rarray : TDMObjectArray;
begin
rarray := Copy( m_Objects, 0, m_Size );
Result := rarray;
end;

function TDMFastVector.contains( element : TObject ) : Boolean;
var
i, n1 : Integer;
cobject : TObject;
cstdobject : TDMStandardObject;
begin
Result := false;
if ( element <> nil ) and ( m_Size > 0 ) then
begin
n1 := m_Size - 1;
for i := 0 to n1 do
begin
cobject := m_Objects[ i ];
if ( cobject is TDMStandardObject ) then
begin
cstdobject := cobject as TDMStandardObject;
if ( cstdobject.equals( element ) ) then
begin
Result := true;
Break;
end;
end;
end;
end;
end;

function TDMFastVector.elementAt( const index : Integer ) : TObject;
begin
Result := nil;
if ( index >= 0 ) and ( index < m_Size ) then Result := m_Objects[ index ];
end;

procedure TDMFastVector.trimToSize( const size : Integer );
var
n1 : Integer;
begin
n1 := m_Size - size;
if ( size > 0 ) and ( n1 > 0 ) then
begin
if ( m_ElementMemoryManagement ) then freeRange( size, n1 );
SetLength( m_Objects, size );
m_Capacity := size;
m_Size := size;
end;
end;

procedure TDMFastVector.trimToSize();
var
newObjects : TDMObjectArray;
begin
SetLength(newObjects, m_Size);

newObjects := Copy(m_Objects, 0, m_Size);
m_Objects := newObjects;
end;

procedure TDMFastVector.setCapacity( const capacity : Integer );
var
n1 : Integer;
begin
if capacity >= 0 then
begin
if ( m_ElementMemoryManagement ) then
begin
n1 := m_Size - capacity;
if ( n1 > 0 ) then
freeRange( capacity, n1 );
end;
SetLength( m_Objects, capacity );
m_Capacity := capacity;
if m_Size > m_Capacity then
m_Size := m_Capacity;
end;
end;

function TDMFastVector.equals( otherObject : TObject ) : Boolean;
var
otherFastVector : TDMFastVector;
thisElement, otherElement : TObject;
thisStdObject, otherStdObject : TDMStandardObject;
i, n1 : Integer;
objectsNotComparableNil, thisIsStandard, otherIsStandard : Boolean;
begin
Result := false;
if ( otherObject <> nil ) then
if ( otherObject is TDMFastVector ) then
begin
otherFastVector := otherObject as TDMFastVector;
if ( otherFastVector.m_Size = m_Size ) then
begin
n1 := m_Size - 1;
Result := true;
for i := 0 to n1 do
begin
thisElement := m_Objects[ i ];
otherElement := otherFastVector.m_Objects[ i ];
objectsNotComparableNil := ( thisElement = nil ) xor ( otherElement = nil );

if ( objectsNotComparableNil ) then
begin
Result := false;
Break;
end;

if ( thisElement = nil ) and ( otherElement = nil ) then Continue;

thisIsStandard := thisElement is TDMStandardObject;
otherIsStandard := otherElement is TDMStandardObject;

if ( thisIsStandard xor otherIsStandard ) then
begin
Result := false;
Break;
end;

if ( not thisIsStandard ) and ( not otherIsStandard ) then
if ( thisElement <> otherElement ) then
begin
Result := false;
Break;
end
else Continue;

thisStdObject := thisElement as TDMStandardObject;
otherStdObject := otherElement as TDMStandardObject;

if ( thisStdObject.equals( otherStdObject ) ) then Continue
else
begin
Result := false;
Break;
end;
end;
end;
end;
end;

procedure TDMFastVector.serializeObject( ostream : TStream );
begin
end;

procedure TDMFastVector.deserializeObject( istream : TStream );
begin
end;

function TDMFastVector.toString : AnsiString;
var
i, n1 : Integer;
rstring : AnsiString;
selem : TDMStandardObject;
begin
rstring := 'FastVector ( m_Size = ' + IntToStr( m_Size ) + ' m_Capacity = ';
rstring := rstring + IntToStr( capacity ) + ' )'#10#13'';
n1 := m_Size - 1;
for i := 0 to n1 do
begin
if ( m_Objects[ i ] <> nil ) then
if ( m_Objects[ i ] is TDMStandardObject ) then
begin
selem := m_Objects[ i ] as TDMStandardObject;
rstring := rstring + ' ' + selem.toString + ''#10#13'';
end;
end;
Result := rstring;
end;

destructor TDMFastVector.Destroy;
begin
if ( m_ElementMemoryManagement ) then
begin
freeRange( 0, m_Size - 1 );
end;
SetLength( m_Objects, 0 );
end;

constructor TDMFastVectorEnumeration.Create( fastVector : TDMFastVector );
begin
m_Counter := 0;
m_FastVector := fastVector;
m_SpecialElement := -1;
end;

constructor TDMFastVectorEnumeration.Create( fastVector : TDMFastVector; const specialElement : Integer );
begin
if ( specialElement = 0 ) then m_Counter := 1
else m_Counter := 0;
m_FastVector := fastVector;
m_SpecialElement := specialElement;
end;

function TDMFastVectorEnumeration.hasMoreElements : Boolean;
begin
Result := false;
if ( m_Counter < m_FastVector.size ) then Result := true;
end;

function TDMFastVectorEnumeration.nextElement : TObject;
begin
Result := m_FastVector.elementAt( m_Counter );
m_Counter := m_Counter + 1;
if ( m_Counter = m_SpecialElement ) then m_Counter := m_Counter + 1;
end;

function TDMFastVectorEnumeration.cloneObject : TObject;
var
renumeration : TDMFastVectorEnumeration;
begin
renumeration := TDMFastVectorEnumeration.Create;
renumeration.m_FastVector := m_FastVector;
renumeration.m_Counter := m_Counter;
renumeration.m_SpecialElement := m_SpecialElement;
Result := renumeration;
end;

function TDMFastVectorEnumeration.copyObject : TObject;
begin
Result := cloneObject;
end;

procedure TDMFastVectorEnumeration.serializeObject( ostream : TStream );
begin
end;

procedure TDMFastVectorEnumeration.deserializeObject( istream : TStream );
begin
end;

destructor TDMFastVectorEnumeration.Destroy;
begin
m_Counter := 0;
m_FastVector := nil;
m_SpecialElement := 0;
end;

end.
Соседние файлы в папке DMCore