• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

spl/collection/Array.h

00001 /*
00002  *   This file is part of the Standard Portable Library (SPL).
00003  *
00004  *   SPL is free software: you can redistribute it and/or modify
00005  *   it under the terms of the GNU General Public License as published by
00006  *   the Free Software Foundation, either version 3 of the License, or
00007  *   (at your option) any later version.
00008  *
00009  *   SPL is distributed in the hope that it will be useful,
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *   GNU General Public License for more details.
00013  *
00014  *   You should have received a copy of the GNU General Public License
00015  *   along with SPL.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 #ifndef _array_h
00018 #define _array_h
00019 
00020 #include <spl/types.h>
00021 #include <spl/Debug.h>
00022 
00023 #ifdef _WINDOWS
00024 #include <spl/configwin32.h>
00025 #else
00026 #include <spl/autoconf/config.h>
00027 #endif
00028 
00029 #include <spl/Exception.h>
00030 #include <spl/collection/IEnumerable.h>
00031 #include <spl/IIterator.h>
00032 #include <spl/Memory.h>
00033 #include <spl/RefCountPtr.h>
00034 
00043 template<typename T>
00044 class Array : public IEnumerable<T>
00045 {
00046 private:
00047         T *m_data;
00048         int m_len;
00049 
00050 public:
00051         class Iterator : public IIterator<T>
00052         {
00053         private:
00054                 const Array<T> *m_ap;
00055                 int m_pos;
00056 
00057         public:
00058                 Iterator()
00059                 : m_ap(NULL), m_pos(-1)
00060                 {
00061                 }
00062 
00063                 Iterator(const Array<T> *ap)
00064                 : m_ap(ap), m_pos(-1)
00065                 {
00066                 }
00067 
00068                 Iterator(const Iterator& ai)
00069                 : m_ap(ai.m_ap), m_pos(ai.m_pos)
00070                 {
00071                 }
00072 
00073                 virtual bool Next()
00074                 {
00075                         if (NULL == m_ap || ++m_pos >= m_ap->Count())
00076                         {
00077                                 return false;
00078                         }
00079                         return true;
00080                 }
00081 
00082                 virtual bool Prev()
00083                 {
00084                         if (--m_pos < 0)
00085                         {
00086                                 return false;
00087                         }
00088                         return true;
00089                 }
00090 
00091                 virtual T Current()
00092                 {
00093                         return m_ap->ElementAt(m_pos);
00094                 }
00095 
00096                 virtual T& CurrentRef()
00097                 {
00098                         return m_ap->ElementAtRef(m_pos);
00099                 }
00100         };
00101 
00102 protected:
00103         virtual RefCountPtr<IIterator<T> > IteratorPtr()
00104         {
00105                 return RefCountPtr<IIterator<T> >(new Iterator(this));
00106         }
00107 
00108 public:
00112         Array(int count) 
00113         : m_len(count)
00114         {
00115                 ASSERT(m_len > -1);
00116                 if (0 == m_len)
00117                 {
00118                         m_data = NULL;
00119                         return;
00120                 }
00121                 m_data = new T[m_len];
00122 
00123                 for ( int x = 0; x < m_len; x++ )
00124                 {
00125                         m_data[x] = T();
00126                 }
00127         }
00128 
00129         Array()
00130         : m_len(0), m_data(NULL)
00131         {
00132         }
00133 
00134         Array(const Array& v) 
00135         : m_len(v.m_len)
00136         {
00137                 ASSERT(m_len > -1);
00138                 if (0 == m_len)
00139                 {
00140                         m_data = NULL;
00141                         return;
00142                 }
00143 
00144                 m_data = new T[m_len];
00145 
00146                 for ( int x = 0; x < m_len; x++ )
00147                 {
00148                         m_data[x] = v.m_data[x];
00149                 }
00150         }
00151 
00152         Array(const T* v, int len)
00153         : m_len(len)
00154         {
00155                 if (0 == m_len)
00156                 {
00157                         m_data = NULL;
00158                         return;
00159                 }
00160 
00161                 m_data = new T[m_len];
00162 
00163                 for ( int x = 0; x < m_len; x++ )
00164                 {
00165                         m_data[x] = v[x];
00166                 }
00167         }
00168 
00169         virtual ~Array()
00170         {
00171                 if (NULL != m_data)
00172                 {
00173                         ASSERT_MEM( m_data, sizeof(T) * m_len );
00174                         delete[] m_data;
00175                 }
00176         }
00177 
00178         Array& operator =(const Array& v)
00179         {
00180                 Array<T>::ValidateMem();
00181 
00182                 if (m_len > 0)
00183                 {
00184                         delete[] m_data;
00185                 }
00186                 else
00187                 {
00188                         ASSERT(NULL == m_data);
00189                 }
00190 
00191                 if (0 == (m_len = v.m_len))
00192                 {
00193                         m_data = NULL;
00194                 }
00195                 else
00196                 {
00197                         m_data = new T[m_len];
00198                 }
00199 
00200                 for ( int x = 0; x < m_len; x++ )
00201                 {
00202                         m_data[x] = v.m_data[x];
00203                 }
00204 
00205                 return *this;
00206         }
00207 
00208         inline Iterator Begin() const
00209         {
00210                 return Iterator(this);
00211         }
00212 
00218         inline T ElementAt( const int pos ) const
00219         {
00220                 if (pos >= m_len || 0 > pos)
00221                 {
00222                         throw new IndexOutOfBoundsException();
00223                 }
00224                 ASSERT_MEM( m_data, sizeof(T) * m_len);
00225 
00226                 return m_data[pos];
00227         }
00228 
00234         inline T& ElementAtRef( const int pos ) const
00235         {
00236                 ASSERT_MEM( m_data, sizeof(T) * m_len );
00237                 if ( pos >= m_len || 0 > pos )
00238                 {
00239                         throw IndexOutOfBoundsException();
00240                 }
00241                 return m_data[pos];
00242         }
00243 
00244         inline void SetElementAt( const int pos, T val )
00245         {
00246                 if ( pos >= m_len || 0 > pos )
00247                 {
00248                         throw IndexOutOfBoundsException();
00249                 }
00250                 m_data[pos] = val;
00251         }
00252 
00253         inline T& operator[] (const int idx)
00254         {
00255                 return ElementAtRef(idx);
00256         }
00257 
00258         inline const T& operator[] (const int idx) const
00259         {
00260                 return ElementAtRef(idx);
00261         }
00262 
00263         inline operator T*() const
00264         {
00265                 return m_data;
00266         }
00267 
00268         inline T* Data() const
00269         {
00270                 return m_data;
00271         }
00272 
00277         inline void Clear()
00278         {
00279                 Clear(0, Length());
00280         }
00281 
00282         void Clear(int start, int len)
00283         {
00284                 ASSERT(len - start <= m_len);
00285                 for ( int x = start; x < m_len && x < len; x++ )
00286                 {
00287                         m_data[x + start] = T();
00288                 }
00289         }
00290 
00291         inline void ClearBinary()
00292         {
00293                 ClearBinary(0, Length());
00294         }
00295 
00296         void ClearBinary(int start, int len)
00297         {
00298                 ASSERT(len - start <= m_len);
00299                 memset(m_data, 0, sizeof(T) * (len - start));
00300                 for ( int x = start; x < m_len && x < len; x++ )
00301                 {
00302                         m_data[x + start] = T();
00303                 }
00304         }
00305 
00309         inline int Count() const
00310         {
00311                 return m_len;
00312         }
00313 
00314         inline int Length() const
00315         {
00316                 return m_len;
00317         }
00318 
00319         bool Equals(const Array<T>& a) const
00320         {
00321                 if (m_len != a.m_len)
00322                 {
00323                         return false;
00324                 }
00325                 for (int x = 0; x < m_len; x++)
00326                 {
00327                         if (m_data[x] != a.m_data[x])
00328                         {
00329                                 return false;
00330                         }
00331                 }
00332                 return true;
00333         }
00334 
00335         bool AreElementsEqualTo(const T& val) const
00336         {
00337                 for (int x = 0; x < m_len; x++)
00338                 {
00339                         if (m_data[x] != val)
00340                         {
00341                                 return false;
00342                         }
00343                 }
00344                 return true;
00345         }
00346 
00347         inline RefCountPtr<Array<T> > Clone() const
00348         {
00349                 return RefCountPtr<Array<T> >(new Array<T>(*this));
00350         }
00351 
00352         void CopyTo(Array<T>& to, int sourceStart) const
00353         {
00354                 if (sourceStart >= m_len)
00355                 {
00356                         return;
00357                 }
00358                 int pos = 0;
00359                 for (int x = sourceStart; x < m_len && pos < to.m_len; x++)
00360                 {
00361                         to.m_data[pos++] = m_data[x];
00362                 }
00363         }
00364 
00365         inline void CopyTo(Array<T>& to) const
00366         {
00367                 CopyTo(to, 0);
00368         }
00369 
00370         void CopyToBinary(Array<T>& to, int sourceStart) const
00371         {
00372                 if (sourceStart >= m_len)
00373                 {
00374                         return;
00375                 }
00376                 int len = m_len - sourceStart;
00377                 if (len >= to.Length())
00378                 {
00379                         len = to.Length();
00380                 }
00381                 memcpy(to.m_data, &m_data[sourceStart], sizeof(T) * len);
00382         }
00383 
00384         inline void CopyToBinary(Array<T>& to) const
00385         {
00386                 CopyToBinary(to, 0);
00387         }
00388 
00389         inline static bool Equals(const Array<T>& a, const Array<T>& b)
00390         {
00391                 return Equals(a, 0, b, 0, a.Length());
00392         }
00393 
00394         static bool Equals(const Array<T>& a, int astart, const Array<T>& b, int bstart, int len)
00395         {
00396                 int diff = (a.Length() - astart) - (b.Length() - bstart);
00397                 if (0 != diff)
00398                 {                       
00399                         return false;
00400                 }
00401 
00402                 int length = a.Length() - astart;
00403                 if (length < len)
00404                 {
00405                         return false;
00406                 }
00407                 for ( int x = 0; x < length; x++)
00408                 {
00409                         if (!(a[x + astart] == b[x + bstart]))
00410                         {
00411                                 return false;
00412                         }
00413                 }
00414                 return true;
00415         }
00416 
00417         static void Copy(const Array<T>& from, int fromStart, Array<T>& to, int toStart, int length)
00418         {
00419                 for ( int x = 0; x < length; x++)
00420                 {
00421                         to[toStart + x] = from[fromStart + x];
00422                 }
00423         }
00424 
00425         inline static void CopyBinary(const Array<T>& from, int fromStart, Array<T>& to, int toStart, int length)
00426         {
00427                 memmove(&to.m_data[toStart], &from.m_data[fromStart], sizeof(T) * length);
00428         }
00429 
00430 #if defined(DEBUG) || defined(_DEBUG)
00431         void CheckMem() const
00432         {
00433                 if (NULL != m_data)
00434                 {
00435                         DEBUG_NOTE_MEM_ALLOCATION( m_data );
00436                         for ( int x = 0; x < m_len; x++ )
00437                         {
00438                                 ValidateType( m_data[x] );
00439                         }
00440                 }
00441         }
00442 
00443         void ValidateMem() const
00444         {
00445                 if (NULL != m_data)
00446                 {
00447                         ASSERT_MEM(m_data, sizeof(T) * m_len);
00448                         for ( int x = 0; x < m_len; x++ )
00449                         {
00450                                 ValidateType( m_data[x] );
00451                         }
00452                 }
00453         }
00454 #endif
00455 };
00456 
00457 REGISTER_TYPEOF( 151, Array<char> );
00458 REGISTER_TYPEOF( 152, Array<byte> );
00459 REGISTER_TYPEOF( 156, Array<int16> );
00460 REGISTER_TYPEOF( 157, Array<uint16> );
00461 REGISTER_TYPEOF( 160, Array<int32> );
00462 REGISTER_TYPEOF( 161, Array<uint32> );
00463 REGISTER_TYPEOF( 162, Array<int64> );
00464 REGISTER_TYPEOF( 163, Array<uint64> );
00465 REGISTER_TYPEOF( 164, Array<float32> );
00466 REGISTER_TYPEOF( 165, Array<float64> );
00467 
00470 #endif