00001
00002
00003
00004
00005
00008
00009 #ifndef _ROKU_INCLUDE_CASCADE_UTIL_CASCADENEWARRAY_H
00010 #define _ROKU_INCLUDE_CASCADE_UTIL_CASCADENEWARRAY_H
00011
00012 #include <cascade/CascadeObject.h>
00013
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #undef CASSERT
00037 #define CASSERT(x) do {} while (false)
00038
00039 #if defined(new)
00040 #error "new cannot be #defined when including this file"
00041 #endif
00042
00044
00045 namespace CascadePrivate { class ArrayPlacementHelper { }; }
00046 inline void * operator new(MemoryWord nSize, void * pMem, CascadePrivate::ArrayPlacementHelper *)
00047 {
00048 return pMem;
00049 }
00050
00052
00053 namespace CascadePrivate { void CascadeNewArray_QuickSortHelper(void * base, u32 num, int width, void * pFunc); }
00054
00056
00057 template <class TYPE>
00058 class CascadeNewArray : public CascadeObject
00059 {
00060 public:
00061 CascadeNewArray(u32 nInitialMemSize = kDefaultInitialMemSize);
00062 CascadeNewArray(const CascadeNewArray & that);
00063 virtual ~CascadeNewArray();
00064 public:
00065 CascadeNewArray & operator = (const CascadeNewArray & that);
00066 public:
00067 void SetAt(u32 nIndex, const TYPE & data);
00068 TYPE & GetAt(u32 nIndex) const;
00069 TYPE & operator[](u32 nIndex) const;
00070 void InsertAt(u32 nIndex, const TYPE & data);
00071 void RemoveAt(u32 nIndex);
00072 void Append(const TYPE & pData);
00073 u32 GetSize() const;
00074 void SetSize(u32 nSize);
00075 bool IsEmpty() const;
00076
00077 typedef int (CompareFunction)(const TYPE * pElement1, const TYPE * pElement2);
00078
00079
00080 void QuickSort(CompareFunction * pCompareFunction);
00081
00082
00083
00084
00085
00086
00087
00088 protected:
00089 enum { kDefaultInitialMemSize = 8 };
00090
00091 protected:
00092 TYPE * m_pData;
00093 u32 m_nSize;
00094 u32 m_nMemSize;
00095
00096 protected:
00097 inline static void PlacementNewConstruct(TYPE * pObjects, u32 nNumObjects)
00098 {
00099 u8 * pBytes = (u8 *)pObjects;
00100 u32 nBytes = nNumObjects * sizeof(TYPE);
00101 while (nBytes--) *pBytes++ = 0;
00102 for (; nNumObjects--; pObjects++) ::new((void *)pObjects, (CascadePrivate::ArrayPlacementHelper *)NULL) TYPE;
00103 }
00104 inline static void ManualDestruct(TYPE * pObjects, u32 nNumObjects)
00105 {
00106 for (; nNumObjects--; pObjects++) pObjects->~TYPE();
00107 }
00108 inline static void arraymemmove(void * pDest, const void * pSource, u32 nCount)
00109 {
00110 if ((u32)pDest > (u32)pSource)
00111 {
00112
00113 u8 * pDEST = (u8 *)pDest + nCount - 1;
00114 u8 * pSOURCE = (u8 *)pSource + nCount - 1;
00115 for (; nCount--;) *pDEST-- = *pSOURCE--;
00116 }
00117 else
00118 {
00119
00120 u8 * pDEST = (u8 *)pDest;
00121 u8 * pSOURCE = (u8 *)pSource;
00122 for (; nCount--;) *pDEST++ = *pSOURCE++;
00123 }
00124 }
00125 inline static void arraymemcpy(void * pDest, const void * pSource, u32 nCount)
00126 {
00127 u8 * pDEST = (u8 *)pDest;
00128 u8 * pSOURCE = (u8 *)pSource;
00129 for (; nCount--;) *pDEST++ = *pSOURCE++;
00130 }
00131 };
00132
00134
00135 template <class TYPE>
00136 CascadeNewArray<TYPE>::CascadeNewArray(u32 nInitialMemSize)
00137 {
00138 m_nSize = m_nMemSize = 0;
00139 m_pData = NULL;
00140 SetSize(nInitialMemSize);
00141 SetSize(0);
00142 }
00143
00144 template <class TYPE>
00145 CascadeNewArray<TYPE>::CascadeNewArray(const CascadeNewArray<TYPE> & that)
00146 {
00147 m_nSize = m_nMemSize = 0;
00148 m_pData = NULL;
00149
00150 u32 nThatSize = that.GetSize();
00151 if (0 == nThatSize)
00152 {
00153 SetSize(that.m_nMemSize);
00154 SetSize(0);
00155 }
00156 else
00157 {
00158 SetSize(nThatSize);
00159 for (u32 i = 0; i < nThatSize; i++) m_pData[i] = that.m_pData[i];
00160 }
00161 }
00162
00163 template <class TYPE>
00164 CascadeNewArray<TYPE>::~CascadeNewArray()
00165 {
00166 if (m_pData)
00167 {
00168 ManualDestruct(m_pData, m_nMemSize);
00169 delete [] (u8 *)m_pData;
00170 }
00171 }
00172
00173 template <class TYPE>
00174 CascadeNewArray<TYPE> &
00175 CascadeNewArray<TYPE>::operator = (const CascadeNewArray<TYPE> & that)
00176 {
00177 SetSize(that.m_nSize);
00178 for (u32 i = 0; i < that.m_nSize; i++) m_pData[i] = that.m_pData[i];
00179 return *this;
00180 }
00181
00182 template <class TYPE>
00183 inline void
00184 CascadeNewArray<TYPE>::SetAt(u32 nIndex, const TYPE & data)
00185 {
00186 CASSERT(nIndex < m_nSize);
00187 m_pData[nIndex] = data;
00188 }
00189
00190 template <class TYPE>
00191 inline TYPE &
00192 CascadeNewArray<TYPE>::GetAt(u32 nIndex) const
00193 {
00194 CASSERT(nIndex < m_nSize);
00195 return m_pData[nIndex];
00196 }
00197
00198 template <class TYPE>
00199 void
00200 CascadeNewArray<TYPE>::InsertAt(u32 nIndex, const TYPE & data)
00201 {
00202 if (nIndex >= m_nSize)
00203 {
00204
00205 SetSize(nIndex + 1);
00206 }
00207 else
00208 {
00209
00210 SetSize(m_nSize + 1);
00211
00212 ManualDestruct(&m_pData[m_nSize-1], 1);
00213
00214
00215 arraymemmove(&m_pData[nIndex+1], &m_pData[nIndex], ((m_nSize-1) - nIndex) * sizeof(TYPE));
00216
00217 PlacementNewConstruct(&m_pData[nIndex], 1);
00218 }
00219
00220 CASSERT(nIndex < m_nSize);
00221 m_pData[nIndex] = data;
00222 }
00223
00224 template <class TYPE>
00225 void
00226 CascadeNewArray<TYPE>::RemoveAt(u32 nIndex)
00227 {
00228 CASSERT(nIndex < m_nSize);
00229
00230
00231 ManualDestruct(&m_pData[nIndex], 1);
00232
00233
00234
00235 if (nIndex < (m_nSize - 1)) arraymemmove(&m_pData[nIndex], &m_pData[nIndex + 1], (m_nSize - (nIndex + 1)) * sizeof(TYPE));
00236
00237 PlacementNewConstruct(&m_pData[m_nSize - 1], 1);
00238
00239
00240 m_nSize--;
00241 }
00242
00243 template <class TYPE>
00244 inline void
00245 CascadeNewArray<TYPE>::Append(const TYPE & data)
00246 {
00247 InsertAt(m_nSize, data);
00248 }
00249
00250 template <class TYPE>
00251 inline u32
00252 CascadeNewArray<TYPE>::GetSize() const
00253 {
00254 return m_nSize;
00255 }
00256
00257 template <class TYPE>
00258 void
00259 CascadeNewArray<TYPE>::SetSize(u32 nSize)
00260 {
00261 if (nSize > m_nMemSize)
00262 {
00263 u32 nNewMemSize;
00264 if (m_nMemSize)
00265 {
00266 u32 nDouble = 2 * m_nMemSize;
00267 nNewMemSize = nDouble * ((nSize / nDouble) + 1);
00268 }
00269 else nNewMemSize = nSize;
00270
00271
00272 u32 nBytesToAlloc = sizeof(TYPE) * nNewMemSize;
00273 TYPE * pNewData = (TYPE *) new u8[nBytesToAlloc];
00274
00275
00276
00277 if (m_nMemSize) arraymemcpy(pNewData, m_pData, m_nMemSize * sizeof(TYPE));
00278
00279
00280 PlacementNewConstruct(&pNewData[m_nSize], nNewMemSize - m_nSize);
00281
00282
00283 if (m_pData) delete [] (u8 *)m_pData;
00284 m_pData = pNewData;
00285 m_nMemSize = nNewMemSize;
00286 }
00287
00288 m_nSize = nSize;
00289 }
00290
00291 template <class TYPE>
00292 inline bool
00293 CascadeNewArray<TYPE>::IsEmpty() const
00294 {
00295 return (m_nSize == 0);
00296 }
00297
00298 template <class TYPE>
00299 inline TYPE &
00300 CascadeNewArray<TYPE>::operator[](u32 nIndex) const
00301 {
00302 CASSERT(nIndex < m_nSize);
00303 return m_pData[nIndex];
00304 }
00305
00306 template <class TYPE>
00307 void
00308 CascadeNewArray<TYPE>::QuickSort(CompareFunction * pCompareFunction)
00309 {
00310 CascadePrivate::CascadeNewArray_QuickSortHelper((void *)m_pData, m_nSize, sizeof(TYPE), (void *)pCompareFunction);
00311 }
00312
00313 #endif // #ifndef _ROKU_INCLUDE_CASCADE_UTIL_CASCADENEWARRAY_H
00314
00316
00318
00319
00320
00321
00322
00323
00324
00325