Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

Sequence.H

Go to the documentation of this file.
00001 // Copyright (C) 2001, Compaq Computer Corporation
00002 
00003 // This file is part of Vesta.
00004 
00005 // Vesta is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 
00010 // Vesta is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with Vesta; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 
00019 // Last modified on Thu Apr 21 09:26:51 EDT 2005 by irina.furman@intel.com 
00020 //      modified on Mon Jan  3 22:36:08 EST 2005 by ken@xorian.net        
00021 //      modified on Thu Aug  8 13:44:11 EDT 2002 by kcschalk@shr.intel.com
00022 //      modified on Tue Feb  8 11:32:13 PST 2000 by mann   
00023 //      modified on Wed Feb 21 12:41:35 PST 1996 by heydon 
00024 //      modified on Sat Feb 17 11:28:56 PST 1996 by mcjones
00025 
00026 #ifndef _SEQUENCE_H
00027 #define _SEQUENCE_H
00028 
00029 /* Sequence is a template class defining extensible sequences,
00030    patterned after the Modula-3 generic Sequence interface.  Elements
00031    can be added or removed at either end of a sequence; they can also
00032    be accessed or updated at specific indexes. The expected cost of
00033    every method of a sequence is constant.
00034 
00035    The Sequence class is parameterized by a class "Elem". The implementation
00036    uses the "Elem" assignment operator to add new elements to the sequence, so
00037    you should make sure that an appropriate assignment operator is defined for
00038    your element type.
00039 
00040    To instantiate a sequence, you use cxx's "define_template"
00041    pragma. For this to work, you must first include the source file
00042    "Sequence.C", which provides implementations for the generic
00043    sequence methods. However, the "Sequence.C" code must be linked into
00044    your executable exactly once. Therefore, the recommended procedure
00045    is to write an implementation (.C) file of the form:
00046 
00047      #include "Sequence.C"
00048      <template-instantiation>
00049      <template-instantiation>
00050      ...
00051 
00052    Each <template-instantiation> is a one-line pragma, of the form:
00053 
00054      #pragma define_template Sequence<Elem>
00055 
00056    where "Elem" is the element type of the instantiated sequence. */
00057 
00058 // Forward declaration of STL type.
00059 struct std::bidirectional_iterator_tag;
00060 
00061 template <class Elem,
00062           bool elem_ptrfree = false>
00063 class Sequence {
00064   public:
00065     Sequence(int sizeHint = 5) throw ();
00066     /* Construct a new, empty sequence.  */
00067 
00068     Sequence(const Sequence<Elem, elem_ptrfree>& s) throw ();
00069     /* Construct a copy of "s". */
00070 
00071     Sequence(const Elem a[], int n) throw ();
00072     /* Construct a new sequence containing "a[i]" for "i" in the
00073        half-open interval "[0, n)". */
00074 
00075     ~Sequence() throw ();
00076     /* Free any memory allocated by this sequence. */
00077 
00078     Sequence<Elem, elem_ptrfree>& operator= (const Sequence<Elem, elem_ptrfree>& s)
00079       throw ();
00080     /* Assign to this sequence a copy of "s". */
00081 
00082     int size() const throw () { return sz; }
00083     /* Return the number of elements in the sequence. */
00084 
00085     void addhi(const Elem &x) throw ();
00086     /* Append "x" to the end of the sequence, without changing the
00087        index of any existing element. */
00088 
00089     void addlo(const Elem &x) throw ();
00090     /* Append "x" to the front of the sequence, increasing the index
00091        of all existing elements by one. */
00092 
00093     Elem remhi() throw ();
00094     /* Remove and return the last element of the sequence, without
00095        changing the index of any other element.  If the sequence
00096        is empty, "remhi()" causes a checked runtime error. */
00097 
00098     Elem remlo() throw ();
00099     /* Remove and return the first element of the sequence,
00100        decreasing the index of all other elements by one.  If the
00101        sequence is empty, "remlo()" causes a checked runtime
00102        error. */
00103 
00104     void put(int i, const Elem &x) throw ();
00105     /* Replace element "i" of the sequence with "x".  Element 0 is the
00106        first element. It is a checked runtime error unless "i" is
00107        less than "size()". */
00108 
00109     Elem get(int i) const throw ();
00110     /* Return element "i" of the sequence.  It is a checked runtime
00111        error unless "i" is less than "size()". */
00112 
00113     Elem &get_ref(int i) throw ();
00114     const Elem &get_ref(int i) const throw ();
00115     /* Return a reference to element "i" of the sequence.  It is a
00116        checked runtime error unless "i" is less than "size()". */
00117 
00118     Elem gethi() const throw ();
00119     /* Return the last element of the sequence; equivalent to
00120        "get(size()-1)". */
00121 
00122     Elem getlo() const throw ();
00123     /* Return the first element of the sequence; equivalent to
00124        "get(0)". */
00125  
00126     Sequence<Elem, elem_ptrfree> cat(const Sequence<Elem, elem_ptrfree> &s)
00127       const throw ();
00128     /* Return a sequence whose elements are the concatenation of
00129        this sequence and "s". */
00130 
00131     Sequence<Elem, elem_ptrfree> sub(int start, int length = INT_MAX)
00132       const throw ();
00133     /* Return a sub-sequence of this sequence: empty if "start >= size()"
00134        or "length == 0"; otherwise the subsequence ranging from start
00135        to the minimum of "start + length - 1" and "size() - 1". */
00136 
00137     /* Sequences are unmonitored: a client accessing a sequence
00138        from multiple threads must ensure that if two operations
00139        are active concurrently, then neither of them has
00140        side-effects on the sequence. */
00141 
00142   // Iterator class making it possible to use a Sequence with the
00143   // Standard Template Library (STL).
00144   class Iterator
00145   {
00146   public:
00147     // These typedefs are required to be an STL iterator.
00148     typedef Elem value_type;
00149     typedef Elem *pointer;
00150     typedef Elem &reference;
00151     typedef unsigned int size_type;
00152     typedef int difference_type;
00153     typedef std::bidirectional_iterator_tag iterator_category;
00154     
00155   private:
00156     Sequence<Elem, elem_ptrfree> &seq;
00157     unsigned int index;
00158   public:
00159     Iterator(Sequence<Elem, elem_ptrfree> &s,
00160              unsigned int i) throw()
00161       : seq(s), index(i)
00162       { }
00163     Iterator(const Iterator &other) throw()
00164       : seq(other.seq), index(other.index)
00165       { }
00166 
00167     bool operator==(const Iterator& other) const
00168       { return (&seq == &(other.seq)) && (index == other.index); }
00169     bool operator!=(const Iterator& other) const
00170       { return (&seq != &(other.seq)) || (index != other.index); }
00171     bool operator<(const Iterator& other) const
00172       { return (&seq == &(other.seq)) && (index < other.index); }
00173 
00174     difference_type operator-(const Iterator& other) const
00175     {
00176       assert(&seq == &(other.seq));
00177       return index - other.index;
00178     }
00179     Iterator operator-(difference_type d)
00180     {
00181       Iterator r(*this);
00182       r.index -= d;
00183       return r;
00184     }
00185     Iterator operator+(difference_type d)
00186     {
00187       Iterator r(*this);
00188       r.index += d;
00189       return r;
00190     }
00191 
00192     Iterator &operator=(const Iterator& other) throw()
00193     {
00194       assert(&seq == &(other.seq));
00195       index = other.index;
00196       return *this;
00197     }
00198     Iterator& operator+=(difference_type d)
00199       { index += d; return *this; }
00200     Iterator& operator-=(difference_type d)
00201       { index -= d; return *this; }
00202 
00203     Elem &operator*() const throw()
00204       { return seq.get_ref(index); }
00205 
00206     Iterator& operator++() throw()
00207       { index++; return *this; }
00208     Iterator operator++(int)
00209       { Iterator r = *this; ++*this; return r; }
00210     Iterator& operator--() throw()
00211       { index--; return *this; }
00212     Iterator operator--(int)
00213       { Iterator r = *this; --*this; return r; }
00214   };
00215 
00216   // Create iterators for the first element and one past the last
00217   // element.
00218   Iterator begin() throw()
00219     { return Iterator(*this, 0); }
00220   Iterator end() throw()
00221     { return Iterator(*this, sz); }
00222 
00223   // Note: currently there's no const Iterator, and the above methods
00224   // can't be used on a const Sequence.  The Iterator was added
00225   // primarily to make it possible to use std::sort on a Sequence.
00226   // Some additional work is required to make an iterator that can be
00227   // used on a const Sequence.
00228 
00229   private:
00230     int numElem;
00231     Elem* elem;
00232     int sz;
00233     int st;
00234 
00235     /* Element i of s is stored in s.elem[(s.st + i) % s.numElem].
00236 
00237        A sequence s satisfies the invariant that:
00238          (s.elem != NULL) && (s.sz <= s.numElem)
00239          && ``s.elem contains numElem elements''
00240          && (s.size() == s.sz) && (s.numElem > 0)
00241          && (0 <= s.st) && (s.st < s.numElem)
00242     */
00243 
00244     // static zero element
00245     static Elem elemZero;
00246 
00247     void expand() throw ();
00248     /* Double the size of the sequence so it can hold more elements. */
00249 };
00250 
00251 // ========== template member definitions ==========
00252 
00253 template <class Elem, bool elem_ptrfree>
00254 Elem Sequence<Elem, elem_ptrfree>::elemZero;
00255 
00256 template <class Elem, bool elem_ptrfree>
00257 Sequence<Elem, elem_ptrfree>::Sequence(int sizeHint) throw ()
00258 : numElem(max(sizeHint, 1)), sz(0), st(0)
00259 {
00260   elem =(elem_ptrfree 
00261          ? NEW_PTRFREE_ARRAY(Elem, numElem)
00262          : NEW_ARRAY(Elem, numElem)); 
00263 }
00264 
00265 template <class Elem, bool elem_ptrfree>
00266 Sequence<Elem, elem_ptrfree>::Sequence(const Sequence<Elem, elem_ptrfree> &s)
00267   throw ()
00268 : numElem(s.numElem), sz(s.sz), st(0)
00269 {
00270   elem =(elem_ptrfree 
00271          ? NEW_PTRFREE_ARRAY(Elem, s.numElem)
00272          : NEW_ARRAY(Elem, s.numElem)); 
00273   for (int i = 0, j = s.st; i < sz; i++, j++) {
00274     if (j == s.numElem) j = 0;
00275     elem[i] = s.elem[j];
00276   }
00277 }
00278 
00279 template <class Elem, bool elem_ptrfree>
00280 Sequence<Elem, elem_ptrfree>::Sequence(const Elem a[], int n) throw ()
00281 : numElem(max(n, 1)), sz(n), st(0)
00282 {
00283   elem =(elem_ptrfree 
00284          ? NEW_PTRFREE_ARRAY(Elem, numElem)
00285          : NEW_ARRAY(Elem, numElem)); 
00286   for (int i = 0; i < n; i++)
00287         elem[i] = a[i];
00288 }
00289 
00290 template <class Elem, bool elem_ptrfree>
00291 Sequence<Elem, elem_ptrfree>::~Sequence() throw ()
00292 {
00293     delete[] elem; // call elem[i].~Elem() for 0 <= i < numElem
00294 }
00295 
00296 template <class Elem, bool elem_ptrfree>
00297 Sequence<Elem, elem_ptrfree>& Sequence<Elem, elem_ptrfree>::operator= (const Sequence<Elem, elem_ptrfree> &s)
00298   throw ()
00299 {
00300     delete[] elem; // call elem[i].~Elem() for 0<=i<numElem
00301     numElem = s.numElem;
00302     elem =(elem_ptrfree 
00303            ? NEW_PTRFREE_ARRAY(Elem, numElem)
00304            : NEW_ARRAY(Elem, numElem)); 
00305     sz = s.sz;
00306     st = 0;
00307     for (int i = 0, j = s.st; i < sz; i++, j++) {
00308         if (j == s.numElem) j = 0;
00309         elem[i] = s.elem[j];
00310     }
00311     return *this;
00312 }
00313 
00314 template <class Elem, bool elem_ptrfree>
00315 void Sequence<Elem, elem_ptrfree>::expand() throw ()
00316 {
00317   Elem* elemNew =(elem_ptrfree 
00318                   ? NEW_PTRFREE_ARRAY(Elem, 2*numElem)
00319                   : NEW_ARRAY(Elem, 2*numElem)); 
00320     int m = numElem - st;
00321     int i,j;
00322     for (i = 0, j = st; i < m; i++, j++)       elemNew[i] = elem[j];
00323     for (i = m, j = 0 ; i < numElem; i++, j++) elemNew[i] = elem[j];
00324 
00325     numElem = 2 * numElem;
00326     delete[] elem; // call elem[i].~Elem() for 0 <= i < numElem
00327     elem = elemNew;
00328     st = 0;
00329 }
00330 
00331 template <class Elem, bool elem_ptrfree>
00332 void Sequence<Elem, elem_ptrfree>::addhi(const Elem &x) throw ()
00333 {
00334     if (sz == numElem) expand();
00335     int i = st + sz;
00336     if (numElem <= i) i -= numElem;
00337     elem[i] = x;
00338     sz++;
00339 }
00340 
00341 template <class Elem, bool elem_ptrfree>
00342 void Sequence<Elem, elem_ptrfree>::addlo(const Elem &x) throw ()
00343 {
00344     if (sz == numElem) expand();
00345     int i = st;
00346     if (i == 0) i = numElem;
00347     i--;
00348     elem[i] = x;
00349     st = i;
00350     sz++;
00351 }
00352 
00353 template <class Elem, bool elem_ptrfree>
00354 Elem Sequence<Elem, elem_ptrfree>::remhi() throw ()
00355 {
00356     assert(0 < sz);
00357     int i = st+sz-1;
00358     if (numElem <= i) i -= numElem;
00359     Elem res(elem[i]);
00360     elem[i] = elemZero;
00361     sz--;
00362     return res;
00363 }
00364 
00365 template <class Elem, bool elem_ptrfree>
00366 Elem Sequence<Elem, elem_ptrfree>::remlo() throw ()
00367 {
00368     assert(0 < sz);
00369     Elem res(elem[st]);
00370     elem[st] = elemZero;
00371     st++; if (st == numElem) st = 0;
00372     sz--;
00373     return res;
00374 }
00375 
00376 template <class Elem, bool elem_ptrfree>
00377 void Sequence<Elem, elem_ptrfree>::put(int i, const Elem &x) throw ()
00378 {
00379     assert((0 <= i) && (i < sz));
00380     int j = st + i;
00381     if (numElem <= j) j -= numElem;
00382     elem[j] = x;
00383 }
00384 
00385 template <class Elem, bool elem_ptrfree>
00386 Elem Sequence<Elem, elem_ptrfree>::get(int i) const throw ()
00387 {
00388     assert((0 <= i) && (i < sz));
00389     int j = st + i;
00390     if (numElem <= j) j -= numElem;
00391     return elem[j];
00392 }
00393 
00394 template <class Elem, bool elem_ptrfree>
00395 Elem &Sequence<Elem, elem_ptrfree>::get_ref(int i) throw ()
00396 {
00397     assert((0 <= i) && (i < sz));
00398     int j = st + i;
00399     if (numElem <= j) j -= numElem;
00400     return elem[j];
00401 }
00402 
00403 template <class Elem, bool elem_ptrfree>
00404 const Elem &Sequence<Elem, elem_ptrfree>::get_ref(int i) const throw ()
00405 {
00406     assert((0 <= i) && (i < sz));
00407     int j = st + i;
00408     if (numElem <= j) j -= numElem;
00409     return elem[j];
00410 }
00411 
00412 template <class Elem, bool elem_ptrfree>
00413 Elem Sequence<Elem, elem_ptrfree>::gethi() const throw ()
00414 {
00415     assert(0 < sz);
00416     int j = st + sz - 1;
00417     if (numElem <= j) j -= numElem;
00418     return elem[j];
00419 }
00420 
00421 template <class Elem, bool elem_ptrfree>
00422 Elem Sequence<Elem, elem_ptrfree>::getlo() const throw ()
00423 {
00424     assert(0 < sz);
00425     return elem[st];
00426 }
00427 
00428 template <class Elem, bool elem_ptrfree>
00429 Sequence<Elem, elem_ptrfree> Sequence<Elem, elem_ptrfree>::cat(const Sequence<Elem, elem_ptrfree> &s)
00430   const throw ()
00431 {
00432     int i;
00433     Sequence<Elem, elem_ptrfree> u(sz + s.sz);
00434     u.sz = sz + s.sz;
00435     for (i = 0; i < sz;   i++) u.elem[i] = get(i);
00436     for (i = 0; i < s.sz; i++) u.elem[sz+i] = s.get(i);
00437     return u;
00438 }
00439 
00440 template <class Elem, bool elem_ptrfree>
00441 Sequence<Elem, elem_ptrfree> Sequence<Elem, elem_ptrfree>::sub(int start,
00442                                                                int length)
00443   const throw ()
00444 {
00445     int n = (sz <= start) ? 0 : min(length, sz - start);
00446     Sequence<Elem, elem_ptrfree> u(n);
00447     u.sz = n;
00448     for (int i = 0; i < n; i++)
00449         u.elem[i] = get(start + i);
00450     return u;
00451 }
00452 
00453 #endif // _SEQUENCE_H

Generated on Mon May 8 00:48:29 2006 for Vesta by  doxygen 1.4.2