00001 /* 00002 * 00003 * Copyright (C) 1997-2005, OFFIS 00004 * 00005 * This software and supporting documentation were developed by 00006 * 00007 * Kuratorium OFFIS e.V. 00008 * Healthcare Information and Communication Systems 00009 * Escherweg 2 00010 * D-26121 Oldenburg, Germany 00011 * 00012 * THIS SOFTWARE IS MADE AVAILABLE, AS IS, AND OFFIS MAKES NO WARRANTY 00013 * REGARDING THE SOFTWARE, ITS PERFORMANCE, ITS MERCHANTABILITY OR 00014 * FITNESS FOR ANY PARTICULAR USE, FREEDOM FROM ANY COMPUTER DISEASES OR 00015 * ITS CONFORMITY TO ANY SPECIFICATION. THE ENTIRE RISK AS TO QUALITY AND 00016 * PERFORMANCE OF THE SOFTWARE IS WITH THE USER. 00017 * 00018 * Module: ofstd 00019 * 00020 * Author: Andreas Barth 00021 * 00022 * Purpose: 00023 * Defines a template list class with interfaces similar to the C++ Standard 00024 * 00025 * Last Update: $Author: meichel $ 00026 * Update Date: $Date: 2005/12/08 16:05:58 $ 00027 * Source File: $Source: /share/dicom/cvs-depot/dcmtk/ofstd/include/dcmtk/ofstd/oflist.h,v $ 00028 * CVS/RCS Revision: $Revision: 1.22 $ 00029 * Status: $State: Exp $ 00030 * 00031 * CVS/RCS Log at end of file 00032 * 00033 */ 00034 00035 #ifndef OFLIST_H 00036 #define OFLIST_H 00037 00038 // Usage (only non standard): 00039 // OFListInsert(InputIterator_type, T_type, c, pos, first, last) 00040 // Inserts the elements of type T in 00041 // range [first, last) into list c, 00042 // OFListRemoveIf(Predicate_Type, T_type, c, pred) 00043 // Erases all elements of type T in the list referred by 00044 // an iterator i where pred(*i) == true. 00045 // Predicate_Type is the function type of pred 00046 // 00047 // Additional Remarks: 00048 // In some template functions one template parameter is another function. 00049 // Some compilers cannot determine automatically the type of template 00050 // function parameters, so you must give them a hint casting 00051 // the parameter function to the correct type (e.g. NeXT gcc 2.5.8) 00052 00053 #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ 00054 #include "dcmtk/ofstd/oftypes.h" 00055 #include "dcmtk/ofstd/ofcast.h" 00056 00057 #ifndef HAVE_CLASS_TEMPLATE 00058 #error Your C++ compiler cannot handle class templates: 00059 #endif 00060 00061 #if defined(HAVE_STL) || defined(HAVE_STL_LIST) 00062 // It is possible to use the standard template library list class since the 00063 // interface is nearly identical. 00064 // Important: If you want to use the standard template library (STL), no 00065 // variable within a namespace using a class of the STL shall have a name 00066 // of one class of the STL 00067 #include <list> 00068 00069 #ifdef HAVE_STD_NAMESPACE 00070 #define OFList std::list 00071 #define OFListIterator(x) std::list< x >::iterator 00072 #define OFListConstIterator(x) std::list< x >::const_iterator 00073 #else 00074 #define OFList list 00075 #define OFListIterator(x) list< x >::iterator 00076 #define OFListConstIterator(x) list< x >::const_iterator 00077 #endif 00078 00079 #define OFListInsert(InputIterator, T, c, pos, first, last) (c).insert((pos), (first), (last)) 00080 #define OFListRemoveIf(Predicate, T, c, pred) (c).remove_if((pred)) 00081 00082 // workaround for "implicit typename" warning on gcc 3.x 00083 #if defined(HAVE_TYPENAME) 00084 #define OFLIST_TYPENAME typename 00085 #else 00086 #define OFLIST_TYPENAME 00087 #endif 00088 00089 #else 00090 00091 #define INCLUDE_CASSERT 00092 #define INCLUDE_CSTDDEF 00093 #include "dcmtk/ofstd/ofstdinc.h" 00094 00095 #define OFLIST_TYPENAME 00096 00097 00098 // OFListLinkBase, OFListLink and OFListBase are classes for internal 00099 // use only and shall not be used. 00100 00101 /* non-template double linked list. Base class fo OFListLink. 00102 * Implicitly used by OFList, should not be called by users. 00103 */ 00104 struct OFListLinkBase 00105 { 00106 OFListLinkBase * next; 00107 OFListLinkBase * prev; 00108 OFBool dummy; 00109 OFListLinkBase(): next(NULL), prev(NULL), dummy(OFFalse) { } 00110 virtual ~OFListLinkBase() {} 00111 00112 private: 00113 /* undefined */ OFListLinkBase(const OFListLinkBase&); 00114 /* undefined */ OFListLinkBase& operator=(const OFListLinkBase&); 00115 }; 00116 00117 00118 /* non-template list. Base class fo OFList. 00119 * Implicitly used by OFList, should not be called by users. 00120 */ 00121 class OFListBase 00122 { 00123 protected: 00124 OFListLinkBase * afterLast; 00125 size_t listSize; 00126 void base_recalcListSize(); 00127 public: 00128 OFListBase(); 00129 virtual ~OFListBase(); 00130 OFListLinkBase * base_begin() const { return afterLast->next; } 00131 OFListLinkBase * base_end() const { return afterLast; } 00132 OFBool base_empty() const { return afterLast == afterLast->next; } 00133 size_t base_size() const { return listSize; } 00134 OFListLinkBase * base_insert(OFListLinkBase * pos, OFListLinkBase * newElem); 00135 OFListLinkBase * base_erase(OFListLinkBase * pos); 00136 void base_splice(OFListLinkBase * pos, 00137 OFListLinkBase * begin, OFListLinkBase * end); 00138 void base_clear(); 00139 00140 private: 00141 /* undefined */ OFListBase(const OFListBase&); 00142 /* undefined */ OFListBase& operator=(const OFListBase&); 00143 }; 00144 00145 00146 00147 /* template class for double linked list entries. 00148 * Implicitly used by OFList, should not be called by users. 00149 */ 00150 template <class T> 00151 struct OFListLink : public OFListLinkBase 00152 { 00153 T info; 00154 OFListLink(const T& i) : OFListLinkBase(), info(i) { } 00155 virtual ~OFListLink() {} 00156 private: 00157 /* undefined */ OFListLink(const OFListLink<T>&); 00158 /* undefined */ OFListLink<T>& operator=(const OFListLink<T>&); 00159 }; 00160 00161 00162 // Definition of OFList and OFIterator 00163 00164 template <class T> class OFList; 00165 00166 00173 template <class T> 00174 class OFIterator 00175 { 00176 friend class OFList<T>; 00177 protected: 00178 00180 OFListLinkBase * node; 00181 00185 OFIterator(OFListLinkBase * x) : node(x) { } 00186 public: 00187 00192 OFIterator() : node(NULL) { } 00193 00196 OFIterator(const OFIterator<T>& x) : node(x.node) { }; 00197 00200 OFIterator<T>& operator=(const OFIterator<T>& x) 00201 { 00202 node = x.node; 00203 return *this; 00204 } 00205 00211 OFBool operator==(const OFIterator<T>& x) const { return node == x.node; } 00212 00218 OFBool operator!=(const OFIterator<T>& x) const { return node != x.node; } 00219 00224 T& operator*() const 00225 { 00226 assert(!node->dummy); 00227 return (OFstatic_cast(OFListLink<T> *,node))->info; 00228 } 00229 00235 OFIterator<T>& operator++() 00236 { 00237 node = node->next; 00238 return *this; 00239 } 00240 00247 OFIterator<T> operator++(int) 00248 { 00249 OFIterator<T> tmp(*this); 00250 node = node->next; 00251 return tmp; 00252 } 00253 00259 OFIterator<T>& operator--() 00260 { 00261 node = node->prev; 00262 return *this; 00263 } 00264 00271 OFIterator<T> operator--(int) 00272 { 00273 OFIterator<T> tmp(*this); 00274 node = node->prev; 00275 return tmp; 00276 } 00277 }; 00278 00279 00283 template <class T> 00284 class OFList : private OFListBase 00285 { 00286 public: 00292 OFIterator<T> insert(OFIterator<T> position, const T& x) 00293 { 00294 return OFIterator<T>(OFListBase::base_insert(position.node, new OFListLink<T>(x))); 00295 } 00296 00297 private: 00298 00302 void copy(const OFList<T>& oldList) 00303 { 00304 OFIterator<T> vfirst(oldList.begin()); 00305 OFIterator<T> vend(oldList.end()); 00306 OFIterator<T> vpos(this->end()); 00307 while (vfirst != vend) 00308 { 00309 insert(vpos, *vfirst); 00310 ++vfirst; 00311 } 00312 } 00313 00317 void recalcListSize() { OFListBase::base_recalcListSize(); } 00318 00319 public: 00320 00323 OFList() : OFListBase() { } 00324 00327 OFList(const OFList<T>& oldList):OFListBase() 00328 { 00329 copy(oldList); 00330 } 00331 00336 OFIterator<T> begin() const { return OFIterator<T>(OFListBase::base_begin()); } 00337 00342 OFIterator<T> end() const { return OFIterator<T>(OFListBase::base_end()); } 00343 00347 OFBool empty() const { return OFListBase::base_empty(); } 00348 00352 size_t size() const { return OFListBase::base_size(); } 00353 00358 T& front() { return *begin(); } 00359 00364 T& back() { return *(--end()); } 00365 00369 void push_front(const T& x) { insert(begin(), OFconst_cast(T&, x)); } 00370 /* const cast away to keep some old compilers happy */ 00371 00376 void pop_front() { erase(begin()); } 00377 00381 void push_back(const T& x) { insert(end(), OFconst_cast(T&, x)); } 00382 /* const cast away to keep some old compilers happy */ 00383 00388 void pop_back() { erase(--end()); } 00389 00395 void insert(OFIterator<T> position, size_t n, const T& x) 00396 { 00397 while(n--) OFListBase::base_insert(position.node, new OFListLink<T>(x)); 00398 } 00399 00404 OFIterator<T> erase(OFIterator<T> position) 00405 { 00406 return OFIterator<T>(OFListBase::base_erase(position.node)); 00407 } 00408 00415 OFIterator<T> erase(OFIterator<T> position, OFIterator<T> last) 00416 { 00417 while (position != last) position = erase(position); 00418 return last; 00419 } 00420 00424 void clear() { OFListBase::base_clear(); } 00425 00431 void splice(OFIterator<T> position, OFList<T>& x) 00432 { 00433 splice(position, x, x.begin(), x.end()); 00434 } 00435 00441 void splice(OFIterator<T> position, OFList<T>& x, OFIterator<T> i) 00442 { 00443 OFIterator<T> change(i); 00444 ++i; 00445 splice(position, x, change, i); 00446 } 00447 00455 void splice(OFIterator<T> position, OFList<T>& x, 00456 OFIterator<T> first, OFIterator<T> last) 00457 { 00458 OFListBase::base_splice(position.node, first.node, last.node); 00459 x.recalcListSize(); 00460 } 00461 00466 void remove(const T& value) 00467 { 00468 OFIterator<T> first = begin(); 00469 OFIterator<T> last = end(); 00470 while(first != last) 00471 { 00472 if (*first == value) first = erase(first); 00473 else ++first; 00474 } 00475 } 00476 00477 private: 00478 00481 OFList<T>& operator=(const OFList<T>& arg); 00482 }; 00483 00484 00485 #ifdef HAVE_FUNCTION_TEMPLATE 00486 00487 #define OFListInsert(InputIterator, T, c, pos, first, last) OF_ListInsert((c), (pos), (first), (last)) 00488 00489 #define OFListRemoveIf(Predicate, T, c, pred) OF_ListRemoveIf((c), (pred)) 00490 00491 #elif defined(HAVE_STATIC_TEMPLATE_METHOD) 00492 00493 #define OFListInsert(InputIterator, T, c, pos, first, last) OF_ListInsertClass<InputIterator, T>::OF_ListInsert((c), (pos), (first), (last)) 00494 00495 #define OFListRemoveIf(Predicate, T, c, pred) OF_ListRemoveIfClass<Predicate, T>::OF_ListRemoveIf((c), (pred)) 00496 00497 #else 00498 #error Your C++ Compiler is not capable of compiling this code 00499 #endif 00500 00501 // Insert the elements in range [first, last) into list 00502 template <class InputIterator, class T> 00503 #if defined(HAVE_STATIC_TEMPLATE_METHOD) && !defined(HAVE_FUNCTION_TEMPLATE) 00504 class OF_ListInsertClass 00505 { 00506 public: 00507 static 00508 #endif 00509 void OF_ListInsert(OFList<T>& c, OFIterator<T> position, 00510 InputIterator first, InputIterator last) 00511 { 00512 while(first != last) 00513 { 00514 c.insert(position, *first); 00515 ++first; 00516 } 00517 } 00518 #if defined(HAVE_STATIC_TEMPLATE_METHOD) && !defined(HAVE_FUNCTION_TEMPLATE) 00519 }; 00520 #endif 00521 00522 // Erases all elements in the list referred by an iterator i where 00523 // pred(*i) == true 00524 template <class Predicate, class T> 00525 #if defined(HAVE_STATIC_TEMPLATE_METHOD) && !defined(HAVE_FUNCTION_TEMPLATE) 00526 class OF_ListRemoveIfClass 00527 { 00528 public: 00529 static 00530 #endif 00531 void OF_ListRemoveIf(OFList<T>& c, Predicate pred) 00532 { 00533 OFIterator<T> first = c.begin(); 00534 OFIterator<T> last = c.end(); 00535 while (first != last) 00536 { 00537 if (pred(*first)) 00538 first = c.erase(first); 00539 else 00540 ++first; 00541 } 00542 } 00543 00544 #if defined(HAVE_STATIC_TEMPLATE_METHOD) && !defined(HAVE_FUNCTION_TEMPLATE) 00545 }; 00546 #endif 00547 00548 #define OFListIterator(x) OFIterator< x > 00549 #define OFListConstIterator(x) OFIterator< x > 00550 00551 #endif 00552 00553 #endif 00554 00555 /* 00556 ** CVS/RCS Log: 00557 ** $Log: oflist.h,v $ 00558 ** Revision 1.22 2005/12/08 16:05:58 meichel 00559 ** Changed include path schema for all DCMTK header files 00560 ** 00561 ** Revision 1.21 2004/04/14 11:44:48 joergr 00562 ** Replaced non-Unix newline characters. 00563 ** 00564 ** Revision 1.20 2003/08/07 11:44:55 joergr 00565 ** Slightly modified header comments to conform to doxygen syntax. 00566 ** 00567 ** Revision 1.19 2003/07/11 13:46:14 joergr 00568 ** Added workaround to get rid of "implicit typename" warnings on gcc 3.x 00569 ** (introduced macro OFLIST_TYPENAME). 00570 ** 00571 ** Revision 1.18 2003/07/09 13:57:43 meichel 00572 ** Adapted type casts to new-style typecast operators defined in ofcast.h 00573 ** 00574 ** Revision 1.17 2003/06/12 15:20:30 joergr 00575 ** Slightly modified macro definitions to avoid potential parser errors (added 00576 ** space character after '<' and before '>'). 00577 ** 00578 ** Revision 1.16 2003/06/12 13:21:54 joergr 00579 ** Introduced macro OFListConstIterator() to support STL const_iterators. 00580 ** 00581 ** Revision 1.15 2003/06/03 10:20:00 meichel 00582 ** OFList now explicitly defined as std::list if std namespace present 00583 ** 00584 ** Revision 1.14 2002/11/27 11:23:05 meichel 00585 ** Adapted module ofstd to use of new header file ofstdinc.h 00586 ** 00587 ** Revision 1.13 2001/08/23 16:05:52 meichel 00588 ** Added private undefined copy assignment operators to avoid gcc warnings 00589 ** 00590 ** Revision 1.12 2001/06/01 15:51:34 meichel 00591 ** Updated copyright header 00592 ** 00593 ** Revision 1.11 2000/10/10 12:01:21 meichel 00594 ** Created/updated doc++ comments 00595 ** 00596 ** Revision 1.10 2000/03/08 16:36:02 meichel 00597 ** Updated copyright header. 00598 ** 00599 ** Revision 1.9 1998/11/27 12:42:51 joergr 00600 ** Added copyright message to source files and changed CVS header. 00601 ** 00602 ** Revision 1.8 1998/07/02 07:47:02 meichel 00603 ** Some code purifications to avoid gcc 2.8.1 -Weffc++ warnings. 00604 ** 00605 ** Revision 1.7 1998/06/29 12:09:23 meichel 00606 ** Removed some name clashes (e.g. local variable with same 00607 ** name as class member) to improve maintainability. 00608 ** Applied some code purifications proposed by the gcc 2.8.1 -Weffc++ option. 00609 ** 00610 ** Revision 1.6 1998/02/06 15:07:38 meichel 00611 ** Removed many minor problems (name clashes, unreached code) 00612 ** reported by Sun CC4 with "+w" or Sun CC2. 00613 ** 00614 ** Revision 1.5 1997/11/10 16:31:19 meichel 00615 ** Corrected bug possibly causing a memory leak in OFList. 00616 ** Added virtual destructors to classes OFListLinkBase and OFListLink. 00617 ** 00618 ** Revision 1.4 1997/09/11 15:43:15 hewett 00619 ** Minor changes to eliminate warnings when compiled under the 00620 ** Signus GnuWin32 envionment. Changed order of initialisers 00621 ** for OFListLink and OFStackLink. Make ~OFLisBase and ~OFStackBase 00622 ** virtual destructors. 00623 ** 00624 ** Revision 1.3 1997/07/24 13:11:00 andreas 00625 ** - Removed Warnings from SUN CC 2.0.1 00626 ** 00627 ** Revision 1.2 1997/07/07 07:34:18 andreas 00628 ** - Corrected destructor for OFListBase, now the dummy element is 00629 ** deleted. 00630 ** 00631 ** Revision 1.1 1997/07/02 11:51:14 andreas 00632 ** - Preliminary release of the OFFIS Standard Library. 00633 ** In the future this library shall contain a subset of the 00634 ** ANSI C++ Library (Version 3) that works on a lot of different 00635 ** compilers. Additionally this library shall include classes and 00636 ** functions that are often used. All classes and functions begin 00637 ** with OF... This library is independent of the DICOM development and 00638 ** shall contain no DICOM specific stuff. 00639 ** 00640 ** 00641 */