Polaris: List.h Source File

List.h

Go to the documentation of this file.
00001 ///
00002 ///
00003 #ifndef _LIST_H
00004 #define _LIST_H
00005 ///
00006 /// \class List 
00007 /// \brief template for types derived from Listable
00008 /// \defgroup Polaris
00009 /// \ingroup Polaris
00010 ///  C++ VDL
00011 /// \see List.h
00012 ///
00013 /// \endcode
00014 /// \section Overview Overview
00015 /// The List class creates a templatized linked-list object for
00016 /// objects which must be derived from Listable. Since the List
00017 /// is built from Collection it works with Iterators. When an
00018 /// object is placed into a List, the List assumes ownership of
00019 /// the object and that object can not be placed in any other
00020 /// live structure. An object must be in a live structure, like
00021 /// List, before it can be used in a reference structure, like
00022 /// RefList.
00023 ///
00024 /// \endcode
00025 /// \section Description Description
00026 /// If a list is static, its size must remain constant.  Thus, calls
00027 /// to either ins or del methods result in errors.  If an element is
00028 /// grabbed from a static list, the element's position becomes invalid
00029 /// (a state which can be checked).  That position can then be
00030 /// modified to another object which will revalidate it.  All modify
00031 /// routines operate on static lists. A static list can be initialized
00032 /// to a fixed size by passing a positive integer value to the constructor.
00033 /// This creates a staic list of invlaid elements which can changed
00034 /// using 'modify' commands.
00035 ///
00036 /// Note that Lists are indexed from 0.
00037 ///
00038 /// These Lists provide reference counting so
00039 /// List elements, if deleted or grabbed from the owner list while
00040 /// still being referenced by some reference structures, will
00041 /// become \'invalid\'--a state which can be checked by the ref. structure
00042 /// before any dereferencing takes place.
00043 ///
00044 /// \endcode
00045 /// \section Assign Assign Operation
00046 /// assign/pull is designed to allow the functionality of
00047 /// modifying an element of a list to be some function of the old value of
00048 /// that position.  The assign() is meant to be executed first, to 
00049 /// capture the original position in the under-lying list for the element.
00050 /// The Assign<T> object returned by assign() stores the position information
00051 /// of the element.  Then, pull() is used to remove the element from the 
00052 /// list, without losing its position in the list.
00053 /// 
00054 /// The 'pull' method removes the specified object from its list (like
00055 /// grab) but maintains it's 'place' in the list.  Once an object has been
00056 /// pulled, it is no longer possible to access the List using the pulled
00057 /// object as a reference.  Once an object has been pulled it can be
00058 /// modified in any way.  Once the modification is complete, the object
00059 /// can be returned to its position in the list by assigning to the Assign<T>
00060 /// object (the one created by the original assign() call).
00061 ///
00062 /// The user, of course, is responsible for garbage collecting any
00063 /// intermediate forms of the pulled object which may be created.  A 
00064 /// complete use would be as follows:
00065 /// 
00066 /// \code
00067 ///        {
00068 ///        loc = list.index(el);
00069 ///        Assign<Expression> a = list.assign(loc);
00070 ///        a = function(list.pull(loc) );
00071 ///        }  // "a" is removed by leaving the scope
00072 /// 
00073 ///                   --or--
00074 ///        {
00075 ///        Assign<Expression> a = list.assign(el);
00076 ///        a = function(list.pull(el) );
00077 ///        }  // "a" is removed by leaving the scope
00078 /// \endcode
00079 /// 
00080 /// 'function' is simply a funtion which returns the modified value. If
00081 /// the modified value is a different object than the original, function
00082 /// is responsible for garbage collecting the original.  In this case, the
00083 /// specified object is pulled from the list, modified somehow by function
00084 /// and the returned value takes it's place in the list.
00085 /// 
00086 ///  IMPORTANT \note
00087 ///
00088 ///  Due to the order in which different C++ compilers evaluate assignment 
00089 ///  statements, the statement:
00090 ///
00091 /// \code
00092 ///            list.assign(el) = f(list.pull(el));
00093 /// \endcode
00094 ///
00095 ///  may not function correctly.  Also, the following code is INCORRECT:
00096 ///
00097 /// \code
00098 ///             x = list.pull(el);
00099 ///             list.assign(el) = f(x);
00100 /// \endcode
00101 ///
00102 ///  will result in a run-time error.  The assign() member function must
00103 ///  ALWAYS execute prior to the corresponding pull() member function!
00104 ///
00105 ///
00106 /// \endcode
00107 /// \section Hierarchy Hierarchy Structure
00108 /// List does not directly inherit from Collection. Instead
00109 /// it inherits from TypedCollection (which forms the interface
00110 /// to all Iterator routines) and contains a BaseList
00111 /// which inherits from Collection.
00112 /// The hierarchy can be represented by:
00113 ///
00114 /// \code
00115 ///                     --- :    inherited from relationship
00116 ///                     -c- :    contained in relationship
00117 ///
00118 ///
00119 ///                         Collection
00120 ///                        /          \                                          //
00121 ///                       /            \                                         //
00122 ///               BaseList   Listable   BaseRefList
00123 ///               |  \          |             /  |
00124 ///               |   \         |            /   |
00125 ///               |    c  TypedCollection   c    |
00126 ///               |     \     /     \      /     |
00127 ///               |      \   /       \    /      |
00128 ///               |      LIST        RefList     |
00129 ///               |      Set         RefSet      |
00130 ///               c                              c
00131 ///               |          Listable            |
00132 ///               |             |                |
00133 ///               |             |                |
00134 ///               |        BaseMapRoot           |
00135 ///               |       /           \          |
00136 ///               |      /             \         |
00137 ///               BaseMap               BaseRefMap
00138 ///                  |                       |
00139 ///                  |                       |                            
00140 ///             TypedBaseMap          TypedBaseRefMap
00141 ///               /     \                /         \                             //
00142 ///              /       \              /           \                            //
00143 ///    ProtoDatabase      ProtoMap   ProtoRefMap    ProtoRefDatabase
00144 ///         /  \           |    |      |     |         |         \               //
00145 ///        /    \          |    |      |     |         |          \              //
00146 /// Database KeyDatabase  Map KeyMap  RefMap KeyMap  RefDatabase RefKeyDatabase
00147 /// \endcode
00148 ///
00149 /// \endcode
00150 /// \section See See Also
00151 /// Collection, Listable, Wrapper, Iterator, TypedCollection, Zombie,
00152 /// BaseList
00153 ///
00154 ///
00155 #include <stream.h>
00156 #include "BaseList.h"
00157 #include "TypedCollection.h"
00158 #include "Assign.h"
00159 #include "../macros.h"
00160 ///
00161 template <class T> class List : public TypedCollection<T> {
00162     friend class Iterator <T>;
00163     friend class Mutator <T>;
00164     friend class TopSorter;
00165     ///< gcc-2.96 need the stupid "<>" pair
00166     ///< friend ostream & operator << (ostream & o, const List<T> &l);
00167     friend ostream & operator << <> (ostream & o, const List<T> &l);
00168 
00169  protected:
00170     BaseList               _list;
00171     virtual INLINE const Collection &    _base_collection() const;
00172     virtual INLINE Collection &    _base_collection();
00173 
00174  public:
00175     INLINE          List();
00176     ///< create an empty list
00177 
00178     INLINE          List(const List<T> &l);
00179     ///< create a list identical to l
00180 
00181     virtual INLINE          ~List();
00182 
00183     INLINE          List(unsigned static_size);
00184     ///< Create a static list of size static_size initialized
00185     ///< with all elements invalid.
00186 
00187     INLINE          List(const T *el1, const T *el2 GIV(0));
00188     ///< create a static list of 1 or 2 elements.
00189 
00190     INLINE void     make_static_list(int static_size);
00191     ///< Clear the list and set it to a static list of size 
00192     ///< static_size with all elements invalid.
00193     
00194     INLINE Boolean  static_size() const;
00195     ///< Is the size of the collection static?
00196 
00197     INLINE void     fix_size();
00198     ///< Make the size constant.
00199 
00200     INLINE void     unfix_size();
00201     ///< Make the size variable.
00202 
00203     INLINE int      entries() const;
00204     ///< Return the number of entries within the List.
00205 
00206     INLINE Boolean  member(const T &el) const;
00207     ///< Check to see if node 'el' is a member of the List.  Return
00208     ///< 0 if the element was not found, else return 1.
00209 
00210     INLINE int      index(const T &el) const;
00211     ///< Check to see if node 'el' is a member of the List.  Return
00212     ///< -1 if the element was not found, else return the index of
00213     ///< the element.
00214 
00215     INLINE const T &operator[] (int sub) const;
00216     INLINE T       &operator[] (int sub);
00217     ///< Implements the subscript operator (indexed from 0).
00218     ///< Should be used for random access only.
00219     ///< Consecutive searching should use the Iterator<T> class.
00220     ///< It is much more efficient.
00221 
00222     INLINE void     print(ostream & out, char *sep) const;
00223     ///< print list to out with 'sep' sepperating each element.
00224 
00225     virtual INLINE void     ins(const T *new_element, int loc);
00226     ///< Insert new_element at location loc, where 0 <= loc <= entries().
00227     ///< This results in an error if the List is static sized.
00228 
00229     virtual INLINE void     del(int loc); 
00230     ///< Random Access Delete.
00231     ///< Delete the Node in position loc where 0 <= loc < entries()-1.
00232     ///< If references to the deleted element exist in RefStructures,
00233     ///< the references will now be invalid, making access illegal.
00234     ///< This results in an error for static lists.
00235 
00236     virtual INLINE void     del(T &el);
00237     ///< Delete node 'el'.  el MUST be in the BaseList (this is not
00238     ///< necessarily checked). If the list is static a error is raised.
00239     ///< If references to the deleted element exist in RefStructures,
00240     ///< the references will now be invalid, making access illegal.
00241 
00242     virtual INLINE T       *grab(int loc);
00243     ///< Random Access Grab.
00244     ///< Grab (i.e. unlink and return the pointer to, but DO NOT
00245     ///< delete) the element at location loc.
00246     ///< If the list is static, the locth Node becomes invalid.
00247 
00248     virtual INLINE T       *grab(T &el);
00249     ///< Grab (i.e. unlink and return the reference to, but DO NOT
00250     ///< delete) the element 'el', which MUST be in the list
00251     ///< (this is not necessarily checked). If the list is static
00252     ///< the node which was grabbed becomes invalid.
00253     ///< If references to the deleted element exist in RefStructures,
00254     ///< the references will now be invalid, making access illegal.
00255 
00256     virtual INLINE T       *modify_and_grab(T &el, T *replacement);
00257     ///< Modify the list by grabbing 'el' out of the list and
00258     ///< replacing it with 'replacement' in the spot which
00259     ///< 'el' had taken in the list.  A pointer to 'el' is returned,
00260     ///< and the user becomes responsible for deleting 'el'.
00261     ///< If 'el' is the same element as 'replacement', a run-time
00262     ///< error message occurs.
00263 
00264     virtual INLINE void     modify(T &el, T *replacement);
00265     ///< Modify the list by grabbing 'el' out of the list and
00266     ///< replacing it with 'replacement' in the spot which
00267     ///< 'el' had taken in the list.  'el' is deleted.
00268     ///< 'el' MAY be the same element as 'replacement'.  In this
00269     ///< case, the call is simply ignored.
00270 
00271     virtual INLINE void     modify(int loc, T *replacement);
00272     ///< Modify the list by grabbing the locth element out of the
00273     ///< list and replacing it with 'replacement'.  If the locth
00274     ///< element is valid, it is deleted, if it is not valid,
00275     ///< 'replacement' takes the locth position.  'el' MAY be the
00276     ///< same element as teh locth element.  In this case, the call
00277     ///< is simply ignored.  This is the only method of revalidating
00278     ///< invalid nodes.
00279 
00280     virtual INLINE void     ins_first(const T *new_element);
00281     ///< Prepend new_element to the beginning of the list.
00282     ///< This results in an error for static lists.
00283 
00284     virtual INLINE void     ins_last(const T *new_element);
00285     ///< Append new_element to the end of the list.
00286     ///< This results in an error for staic lists.
00287 
00288     virtual INLINE void     ins_before(const T *new_element, const T *ref);
00289     ///< Insert new_element before the reference element 'ref'
00290     ///< (if ref == 0, insert at END of list).
00291     ///< ref MUST be in the list (this is not necessarily
00292     ///< checked).
00293     ///< This results in an error for staic lists.
00294 
00295     virtual INLINE void     ins_after(const T *new_element, const T *ref);
00296     ///< Insert new_element after the reference element 'ref'
00297     ///< (if ref == 0, insert at BEGINNING of list).
00298     ///< ref MUST be in the list (this is not necessarily
00299     ///< checked).
00300     ///< This results in an error for staic lists.
00301 
00302     virtual INLINE T        *pull(int loc);
00303     ///< Temporarily remove the locth element from the list so that
00304     ///< it can be operated on by assign and replaced.  The pulled
00305     ///< element must be replaced using an assign call which must be
00306     ///< on the same line.  See detailed description in the above
00307     ///< section "Assign Operation".
00308 
00309     virtual INLINE T        *pull(T &el);
00310     ///< Temporarily remove the element el from the list so that
00311     ///< it can be operated on by assign and replaced.  The pulled
00312     ///< element must be replaced using an assign call which must be
00313     ///< on the same line.  See detailed description in the 
00314     ///< section "Assign Operation".
00315 
00316     virtual INLINE Assign<T> assign(int loc);
00317     ///< Return control of a pulled element to its list in its original
00318     ///< position.  The assign call must be on the same line as the pull
00319     ///< operation. See detailed description in the 
00320     ///< section "Assign Operation".
00321 
00322     virtual INLINE Assign<T> assign(T &el);
00323     ///< Return control of a pulled element to its list in its original
00324     ///< position.  The assign call must be on the same line as the pull
00325     ///< operation. See detailed description in the above
00326     ///< section "Assign Operation".
00327 
00328     INLINE const T *next_ref(const T &el) const;
00329     INLINE T       *next_ref(const T &el);
00330     ///< Return the element after 'el' (return 0 if none).
00331 
00332     INLINE const T *prev_ref(const T &el) const;
00333     INLINE T       *prev_ref(const T &el);
00334     ///< Return the element before 'el' (return 0 if none).
00335 
00336     INLINE const T *first_ref() const;
00337     INLINE T       *first_ref();
00338     ///< Return the first element.
00339     ///< Run-time error if none (i.e. the list is empty).
00340 
00341     INLINE const T *last_ref() const;
00342     INLINE T       *last_ref();
00343     ///< Return the last element.
00344     ///< Run-time error if none (i.e. the list is empty).
00345 
00346     INLINE Boolean  valid(int loc) const;
00347     ///< is the locth element valid?
00348 
00349     virtual INLINE void     clear();
00350     ///< Delete the entire list and, for static lists, set all
00351     ///< entries to invalid.
00352 
00353     virtual INLINE  List<T> &operator = (const List<T> &l);
00354     ///< Copy operator copies all elements of a list
00355     ///< If the LHS list is static, the RHS list must be of
00356     ///< equal or smaller size and the LHS list will be padded
00357     ///< with invalid nodes.
00358 
00359     virtual INLINE int structures_OK() const;
00360     ///< Check the structure of the data for errors or inconsistency
00361     ///< Return 0 and print error message if problems found, otherwise
00362     ///< return 1 without message.
00363 
00364     virtual INLINE Listable *listable_clone() const;
00365     ///< Needed for Listable class.
00366     
00367     virtual INLINE void print(ostream &o) const;
00368     ///< Needed for Listable class.
00369 
00370 };
00371 
00372 
00373 ///< implementation
00374 
00375 template <class T>
00376 INLINE 
00377 List<T>::List()
00378 {
00379     ///< nothing to do
00380 }
00381 
00382 template <class T>
00383 INLINE
00384 List<T>::List(const List<T> &l)
00385 {
00386     _list = l._list;
00387 }
00388 
00389 template <class T>
00390 INLINE 
00391 List<T>::List(unsigned static_sz)
00392 {
00393     _list.make_static_list(static_sz);
00394 }
00395 
00396 template <class T>
00397 INLINE void
00398 List<T>::make_static_list ( int static_size )
00399 {
00400     _list.make_static_list ( static_size );
00401 }
00402 
00403 template <class T>
00404 INLINE 
00405 List<T>::~List()
00406 {
00407     ///< nothing to do
00408 }
00409 
00410 template <class T>
00411 INLINE
00412 List<T>::List(const T *el1, const T *el2 GIV(0))
00413 {
00414     _list.ins(el1, 0);
00415 
00416     if (el2)
00417         _list.ins(el2, 1);
00418 
00419     _list.fix_size();
00420 }
00421 
00422 template <class T>
00423 INLINE int     
00424 List<T>::entries() const
00425 {
00426     return _list.entries();
00427 }
00428 
00429 template <class T>
00430 INLINE Boolean  
00431 List<T>::static_size() const
00432 {
00433     return _list.static_size();
00434 }
00435 
00436 template <class T>
00437 INLINE void     
00438 List<T>::fix_size()
00439 {
00440     _list.fix_size();
00441 }
00442 
00443 template <class T>
00444 INLINE void     
00445 List<T>::unfix_size()
00446 {
00447     _list.unfix_size();
00448 }
00449 
00450 template <class T>
00451 INLINE const T &
00452 List<T>::operator[] (int sub) const
00453 {
00454     return (const T &) _list[sub];
00455 }
00456 
00457 template <class T>
00458 INLINE T &
00459 List<T>::operator[] (int sub)
00460 {
00461     return (T &) _list[sub];
00462 }
00463 
00464 template <class T>
00465 INLINE void
00466 List<T>::print(ostream & out, char *sep) const
00467 {
00468     _list.print(out, sep);
00469 }
00470 
00471 template <class T>
00472 INLINE void     
00473 List<T>::ins(const T *new_element, int loc)
00474 {
00475     _list.ins(new_element, loc);
00476 }
00477 
00478 template <class T>
00479 INLINE void     
00480 List<T>::del(int loc)
00481 {
00482     _list.del(loc);
00483 }
00484 
00485 template <class T>
00486 INLINE void     
00487 List<T>::del(T &el)
00488 {
00489     _list.del(el);
00490 }
00491 
00492 template <class T>
00493 INLINE T *
00494 List<T>::grab(int loc)
00495 {
00496     return (T *) _list.grab(loc);
00497 }
00498 
00499 template <class T>
00500 INLINE T *
00501 List<T>::grab(T &el)
00502 {
00503     return (T *) _list.grab( el );
00504 }
00505 
00506 template <class T>
00507 INLINE void     
00508 List<T>::ins_first(const T *new_element)
00509 {
00510     _list.ins(new_element, 0);
00511 }
00512 
00513 template <class T>
00514 INLINE void     
00515 List<T>::ins_last(const T *new_element)
00516 {
00517     _list.ins(new_element, _list.entries());
00518 }
00519 
00520 template <class T>
00521 INLINE void     
00522 List<T>::ins_before(const T *new_element, const T *ref)
00523 {
00524     _list.ins_before(new_element, ref);
00525 }
00526 
00527 template <class T>
00528 INLINE void     
00529 List<T>::ins_after(const T *new_element, const T *ref)
00530 {
00531     _list.ins_after(new_element, ref);
00532 }
00533 
00534 template <class T>
00535 INLINE Assign<T>
00536 List<T>::assign(int loc)
00537 {
00538     Assign<T> a(_list.assign(loc));
00539     return a;
00540 }
00541 
00542 template <class T>
00543 INLINE Assign<T>
00544 List<T>::assign(T &el)
00545 {
00546     Assign<T> a(_list.assign(el));
00547     return  a;
00548 }
00549 
00550 template <class T>
00551 INLINE T *
00552 List<T>::pull(int loc)
00553 {
00554     return (T *) _list.pull(loc);
00555 }
00556 
00557 template <class T>
00558 INLINE T *
00559 List<T>::pull(T &el)
00560 {
00561     return (T *) _list.pull(el);
00562 }
00563 
00564 template <class T>
00565 INLINE const T *
00566 List<T>::next_ref(const T &el) const
00567 {
00568     return (const T *) _list.next_ref(el);
00569 }
00570 
00571 template <class T>
00572 INLINE T *
00573 List<T>::next_ref(const T &el)
00574 {
00575     return (T *) _list.next_ref(el);
00576 }
00577 
00578 template <class T>
00579 INLINE const T *
00580 List<T>::prev_ref(const T &el) const
00581 {
00582     return (const T *) _list.prev_ref(el);
00583 }
00584 
00585 template <class T>
00586 INLINE T *
00587 List<T>::prev_ref(const T &el)
00588 {
00589     return (T *) _list.prev_ref(el);
00590 }
00591 
00592 template <class T>
00593 INLINE const T *
00594 List<T>::first_ref() const
00595 {
00596     return (const T *) _list.first_ref();
00597 }
00598 
00599 template <class T>
00600 INLINE T *
00601 List<T>::first_ref()
00602 {
00603     return (T *) _list.first_ref();
00604 }
00605 
00606 template <class T>
00607 INLINE const T *
00608 List<T>::last_ref() const
00609 {
00610     return (const T *) _list.last_ref();
00611 }
00612 
00613 template <class T>
00614 INLINE T *
00615 List<T>::last_ref()
00616 {
00617     return (T *) _list.last_ref();
00618 }
00619 
00620 template <class T>
00621 INLINE Boolean  
00622 List<T>::valid(int loc) const
00623 {
00624     return _list.valid(loc);
00625 }
00626 
00627 template <class T>
00628 INLINE void     
00629 List<T>::clear()
00630 {
00631     _list.clear();
00632 }
00633 
00634 template <class T>
00635 INLINE List<T> &
00636 List<T>::operator = (const List<T> &l) 
00637 {
00638     _list = l._list;
00639     return *this;
00640 }
00641 
00642 template <class T>
00643 INLINE int      
00644 List<T>::structures_OK() const
00645 {
00646     return _list.structures_OK();
00647 }
00648 
00649 template <class T>
00650 INLINE T *
00651 List<T>::modify_and_grab(T &el, T *replacement)
00652 {
00653     return (T *) _list.modify_and_grab(el, replacement);
00654 }
00655 
00656 template <class T>
00657 INLINE void     
00658 List<T>::modify(T &el, T *replacement)
00659 {
00660     _list.modify(el, replacement);
00661 }
00662 
00663 template <class T>
00664 INLINE void     
00665 List<T>::modify(int loc, T *replacement)
00666 {
00667     _list.modify(loc, replacement);
00668 }
00669 
00670 template <class T>
00671 INLINE const Collection &
00672 List<T>::_base_collection() const
00673 {
00674     return _list;
00675 }
00676 
00677 template <class T>
00678 INLINE Collection &
00679 List<T>::_base_collection()
00680 {
00681     return _list;
00682 }
00683 
00684 template <class T>
00685 INLINE Listable *
00686 List<T>::listable_clone() const
00687 {
00688     return (Listable *) new List<T>(*this);
00689 }
00690 
00691 template <class T>
00692 INLINE void
00693 List<T>::print(ostream &o) const
00694 {
00695     print(o, ", ");
00696 }
00697 
00698 template <class T>
00699 INLINE int      
00700 List<T>::index(const T &el) const
00701 {
00702     return _list.index( el );
00703 }
00704 
00705 template <class T>
00706 INLINE Boolean  
00707 List<T>::member(const T &el) const
00708 {
00709     return _list.member( el );
00710 }
00711 
00712 ///< This interface is for testing purposes only.  It prints the BaseList
00713 ///< (with wrapper information), and, since it is not a class member
00714 ///< function, it must be explicitly instantiated before use.
00715 
00716 template <class T>
00717 ostream &
00718 operator << (ostream & o, const List<T> &l)
00719 {
00720   ///< return o << l._list;
00721   ///< -> 
00722   l.print( o );
00723   return o; 
00724 }
00725 
00726 #endif
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:05:58 2005