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