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 UT_DEBUGMSG(("Vector contained %d entries, allocated %d slots\n", m_iCount, m_iSpace));
00205 }
00206
00207 m_iCount = 0;
00208 memset(m_pEntries, 0, m_iSpace * sizeof(T));
00209 }
00210
00211
00212 template <class T>
00213 UT_GenericVector<T>::~UT_GenericVector()
00214 {
00215 if(m_iCount > m_iCutoffDouble)
00216 {
00217 UT_DEBUGMSG(("Vector contained %d entries, allocated %d slots\n", m_iCount, m_iSpace));
00218 }
00219
00220 FREEP(m_pEntries);
00221 }
00222
00223
00224
00225
00226
00227 template <class T>
00228 UT_sint32 UT_GenericVector<T>::grow(UT_sint32 ndx)
00229 {
00230 UT_sint32 new_iSpace;
00231 if(!m_iSpace) {
00232 new_iSpace = m_iPostCutoffIncrement;
00233 }
00234 else if (m_iSpace < m_iCutoffDouble) {
00235 xxx_UT_DEBUGMSG(("Vector growing (%d -> %d\n", m_iSpace, ndx));
00236 new_iSpace = m_iSpace * 2;
00237 }
00238 else {
00239 new_iSpace = m_iSpace + m_iPostCutoffIncrement;
00240 }
00241
00242 if (new_iSpace < ndx)
00243 {
00244 new_iSpace = ndx;
00245 }
00246
00247 T * new_pEntries = static_cast<T *>(g_try_realloc(m_pEntries, new_iSpace * sizeof(T)));
00248 if (!new_pEntries) {
00249 return -1;
00250 }
00251
00252
00253
00254 memset(&new_pEntries[m_iSpace], 0, (new_iSpace - m_iSpace) * sizeof(T));
00255 m_iSpace = new_iSpace;
00256 m_pEntries = new_pEntries;
00257
00258 return 0;
00259 }
00260
00261 template <class T>
00262 UT_sint32 UT_GenericVector<T>::insertItemAt(const T p, UT_sint32 ndx)
00263 {
00264 if (ndx > m_iCount + 1)
00265 return -1;
00266
00267 if ((m_iCount+1) > m_iSpace)
00268 {
00269 UT_sint32 err = grow(0);
00270 if (err)
00271 {
00272 return err;
00273 }
00274 }
00275
00276
00277 memmove(&m_pEntries[ndx+1], &m_pEntries[ndx], (m_iCount - ndx) * sizeof(T));
00278
00279 m_pEntries[ndx] = (T)p;
00280 ++m_iCount;
00281
00282 return 0;
00283 }
00284
00285 template <class T>
00286 UT_sint32 UT_GenericVector<T>::addItem(const T p, UT_sint32 * pIndex)
00287 {
00288 UT_sint32 err = addItem(p);
00289 if (!err && pIndex)
00290 *pIndex = m_iCount-1;
00291 return err;
00292 }
00293
00294 template <class T>
00295 UT_sint32 UT_GenericVector<T>::addItem(const T p)
00296 {
00297 if ((m_iCount+1) > m_iSpace)
00298 {
00299 UT_sint32 err = grow(0);
00300 if (err)
00301 {
00302 return err;
00303 }
00304 }
00305
00306 m_pEntries[m_iCount++] = (T)p;
00307
00308 return 0;
00309 }
00310
00311 template <class T>
00312 UT_sint32 UT_GenericVector<T>::addItemSorted(const T p, int (*compar)(const void *, const void *))
00313 {
00314 if (!m_iCount) {
00315 return addItem(p);
00316 }
00317
00318 return insertItemAt( p, binarysearchForSlot((static_cast<void*>(const_cast<T*>(&p))), compar));
00319 }
00320
00322 template <class T>
00323 bool UT_GenericVector<T>::pop_back()
00324 {
00325 if (m_iCount > 0)
00326 {
00327 --m_iCount;
00328 return true;
00329 }
00330 else
00331 return false;
00332 }
00333
00334 template <class T>
00335 UT_sint32 UT_GenericVector<T>::setNthItem(UT_sint32 ndx, T pNew, T* ppOld)
00336 {
00337 const UT_sint32 old_iSpace = m_iSpace;
00338
00339 if (ndx >= m_iSpace)
00340 {
00341 const UT_sint32 err = grow(ndx+1);
00342 if (err)
00343 {
00344 return err;
00345 }
00346 }
00347
00348 if (ppOld)
00349 {
00350 *ppOld = (ndx < old_iSpace) ? m_pEntries[ndx] : 0;
00351 }
00352
00353 m_pEntries[ndx] = pNew;
00354 if (ndx >= m_iCount)
00355 {
00356 m_iCount = ndx + 1;
00357 }
00358
00359 return 0;
00360 }
00361
00362 template <class T>
00363 const T UT_GenericVector<T>::getLastItem() const
00364 {
00365 UT_ASSERT_HARMLESS(m_iCount > 0);
00366
00367 return m_pEntries[m_iCount-1];
00368 }
00369
00370 template <class T>
00371 const T UT_GenericVector<T>::getFirstItem() const
00372 {
00373 UT_ASSERT_HARMLESS(m_iCount > 0);
00374 UT_ASSERT_HARMLESS(m_pEntries);
00375
00376 return m_pEntries[0];
00377 }
00378
00379 template <class T>
00380 void UT_GenericVector<T>::deleteNthItem(UT_sint32 n)
00381 {
00382 UT_ASSERT_HARMLESS(n < m_iCount);
00383 UT_ASSERT_HARMLESS(m_iCount > 0);
00384
00385 memmove(&m_pEntries[n], &m_pEntries[n+1], (m_iCount - (n + 1)) * sizeof(T));
00386
00387 m_pEntries[m_iCount-1] = 0;
00388 m_iCount--;
00389
00390 return;
00391 }
00392
00393 template <class T>
00394 UT_sint32 UT_GenericVector<T>::findItem(T p) const
00395 {
00396 for (UT_sint32 i=0; i<m_iCount; i++)
00397 {
00398 if (m_pEntries[i] == p)
00399 {
00400 return i;
00401 }
00402 }
00403
00404 return -1;
00405 }
00406
00407 template <class T>
00408 void UT_GenericVector<T>::qsort(int (*compar)(const void *, const void *))
00409 {
00410 ::qsort(m_pEntries, m_iCount, sizeof(T), compar);
00411 }
00412
00413
00414
00415
00416
00417
00418 template <class T>
00419 UT_sint32 UT_GenericVector<T>::binarysearch(const void* key, compar_fn_t compar) const
00420 {
00421 UT_sint32 slot = binarysearchForSlot(key, compar);
00422
00423 if ((slot == m_iCount) || (0 != (*compar)(key, &m_pEntries[slot])))
00424 return -1;
00425 else
00426 return slot;
00427 }
00428
00429 template <class T>
00430 UT_sint32 UT_GenericVector<T>::binarysearchForSlot(const void* key, compar_fn_t compar) const
00431 {
00432 UT_sint32 high = m_iCount;
00433 UT_sint32 low = -1;
00434 UT_sint32 probe;
00435
00436 while (high - low > 1)
00437 {
00438 int res;
00439 probe = (high + low) / 2;
00440 res = (*compar)(key, &m_pEntries[probe]);
00441 if (0 < res)
00442 low = probe;
00443 else
00444 high = probe;
00445 }
00446
00447 return high;
00448 }
00449
00450 template <class T>
00451 bool UT_GenericVector<T>::copy(const UT_GenericVector<T> *pVec)
00452 {
00453 clear();
00454
00455 for (UT_sint32 i=0; i < pVec->m_iCount; i++)
00456 {
00457 UT_sint32 err;
00458
00459 err = addItem(pVec->m_pEntries[i]);
00460 if(err == -1)
00461 return (err ? true : false);
00462 }
00463
00464 return 0;
00465 }
00466
00467 template <class T>
00468 const T UT_GenericVector<T>::operator[](UT_sint32 i) const
00469 {
00470 return this->getNthItem(i);
00471 }
00472
00473
00474 #endif