00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef UTVECTOR_H
00023 #define UTVECTOR_H
00024
00025
00026
00027
00028
00029 #ifndef UT_TYPES_H
00030 #include "ut_types.h"
00031 #endif
00032 #include "ut_assert.h"
00033 #include "ut_debugmsg.h"
00034
00035
00036 #define UT_VECTOR_CLEANUP(d, v, r) \
00037 do { int utv_max = v.getItemCount(); \
00038 for (int utv=utv_max-1; utv>=0; utv--) \
00039 { \
00040 d utv_p = (d) v.getNthItem(utv); \
00041 UT_ASSERT_HARMLESS(utv_p); \
00042 if (utv_p) \
00043 r (utv_p); \
00044 } \
00045 } while (0)
00046
00047 #define UT_VECTOR_SPARSECLEANUP(d, v, r) \
00048 do { int utv_max = v.getItemCount(); \
00049 for (int utv=utv_max-1; utv>=0; utv--) \
00050 { \
00051 d utv_p = (d) v.getNthItem(utv); \
00052 if (utv_p) \
00053 r (utv_p); \
00054 } \
00055 } while (0)
00056
00057 #define UT_VECTOR_PURGEALL(d, v) UT_VECTOR_CLEANUP(d, v, delete)
00058 #define UT_VECTOR_FREEALL(d, v) UT_VECTOR_CLEANUP(d, v, g_free)
00059 #define UT_VECTOR_SPARSEPURGEALL(d, v) UT_VECTOR_SPARSECLEANUP(d, v, delete)
00060 #define UT_VECTOR_SPARSEFREEALL(d, v) UT_VECTOR_SPARSECLEANUP(d, v, g_free)
00061
00062
00063
00064 #define UT_VECTOR_RELEASE(v) \
00065 { \
00066 int utv_max = v.getItemCount(); \
00067 for (int utv=utv_max-1; utv>=0; utv--) \
00068 { \
00069 id utv_p = (id) v.getNthItem(utv); \
00070 [utv_p release]; \
00071 } \
00072 }
00073
00074
00075 template <class T> class UT_GenericVector
00076 {
00077 public:
00078 typedef int (*compar_fn_t) (const void *, const void *);
00079
00080
00081
00082
00083
00084 UT_GenericVector(UT_sint32 sizehint = 32, UT_sint32 baseincr = 4, bool bPrealloc = false);
00085 UT_GenericVector(const UT_GenericVector<T>&);
00086 UT_GenericVector<T>& operator=(const UT_GenericVector<T>&);
00087 virtual ~UT_GenericVector();
00088
00089 UT_sint32 addItem(const T);
00090 inline UT_sint32 push_back(const T item) { return addItem(item); }
00091 bool pop_back();
00092 inline const T back() const { return getLastItem(); }
00093
00094 UT_sint32 addItem(const T p, UT_sint32 * pIndex);
00095
00096
00097
00098
00099 inline T getNthItem(UT_sint32 n) const
00100 {
00101 UT_ASSERT_HARMLESS(m_pEntries);
00102 UT_ASSERT_HARMLESS(m_iCount > 0);
00103 UT_ASSERT_HARMLESS(n<m_iCount);
00104
00105 if(n >= m_iCount || !m_pEntries) {
00106 return 0;
00107 }
00108 return m_pEntries[n];
00109 }
00110
00111 const T operator[](UT_sint32 i) const;
00112 UT_sint32 setNthItem(UT_sint32 ndx, T pNew, T * ppOld);
00113 const T getFirstItem() const;
00114 const T getLastItem() const;
00115 inline UT_sint32 getItemCount() const { return m_iCount; }
00116 UT_sint32 findItem(T) const;
00117
00118 UT_sint32 insertItemAt(T, UT_sint32 ndx);
00119 UT_sint32 addItemSorted(const T p, int (*compar)(const void *, const void *));
00120 void deleteNthItem(UT_sint32 n);
00121 void clear();
00122 void qsort(int (*compar)(const void *, const void *));
00123 UT_sint32 binarysearch(const void* key, int (*compar)(const void *, const void *)) const;
00124
00125 bool copy(const UT_GenericVector<T> *pVec);
00126 inline UT_sint32 size() const { return getItemCount(); }
00127
00128 private:
00129 UT_sint32 grow(UT_sint32);
00130 UT_sint32 binarysearchForSlot(const void* key, compar_fn_t compar) const;
00131
00132 T* m_pEntries;
00133 UT_sint32 m_iCount;
00134 UT_sint32 m_iSpace;
00135 UT_sint32 m_iCutoffDouble;
00136 UT_sint32 m_iPostCutoffIncrement;
00137 };
00138
00139
00140
00141 class ABI_EXPORT UT_Vector : public UT_GenericVector<void const *> {
00142 public:
00143 UT_Vector(UT_sint32 sizehint = 32, UT_sint32 baseincr = 4, bool bPrealloc = false)
00144 : UT_GenericVector<void const *>(sizehint, baseincr, bPrealloc)
00145 {}
00146 };
00147
00148
00149
00150 class ABI_EXPORT UT_NumberVector : public UT_GenericVector<UT_sint32> {
00151 public:
00152 UT_NumberVector(UT_sint32 sizehint = 32, UT_sint32 baseincr = 4, bool bPrealloc = false)
00153 : UT_GenericVector<UT_sint32>(sizehint, baseincr, bPrealloc)
00154 {}
00155 };
00156
00157 #include <stdlib.h>
00158 #include <string.h>
00159
00169 template <class T>
00170 UT_GenericVector<T>::UT_GenericVector(UT_sint32 sizehint, UT_sint32 baseincr, bool bPrealoc)
00171 : m_pEntries(NULL), m_iCount(0), m_iSpace(0),
00172 m_iCutoffDouble(sizehint), m_iPostCutoffIncrement(baseincr)
00173 {
00174 if(bPrealoc)
00175 grow(sizehint);
00176 }
00177
00178 template <class T>
00179 UT_GenericVector<T>::UT_GenericVector(const UT_GenericVector<T>& utv)
00180 : m_pEntries(NULL), m_iCount(0), m_iSpace(0),
00181 m_iCutoffDouble(utv.m_iCutoffDouble),
00182 m_iPostCutoffIncrement(utv.m_iPostCutoffIncrement)
00183 {
00184 copy(&utv);
00185 }
00186
00187 template <class T>
00188 UT_GenericVector<T>& UT_GenericVector<T>::operator=(const UT_GenericVector<T>& utv)
00189 {
00190 if(this != &utv)
00191 {
00192 m_iCutoffDouble = utv.m_iCutoffDouble;
00193 m_iPostCutoffIncrement = utv.m_iPostCutoffIncrement;
00194 copy(&utv);
00195 }
00196 return *this;
00197 }
00198
00199 template <class T>
00200 void UT_GenericVector<T>::clear()
00201 {
00202 if(m_iCount > m_iCutoffDouble)
00203 {
00204 xxx_UT_DEBUGMSG(("Vector contained %d entries, allocated %d slots\n", m_iCount, m_iSpace));
00205 }
00206
00207 m_iCount = 0;
00208 if (m_iSpace > 0)
00209 memset(m_pEntries, 0, m_iSpace * sizeof(T));
00210 }
00211
00212
00213 template <class T>
00214 UT_GenericVector<T>::~UT_GenericVector()
00215 {
00216 if(m_iCount > m_iCutoffDouble)
00217 {
00218 xxx_UT_DEBUGMSG(("Vector contained %d entries, allocated %d slots\n", m_iCount, m_iSpace));
00219 }
00220
00221 FREEP(m_pEntries);
00222 }
00223
00224
00225
00226
00227
00228 template <class T>
00229 UT_sint32 UT_GenericVector<T>::grow(UT_sint32 ndx)
00230 {
00231 UT_sint32 new_iSpace;
00232 if(!m_iSpace) {
00233 new_iSpace = m_iPostCutoffIncrement;
00234 }
00235 else if (m_iSpace < m_iCutoffDouble) {
00236 xxx_UT_DEBUGMSG(("Vector growing (%d -> %d\n", m_iSpace, ndx));
00237 new_iSpace = m_iSpace * 2;
00238 }
00239 else {
00240 new_iSpace = m_iSpace + m_iPostCutoffIncrement;
00241 }
00242
00243 if (new_iSpace < ndx)
00244 {
00245 new_iSpace = ndx;
00246 }
00247
00248 T * new_pEntries = static_cast<T *>(g_try_realloc(m_pEntries, new_iSpace * sizeof(T)));
00249 if (!new_pEntries) {
00250 return -1;
00251 }
00252
00253
00254
00255 memset(&new_pEntries[m_iSpace], 0, (new_iSpace - m_iSpace) * sizeof(T));
00256 m_iSpace = new_iSpace;
00257 m_pEntries = new_pEntries;
00258
00259 return 0;
00260 }
00261
00262 template <class T>
00263 UT_sint32 UT_GenericVector<T>::insertItemAt(const T p, UT_sint32 ndx)
00264 {
00265 if (ndx > m_iCount + 1)
00266 return -1;
00267
00268 if ((m_iCount+1) > m_iSpace)
00269 {
00270 UT_sint32 err = grow(0);
00271 if (err)
00272 {
00273 return err;
00274 }
00275 }
00276
00277
00278 memmove(&m_pEntries[ndx+1], &m_pEntries[ndx], (m_iCount - ndx) * sizeof(T));
00279
00280 m_pEntries[ndx] = (T)p;
00281 ++m_iCount;
00282
00283 return 0;
00284 }
00285
00286 template <class T>
00287 UT_sint32 UT_GenericVector<T>::addItem(const T p, UT_sint32 * pIndex)
00288 {
00289 UT_sint32 err = addItem(p);
00290 if (!err && pIndex)
00291 *pIndex = m_iCount-1;
00292 return err;
00293 }
00294
00295 template <class T>
00296 UT_sint32 UT_GenericVector<T>::addItem(const T p)
00297 {
00298 if ((m_iCount+1) > m_iSpace)
00299 {
00300 UT_sint32 err = grow(0);
00301 if (err)
00302 {
00303 return err;
00304 }
00305 }
00306
00307 m_pEntries[m_iCount++] = (T)p;
00308
00309 return 0;
00310 }
00311
00312 template <class T>
00313 UT_sint32 UT_GenericVector<T>::addItemSorted(const T p, int (*compar)(const void *, const void *))
00314 {
00315 if (!m_iCount) {
00316 return addItem(p);
00317 }
00318
00319 return insertItemAt( p, binarysearchForSlot((static_cast<void*>(const_cast<T*>(&p))), compar));
00320 }
00321
00323 template <class T>
00324 bool UT_GenericVector<T>::pop_back()
00325 {
00326 if (m_iCount > 0)
00327 {
00328 --m_iCount;
00329 return true;
00330 }
00331 else
00332 return false;
00333 }
00334
00335 template <class T>
00336 UT_sint32 UT_GenericVector<T>::setNthItem(UT_sint32 ndx, T pNew, T* ppOld)
00337 {
00338 const UT_sint32 old_iSpace = m_iSpace;
00339
00340 if (ndx >= m_iSpace)
00341 {
00342 const UT_sint32 err = grow(ndx+1);
00343 if (err)
00344 {
00345 return err;
00346 }
00347 }
00348
00349 if (ppOld)
00350 {
00351 *ppOld = (ndx < old_iSpace) ? m_pEntries[ndx] : 0;
00352 }
00353
00354 m_pEntries[ndx] = pNew;
00355 if (ndx >= m_iCount)
00356 {
00357 m_iCount = ndx + 1;
00358 }
00359
00360 return 0;
00361 }
00362
00363 template <class T>
00364 const T UT_GenericVector<T>::getLastItem() const
00365 {
00366 UT_ASSERT_HARMLESS(m_iCount > 0);
00367
00368 return m_pEntries[m_iCount-1];
00369 }
00370
00371 template <class T>
00372 const T UT_GenericVector<T>::getFirstItem() const
00373 {
00374 UT_ASSERT_HARMLESS(m_iCount > 0);
00375 UT_ASSERT_HARMLESS(m_pEntries);
00376 if (!m_pEntries) {
00377 return T();
00378 }
00379 return m_pEntries[0];
00380 }
00381
00382 template <class T>
00383 void UT_GenericVector<T>::deleteNthItem(UT_sint32 n)
00384 {
00385 UT_ASSERT_HARMLESS(n < m_iCount);
00386 UT_ASSERT_HARMLESS(m_iCount > 0);
00387
00388 memmove(&m_pEntries[n], &m_pEntries[n+1], (m_iCount - (n + 1)) * sizeof(T));
00389
00390 m_pEntries[m_iCount-1] = 0;
00391 m_iCount--;
00392
00393 return;
00394 }
00395
00396 template <class T>
00397 UT_sint32 UT_GenericVector<T>::findItem(T p) const
00398 {
00399 for (UT_sint32 i=0; i<m_iCount; i++)
00400 {
00401 if (m_pEntries[i] == p)
00402 {
00403 return i;
00404 }
00405 }
00406
00407 return -1;
00408 }
00409
00410 template <class T>
00411 void UT_GenericVector<T>::qsort(int (*compar)(const void *, const void *))
00412 {
00413 ::qsort(m_pEntries, m_iCount, sizeof(T), compar);
00414 }
00415
00416
00417
00418
00419
00420
00421 template <class T>
00422 UT_sint32 UT_GenericVector<T>::binarysearch(const void* key, compar_fn_t compar) const
00423 {
00424 UT_sint32 slot = binarysearchForSlot(key, compar);
00425
00426 if ((slot == m_iCount) || (0 != (*compar)(key, &m_pEntries[slot])))
00427 return -1;
00428 else
00429 return slot;
00430 }
00431
00432 template <class T>
00433 UT_sint32 UT_GenericVector<T>::binarysearchForSlot(const void* key, compar_fn_t compar) const
00434 {
00435 UT_sint32 high = m_iCount;
00436 UT_sint32 low = -1;
00437 UT_sint32 probe;
00438
00439 while (high - low > 1)
00440 {
00441 int res;
00442 probe = (high + low) / 2;
00443 res = (*compar)(key, &m_pEntries[probe]);
00444 if (0 < res)
00445 low = probe;
00446 else
00447 high = probe;
00448 }
00449
00450 return high;
00451 }
00452
00453 template <class T>
00454 bool UT_GenericVector<T>::copy(const UT_GenericVector<T> *pVec)
00455 {
00456 clear();
00457
00458 if (!pVec) {
00459 return false;
00460 }
00461
00462 for (UT_sint32 i=0; i < pVec->m_iCount; i++)
00463 {
00464 UT_sint32 err;
00465
00466 err = addItem(pVec->m_pEntries[i]);
00467 if(err == -1)
00468 return (err ? true : false);
00469 }
00470
00471 return false;
00472 }
00473
00474 template <class T>
00475 const T UT_GenericVector<T>::operator[](UT_sint32 i) const
00476 {
00477 return this->getNthItem(i);
00478 }
00479
00480
00481 #endif