2013-06-02 14:32:43 +02:00
/*****************************************************************************
2013-08-11 22:41:39 +02:00
* List . h *
2013-06-02 14:32:43 +02:00
* *
* XFX Generic List definition file *
* Copyright ( c ) XFX Team . All Rights Reserved *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-05-05 18:18:41 +02:00
# ifndef _SYSTEM_COLLECTIONS_GENERIC_LIST_
# define _SYSTEM_COLLECTIONS_GENERIC_LIST_
# include <System/Array.h>
# include <System/FrameworkResources.h>
# include <System/Object.h>
# include <System/String.h>
# include "Interfaces.h"
# include <stdlib.h>
# include <string.h>
# include <sassert.h>
namespace System
{
namespace Collections
{
namespace Generic
{
// Represents a strongly typed list of objects that can be accessed by index. Provides methods to search, sort, and manipulate lists.
// NOTE: types used with the List<T> class must provide at least an == operator.
template < typename T >
2014-03-29 16:17:59 +01:00
class List : public IList < T > , public IEnumerable < T > , public Object
2013-05-05 18:18:41 +02:00
{
private :
static const int defaultCapacity = 4 ;
T * _items ;
int _size ;
int _actualSize ;
int _version ;
void EnsureCapacity ( int capacity )
{
if ( _actualSize < capacity )
{
int num = ( _actualSize = = 0 ) ? defaultCapacity : _actualSize * 2 ;
if ( num > 0x7fefffff )
{
num = 0x7fefffff ;
}
if ( num < capacity )
{
num = capacity ;
}
setCapacity ( num ) ;
}
}
void swap ( T * x , T * y )
{
T temp = * x ;
* x = * y ;
* y = temp ;
}
2014-03-29 16:17:59 +01:00
class Enumerator : public IEnumerator < T >
{
private :
2014-04-20 13:19:50 +02:00
int index ;
List < T > * const parent ;
2014-03-29 16:17:59 +01:00
const int version ;
public :
2014-04-20 13:19:50 +02:00
T & Current ( ) const { return ( * parent ) [ index ] ; }
2014-03-29 16:17:59 +01:00
2014-04-20 13:19:50 +02:00
Enumerator ( List < T > * const parent )
: index ( - 1 ) , parent ( parent ) , version ( parent - > _version )
2014-03-29 16:17:59 +01:00
{
}
bool MoveNext ( )
{
sassert ( version = = parent - > _version , " " ) ;
return index + + < parent - > _size ;
}
2014-07-14 15:03:46 +02:00
2014-03-29 16:17:59 +01:00
void Reset ( )
{
sassert ( version = = parent - > _version , " " ) ;
index = - 1 ;
}
} ;
2013-05-05 18:18:41 +02:00
public :
// Gets the number of elements actually contained in the List<>.
2014-07-14 15:03:46 +02:00
inline int Count ( ) const { return _size ; }
2013-05-05 18:18:41 +02:00
// Gets the total number of elements the internal data structure can hold without resizing.
2014-07-14 15:03:46 +02:00
inline int getCapacity ( ) const { return _actualSize ; }
2013-05-05 18:18:41 +02:00
// Sets the total number of elements the internal data structure can hold without resizing.
void setCapacity ( const int value )
{
if ( value < _size )
2014-07-14 15:03:46 +02:00
{
2013-05-05 18:18:41 +02:00
return ;
2014-07-14 15:03:46 +02:00
}
2013-05-05 18:18:41 +02:00
if ( value ! = _actualSize )
{
if ( value > 0 )
{
T * destinationArray = new T [ value ] ;
2014-07-14 15:03:46 +02:00
2013-05-05 18:18:41 +02:00
if ( _size > 0 )
{
2013-07-22 01:38:59 +02:00
memcpy ( destinationArray , _items , _size * sizeof ( T ) ) ;
2013-05-05 18:18:41 +02:00
}
2014-07-14 15:03:46 +02:00
2013-05-05 18:18:41 +02:00
delete [ ] _items ;
_items = destinationArray ;
}
else
{
delete [ ] _items ;
_items = new T [ 0 ] ;
}
2014-07-14 15:03:46 +02:00
2013-05-05 18:18:41 +02:00
_actualSize = value ;
}
}
2014-07-14 15:03:46 +02:00
inline bool IsReadOnly ( ) const { return false ; }
2013-05-05 18:18:41 +02:00
// Initializes a new instance of the List<> class that is empty and has the default initial capacity.
2013-08-11 22:41:39 +02:00
List ( )
2013-05-05 18:18:41 +02:00
: _size ( 0 ) , _actualSize ( defaultCapacity ) , _version ( 0 )
{
_items = new T [ _actualSize ] ;
}
// Initializes a new instance of the List<> class that is empty and has the specified initial capacity.
List ( const int capacity )
: _size ( 0 ) , _actualSize ( ( capacity < 0 ) ? defaultCapacity : capacity ) , _version ( 0 )
{
_items = new T [ _actualSize ] ;
}
// Copy constructor
List ( const List < T > & obj )
: _size ( obj . _size ) , _actualSize ( obj . _actualSize ) , _version ( obj . _version )
{
_items = new T [ obj . _actualSize ] ;
2013-07-22 01:38:59 +02:00
memcpy ( _items , obj . _items , obj . _size * sizeof ( T ) ) ;
2013-05-05 18:18:41 +02:00
}
~ List ( )
{
delete [ ] _items ;
}
2013-07-22 01:38:59 +02:00
/**
* Adds an element to the end of the list
*/
2013-08-11 22:41:39 +02:00
void Add ( const T & item )
2013-05-05 18:18:41 +02:00
{
if ( _size = = _actualSize )
{
EnsureCapacity ( _size + 1 ) ;
}
2014-07-14 15:03:46 +02:00
_items [ _size + + ] = item ;
2013-05-05 18:18:41 +02:00
_version + + ;
}
2014-03-29 16:17:59 +01:00
void AddRange ( IEnumerable < T > const * const collection )
{
sassert ( collection ! = NULL , " " ) ;
IEnumerator < T > * enumerator = collection - > GetEnumerator ( ) ;
while ( enumerator - > MoveNext ( ) )
{
2014-04-20 13:19:50 +02:00
Add ( enumerator - > Current ( ) ) ;
2014-03-29 16:17:59 +01:00
}
}
2013-07-22 01:38:59 +02:00
/**
* Removes all elements from the list
*/
2013-08-11 22:41:39 +02:00
void Clear ( )
2013-05-05 18:18:41 +02:00
{
if ( _size > 0 )
{
delete [ ] _items ;
_items = new T [ _actualSize ] ;
_size = 0 ;
}
2014-07-14 15:03:46 +02:00
2013-05-05 18:18:41 +02:00
_version + + ;
}
// Determines whether an element is in the List<>.
bool Contains ( const T & item ) const
{
for ( int i = 0 ; i < _size ; i + + )
{
if ( _items [ i ] = = item )
{
return true ;
}
}
2014-07-14 15:03:46 +02:00
2013-05-05 18:18:41 +02:00
return false ;
}
// Copies the entire List<> to a compatible one-dimensional array, starting at the specified index of the target array.
void CopyTo ( T array [ ] , const int arrayIndex ) const
{
sassert ( array ! = null , String : : Format ( " array; %s " , FrameworkResources : : ArgumentNull_Generic ) ) ;
2013-08-13 20:04:25 +02:00
memcpy ( & array [ arrayIndex ] , _items , _size * sizeof ( T ) ) ;
2013-05-05 18:18:41 +02:00
}
2014-03-29 16:17:59 +01:00
Enumerator * GetEnumerator ( )
{
return new Enumerator ( this ) ;
}
2013-07-22 01:38:59 +02:00
static const Type & GetType ( )
2013-05-05 18:18:41 +02:00
{
2013-07-22 01:38:59 +02:00
static Type ListTypeInfo ( " List " , " System::Collections::Generic::List " , TypeCode : : Object , true ) ;
2014-07-14 15:03:46 +02:00
2013-07-22 01:38:59 +02:00
return ListTypeInfo ;
2013-05-05 18:18:41 +02:00
}
// Searches for the specified object and returns the zero-based index of the first occurrence within the entire List<>.
int IndexOf ( const T & item ) const
{
for ( int i = 0 ; i < _size ; i + + )
{
if ( _items [ i ] = = item )
2014-07-14 15:03:46 +02:00
{
2013-05-05 18:18:41 +02:00
return i ;
2014-07-14 15:03:46 +02:00
}
2013-05-05 18:18:41 +02:00
}
2014-07-14 15:03:46 +02:00
2013-05-05 18:18:41 +02:00
return - 1 ;
}
2014-07-14 15:03:46 +02:00
2013-05-05 18:18:41 +02:00
// Inserts an element into the List<> at the specified index.
void Insert ( const int index , const T & item )
{
2013-07-22 01:38:59 +02:00
sassert ( index > = 0 & & index < _size , " Index must be within the bounds of the List. " ) ;
2013-05-05 18:18:41 +02:00
if ( _size = = _actualSize )
{
EnsureCapacity ( _size + 1 ) ;
}
2014-07-14 15:03:46 +02:00
2013-05-05 18:18:41 +02:00
if ( index < _size )
{
2013-07-22 01:38:59 +02:00
memcpy ( & _items [ index + 1 ] , & _items [ index ] , ( _size - index ) * sizeof ( T ) ) ;
2013-05-05 18:18:41 +02:00
}
2014-07-14 15:03:46 +02:00
2013-05-05 18:18:41 +02:00
_items [ index ] = T ( item ) ;
_size + + ;
_version + + ;
}
// Removes the first occurrence of a specific object from the List<>.
bool Remove ( const T & item )
{
int index = IndexOf ( item ) ;
2014-07-14 15:03:46 +02:00
2013-05-05 18:18:41 +02:00
if ( index > = 0 )
{
RemoveAt ( index ) ;
return true ;
}
2014-07-14 15:03:46 +02:00
2013-05-05 18:18:41 +02:00
return false ;
}
// Removes the element at the specified index of the List<>.
void RemoveAt ( const int index )
{
2013-10-04 22:15:52 +02:00
memcpy ( & _items [ index ] , & _items [ index + 1 ] , ( _size - index ) * sizeof ( T ) ) ;
2013-05-05 18:18:41 +02:00
_size - - ;
_version + + ;
}
// Removes a range of elements from the List<>.
void RemoveRange ( const int index , const int count )
{
sassert ( index > = 0 , String : : Format ( " index; %s " , FrameworkResources : : ArgumentOutOfRange_NeedNonNegNum ) ) ;
sassert ( count > = 0 , String : : Format ( " count; %s " , FrameworkResources : : ArgumentOutOfRange_NeedNonNegNum ) ) ;
sassert ( ! ( ( _size - index ) < count ) , " Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection. " ) ;
if ( count > 0 )
{
_size - = count ;
if ( index < _size )
{
2013-07-22 01:38:59 +02:00
memcpy ( & _items [ index ] , & _items [ index + count ] , ( _size - index ) * sizeof ( T ) ) ;
2013-05-05 18:18:41 +02:00
}
2013-07-22 01:38:59 +02:00
memset ( & _items [ _size ] , 0 , count * sizeof ( T ) ) ;
2013-05-05 18:18:41 +02:00
_version + + ;
}
}
2014-07-14 15:03:46 +02:00
inline void Reverse ( ) { Reverse ( 0 , _size ) ; }
2013-05-05 18:18:41 +02:00
void Reverse ( const int index , const int count )
{
sassert ( index > = 0 , String : : Format ( " index; %s " , FrameworkResources : : ArgumentOutOfRange_NeedNonNegNum ) ) ;
sassert ( count > = 0 , String : : Format ( " count; %s " , FrameworkResources : : ArgumentOutOfRange_NeedNonNegNum ) ) ;
sassert ( ! ( ( _size - index ) < count ) , " Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection. " ) ;
int num = index ;
2013-08-11 22:41:39 +02:00
int num2 = ( index + count ) - 1 ;
2013-05-05 18:18:41 +02:00
while ( num < num2 )
{
T obj2 = _items [ num ] ;
_items [ num ] = _items [ num2 ] ;
_items [ num2 ] = obj2 ;
num + + ;
2013-08-11 22:41:39 +02:00
num2 - - ;
2013-05-05 18:18:41 +02:00
}
_version + + ;
}
2014-07-14 15:03:46 +02:00
void Sort ( int index , int count , IComparer < T > * const comparer )
2013-05-05 18:18:41 +02:00
{
sassert ( comparer ! = null , String : : Format ( " comparer; %s " , FrameworkResources : : ArgumentNull_Generic ) ) ;
sassert ( index > = 0 , String : : Format ( " index; %s " , FrameworkResources : : ArgumentOutOfRange_NeedNonNegNum ) ) ;
sassert ( index + count < _actualSize , " " ) ;
int k = ( index + count ) / 2 ;
swap ( & _items [ index ] , & _items [ k ] ) ;
T key = _items [ index ] ;
int i = index + 1 ;
int j = count ;
2014-07-14 15:03:46 +02:00
2013-05-05 18:18:41 +02:00
while ( i < = j )
{
while ( ( i < = count ) & & ( comparer - > Compare ( _items [ i ] , key ) < = 0 ) )
i + + ;
while ( ( j > = index ) & & ( comparer - > Compare ( _items [ j ] , key ) > 0 ) )
j - - ;
if ( i < j )
swap ( & _items [ i ] , & _items [ j ] ) ;
}
2014-07-14 15:03:46 +02:00
2013-05-05 18:18:41 +02:00
// swap two elements
swap ( & _items [ index ] , & _items [ j ] ) ;
// recursively sort the lesser list
Sort ( index , j - 1 , comparer ) ;
Sort ( j + 1 , count , comparer ) ;
}
2014-07-14 15:03:46 +02:00
void Sort ( IComparer < T > * const comparer )
2013-05-05 18:18:41 +02:00
{
sassert ( comparer ! = null , String : : Format ( " comparer; %s " , FrameworkResources : : ArgumentNull_Generic ) ) ;
2013-08-13 20:04:25 +02:00
Sort ( 0 , _size , comparer ) ;
2013-05-05 18:18:41 +02:00
}
T * ToArray ( ) const
{
T * destinationArray = new T [ _size ] ;
2013-07-22 01:38:59 +02:00
memcpy ( destinationArray , _items , _size * sizeof ( T ) ) ;
2013-05-05 18:18:41 +02:00
return destinationArray ;
}
2013-07-11 20:00:07 +02:00
const String ToString ( ) const
2013-05-05 18:18:41 +02:00
{
return " List<T> " ;
}
void TrimExcess ( )
{
int num = ( int ) ( _actualSize * 0.9 ) ;
2014-07-14 15:03:46 +02:00
2013-05-05 18:18:41 +02:00
if ( _size < num )
{
setCapacity ( _size ) ;
}
}
T & operator [ ] ( const int index )
{
2014-07-14 15:03:46 +02:00
sassert ( index > 0 , FrameworkResources : : ArgumentOutOfRange_NeedNonNegNum ) ;
sassert ( index < Count ( ) , " " ) ;
return _items [ index ] ;
}
const T & operator [ ] ( const int index ) const
{
sassert ( index > 0 , FrameworkResources : : ArgumentOutOfRange_NeedNonNegNum ) ;
sassert ( index < Count ( ) , " " ) ;
2013-05-05 18:18:41 +02:00
return _items [ index ] ;
}
const List < T > & operator = ( const List < T > & other )
{
2013-08-13 20:04:25 +02:00
if ( other = = * this )
{
return * this ;
}
2013-05-05 18:18:41 +02:00
delete [ ] _items ;
_actualSize = other . _actualSize ;
_size = other . _size ;
_items = new T [ other . _actualSize ] ;
2013-07-22 01:38:59 +02:00
memcpy ( _items , other . _items , other . _size * sizeof ( T ) ) ;
2013-05-05 18:18:41 +02:00
_version = other . _version ;
return * this ;
}
} ;
}
}
}
# endif //_SYSTEM_COLLECTIONS_GENERIC_LIST_