Скачиваний:
31
Добавлен:
01.05.2014
Размер:
17 Кб
Скачать
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