| Polaris: List.h Source File | ||
|
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members
List.hGo 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 |
||
|