/* utils.h: General utility definitions */ #ifndef _UTILS_H_ #define _UTILS_H_ #include #include "ti_config.h" #include "using-std.h" /* CONTROL EXTENSIONS */ /*********************************************************************** For loops specialized for Standard C++ iterators. P is the control variable, COLLECTION is the iterated-over collection, which has type TYPE. ***********************************************************************/ #define foreach(P, TYPE, COLLECTION) \ for (TYPE::iterator P = (COLLECTION).begin(); \ P != (COLLECTION).end(); \ P++) #define foreach_const(P, TYPE, COLLECTION) \ for (TYPE::const_iterator P = (COLLECTION).begin(); \ P != (COLLECTION).end(); \ P++) /*********************************************************************** For loops that use Hilfinger Standard Iterators (HSIs): P is the control variable, ITER is its iterator value, and TYPE is the type of ITER. In the loop foriter(P, ITER, TYPE) { S } the scope of P is the loop itself. Inside S, *P refers to the current item referred to by P, and one may also use the P-> syntax to get at fields of that item. You may also use an empty type, as in foriter(P, ITER, ) { S } which uses a P previously declared outside the loop. An HSI is a kind of general pointer to elements within some collection. An HSI H has the following methods defined on it: *H (operator*) is the object currently "pointed to" by H. Valid only while ! H.isDone(). In addition, operator-> is usually defined to yield &(*H), so that H->foo gets the foo field of the object currently pointed to by H. H.isDone() -> bool yields true iff H is not pointing at a valid object H.next() increments H to the next item. **********************************************************************/ #define foriter(P, ITER, TYPE) \ for (TYPE P = ITER; ! (P).isDone (); (P).next ()) #define foriter2(P0, ITER0, P1, ITER1, TYPE) \ for (TYPE P0 = ITER0, P1 = ITER1; ! P0.isDone () && ! P1.isDone (); \ P0.next (), P1.next ()) /*********************************************************************** HSIs for C-style vectors: VectIter(V, N, S = 1) A VectIter takes a T* (or T[]) value V and, when used as a control variable in a foriter, points in turn to the elements V[0], V[S], V[2S], ... V[kS], where k is the maximum integer such that kS0. CnstVectIterC(V, N, S = 1) Is the same as VectIter, but takes a T const * value for V. ***********************************************************************/ template class CnstVectIter; template class VectIter { friend class CnstVectIter; public: VectIter (T* V, size_t N0, unsigned int S0 = 1) : p (V), i (0), N (N0), S (S0) {} bool isDone () const { return i >= N; } void next () { i += S; } T& operator* () { return p[i]; } T* operator-> () { return &p[i]; } protected: T* p; unsigned int i; size_t N; unsigned int S; }; template class CnstVectIter { public: CnstVectIter (T const * V, size_t N0, unsigned int S0 = 1) : p (V), i (0), N (N0), S (S0) {} CnstVectIter (const VectIter& v) : p (v.p), i (v.i), N (v.N), S (v.S) {} bool isDone () const { return i >= N; } void next () { i += S; } T const & operator* () { return p[i]; } T const * operator-> () { return &p[i]; } protected: T const * p; unsigned int i; size_t N; unsigned int S; }; template VectIter allElements (vector& v, int step = 1) { return VectIter (&v[0], v.size (), step); } template CnstVectIter allElementVals (const vector& v, int step = 1) { return CnstVectIter (&v[0], v.size (), step); } #endif // !_UTILS_H_