00001
00002
00003
00004
00005
00006
00007 #ifndef __WVVECTOR_H
00008 #define __WVVECTOR_H
00009
00010 #include "wvxplc.h"
00011 #include "wvlink.h"
00012 #include "wvtypetraits.h"
00013 #include <string.h>
00014 #include <cstdio>
00015
00020 class WvVectorBase
00021 {
00022 private:
00023 WvVectorBase(const WvVectorBase &);
00024
00025 protected:
00026 static const int DEFAULTSIZE = 4;
00029 WvLink **xseq;
00030 int xcount;
00031 int xslots;
00034 WvVectorBase(int slots = DEFAULTSIZE);
00035
00037 ~WvVectorBase()
00038 {
00039 if (xseq)
00040 free(xseq);
00041 }
00042
00044 void remove(int slot);
00045
00047 void insert(int slot, WvLink *elem);
00048
00050 void prepend(WvLink *elem)
00051 {
00052 insert(0, elem);
00053 }
00054
00056 void append(WvLink *elem);
00057
00059 bool get_autofree(int slot)
00060 {
00061 if (slot >= 0 && slot < xcount)
00062 return xseq[slot]->get_autofree();
00063 return false;
00064 }
00065
00067 void set_autofree(int slot, bool autofree)
00068 {
00069 if (slot >= 0 && slot < xcount)
00070 xseq[slot]->set_autofree(autofree);
00071 }
00072
00073
00074 typedef int (*comparison_type_t)(const void *, const void *);
00075 private:
00076 static comparison_type_t innercomparator;
00077 protected:
00078 static int wrapcomparator(const void *_a, const void *_b)
00079 {
00080 WvLink *a = *static_cast<WvLink**>(const_cast<void*>(_a));
00081 WvLink *b = *static_cast<WvLink**>(const_cast<void*>(_b));
00082 return innercomparator(a->data, b->data);
00083 }
00084
00085 void qsort(comparison_type_t comparator)
00086 {
00087 innercomparator = comparator;
00088 ::qsort(xseq, xcount, sizeof(WvLink*), &WvVectorBase::wrapcomparator);
00089 }
00090
00091 public:
00092 class IterBase;
00093 friend class IterBase;
00094
00096 int count() const
00097 {
00098 return xcount;
00099 }
00100
00102 bool isempty() const
00103 {
00104 return xcount == 0;
00105 }
00106
00108 int get_capacity() const
00109 {
00110 return xslots;
00111 }
00112
00119 void set_capacity(int newslots);
00120
00122 void compact()
00123 {
00124 set_capacity(xcount);
00125 }
00126
00127 class IterBase
00128 {
00129 protected:
00130 const WvVectorBase &vec;
00131 int i;
00132 WvLink *link;
00133
00134 friend class WvVectorBase;
00135
00136 public:
00140 IterBase(const WvVectorBase &v)
00141 : vec(v), i(-1), link(NULL)
00142 {
00143 }
00144
00149 void rewind()
00150 {
00151 i = -1;
00152 link = (vec.xcount >= 0) ? vec.xseq[0] : NULL;
00153 }
00154
00159 void unwind()
00160 {
00161 i = vec.xcount - 1;
00162 link = (i >= 0) ? vec.xseq[i] : NULL;
00163 }
00164
00174 WvLink *next()
00175 {
00176 if (++i > vec.xcount - 1)
00177 return NULL;
00178 else
00179 {
00180 link = vec.xseq[i];
00181 return link;
00182 }
00183 }
00184
00191 WvLink *prev()
00192 {
00193 if (--i < 0)
00194 return NULL;
00195 else
00196 return vec.xseq[i];
00197 }
00198
00206 WvLink *cur() const
00207 {
00208 return link;
00209 }
00210
00224 WvLink *find(const void *data);
00225
00236 WvLink *find_next(const void *data);
00237 };
00238 };
00239
00245 template<class T>
00246 class WvVector : public WvVectorBase
00247 {
00248 public:
00250 WvVector()
00251 : WvVectorBase()
00252 {
00253 }
00254
00259 WvVector(int slots)
00260 : WvVectorBase(slots)
00261 {
00262 }
00263
00265 ~WvVector()
00266 {
00267 zap();
00268 }
00269
00271 T *operator[] (int slot)
00272 {
00273 if (slot >= 0 && slot < xcount)
00274 return static_cast<T *>(xseq[slot]->data);
00275 return NULL;
00276 }
00277
00279 void zap(bool destroy = true)
00280 {
00281 if (xcount > 0)
00282 for (int i = xcount - 1; i >= 0; --i)
00283 remove(i, destroy);
00284 }
00285
00287 T *first()
00288 {
00289 return (*this)[0];
00290 }
00291
00293 T *last()
00294 {
00295 return (*this)[xcount - 1];
00296 }
00297
00299 void remove(int slot, bool destroy = true)
00300 {
00301 WvLink *l = xseq[slot];
00302 T *obj = ((destroy && l->get_autofree())
00303 ? static_cast<T*>(l->data)
00304 : NULL);
00305 if (obj)
00306 WvTraits<T>::release(obj);
00307 delete l;
00308 WvVectorBase::remove(slot);
00309 }
00310
00312 void remove_last(bool destroy = true)
00313 {
00314 if (xcount)
00315 remove(xcount - 1, destroy);
00316 }
00317
00319 void insert(int slot, T *elem, bool autofree)
00320 {
00321 WvVectorBase::insert(slot, new WvLink(elem, autofree));
00322 }
00323
00325 void prepend(T *elem, bool autofree)
00326 {
00327 WvVectorBase::prepend(new WvLink(elem, autofree));
00328 }
00329
00331 void append(T *elem, bool autofree)
00332 {
00333 WvVectorBase::append(new WvLink(elem, autofree));
00334 }
00335
00341 typedef int (*comparison_type_fn_t)(const T *, const T *);
00342 void qsort(comparison_type_fn_t comparator)
00343 {
00344 if (xcount < 2)
00345 return;
00346 WvVectorBase::qsort(reinterpret_cast<comparison_type_t>(comparator));
00347 }
00348
00350 class Iter : public WvVectorBase::IterBase
00351 {
00352 public:
00354 Iter(const WvVector &v) : IterBase(v)
00355 {
00356 }
00357
00359 T *ptr() const
00360 {
00361 return static_cast<T *>(cur()->data);
00362 }
00363
00364 WvIterStuff(T);
00365
00369 bool get_autofree() const
00370 {
00371 return link->get_autofree();
00372 }
00373
00377 void set_autofree(bool autofree)
00378 {
00379 link->set_autofree(autofree);
00380 }
00381
00387 void remove(bool destroy = true)
00388 {
00389 WvVector::vec.remove(i, destroy);
00390 }
00391
00405 void xremove(bool destroy = true)
00406 {
00407 WvVector::vec.remove(i, destroy);
00408 prev();
00409 }
00410 };
00411 };
00412
00413 #define DeclareWvVector2(_classname_, _type_) \
00414 typedef class WvVector<_type_> _classname_
00415
00416 #define DeclareWvVector(_type_) DeclareWvVector2(_type_##Vector, _type_)
00417
00418 #endif // __WVVECTOR_H