Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

ParmParse.H

Go to the documentation of this file.
00001 /* _______              __
00002   / ___/ /  ___  __ _  / /  ___
00003  / /__/ _ \/ _ \/  ' \/ _ \/ _ \
00004  \___/_//_/\___/_/_/_/_.__/\___/ 
00005 */
00006 //
00007 // This software is copyright (C) by the Lawrence Berkeley
00008 // National Laboratory.  Permission is granted to reproduce
00009 // this software for non-commercial purposes provided that
00010 // this notice is left intact.
00011 // 
00012 // It is acknowledged that the U.S. Government has rights to
00013 // this software under Contract DE-AC03-765F00098 between
00014 // the U.S.  Department of Energy and the University of
00015 // California.
00016 //
00017 // This software is provided as a professional and academic
00018 // contribution for joint exchange. Thus it is experimental,
00019 // is provided ``as is'', with no warranties of any kind
00020 // whatsoever, no support, no promise of updates, or printed
00021 // documentation. By using this software, you acknowledge
00022 // that the Lawrence Berkeley National Laboratory and
00023 // Regents of the University of California shall have no
00024 // liability with respect to the infringement of other
00025 // copyrights by any part of this software.
00026 //
00027 
00028 /*
00029   DISCLAIMER:
00030   This is ugly because it consists of four files from boxlib
00031   concatenated together and munged hopelessly.  This was done
00032   (1) to greatly reduce the size of the API of boxlib
00033   (2) to avoid the godawful task of rewriting parmparse
00034   (3) to avoid cluttering the global namespace
00035   We deeply apologize.
00036 
00037   Any class that begins with PP_ is a convenience
00038   and will not be in any way supported by anyone at ANAG.
00039  */
00040 
00041 #ifndef CH_PARMPARSE_H
00042 #define CH_PARMPARSE_H
00043 
00044 #include <iostream>
00045 #include <iomanip>
00046 #include <cstdlib>
00047 #include <string>
00048 #include <vector>
00049 
00050 #include <cassert>
00051 #include "MayDay.H"
00052 #include "Misc.H"
00053 #include "Vector.H"
00054 using std::cout;
00055 using std::cerr;
00056 using std::endl;
00057 //#include <aString.H>
00058 
00059 //#include <Pointers.H>
00060 
00061 //#include <UseCount.H>
00062 
00063 
00064 //
00065 //@Man:
00066 //@Memo: A Class Encapsulating Reference Counts for ParmParse
00067 /*@Doc:
00068 
00069   This class encapsulates reference counts.  
00070 
00071   This is a convenience class for ParmParse
00072   and will not be in any way supported by anyone at ANAG.
00073 */
00074 
00075 class PP_UseCount
00076 {
00077 public:
00078     //
00079     //@ManDoc: Construct a PP_UseCount initialized to one.
00080     //
00081     PP_UseCount ();
00082     //
00083     //@ManDoc: The copy constructor -- bumps reference count.
00084     //
00085     PP_UseCount (const PP_UseCount& rhs);
00086 
00087     /*@ManDoc: The assignment operator.  Increments the reference count on
00088                rhs, decrements the reference count on this, and then makes
00089                this and rhs point to the same reference count.
00090     */
00091     PP_UseCount& operator= (const PP_UseCount& rhs);
00092     //
00093     //@ManDoc: The destructor -- decrements the reference count.
00094     //
00095     ~PP_UseCount ();
00096     //
00097     //@ManDoc: The PP_UseCount is unique if the reference count == 1.
00098     //
00099     bool unique () const;
00100     //
00101     //@ManDoc: Returns the reference count.
00102     //
00103     int linkCount () const;
00104 
00105 private:
00106     //
00107     // A pointer to the reference count.
00108     //
00109     unsigned int* cnt;
00110     //
00111     // Decrement the reference count and delete the reference
00112     // counter if there are no more references.
00113     //
00114     void decrement ();
00115 };
00116 
00117 //
00118 // Inlines.
00119 //
00120 
00121 inline
00122 PP_UseCount::PP_UseCount ()
00123     :
00124     cnt(new unsigned int(1))
00125 {}
00126 
00127 inline
00128 PP_UseCount::PP_UseCount (const PP_UseCount& rhs)
00129     :
00130     cnt(rhs.cnt)
00131 {
00132     ++*cnt;
00133 }
00134 
00135 inline
00136 bool
00137 PP_UseCount::unique () const
00138 {
00139     return *cnt == 1;
00140 }
00141 
00142 inline
00143 void
00144 PP_UseCount::decrement ()
00145 {
00146     if (unique())
00147     {
00148         delete cnt;
00149         cnt = 0;
00150     }
00151     else
00152         --*cnt;
00153 }
00154 
00155 inline
00156 PP_UseCount&
00157 PP_UseCount::operator= (const PP_UseCount& rhs)
00158 {
00159     ++*rhs.cnt;
00160     decrement();
00161     cnt = rhs.cnt;
00162     return *this;
00163 }
00164 
00165 inline
00166 PP_UseCount::~PP_UseCount ()
00167 {
00168     decrement();
00169 }
00170 
00171 inline
00172 int
00173 PP_UseCount::linkCount () const
00174 {
00175     return *cnt;
00176 }
00177 
00178 
00179 
00180 //
00181 //@Man:
00182 //@Memo: A Smart Pointer for Intrinsic or User-Defined Types for ParmParse
00183 /*@Doc:
00184 
00185   The template class PP_CpPtr<T> provides a simple wrapper around a pointer
00186   to type T (T*) that builds a copy of the pointed-to object when copied
00187   from one PP_CpPtr<T> to another.  This is in contrast to a reference-counted
00188   pointer class that would maintain one pointed-to object with a reference
00189   count indicating the number of references.  Hence we call this a
00190   "copied" smart pointer class.  It is intended for use with any type
00191   type T, including the intrinsic types.  This class does not supply
00192   an operator->(), as such an operator on intrinsic types has only recently
00193   become a part of the C++ language, and many compilers do not yet implement
00194   it.
00195 
00196   This is a convenience class  for ParmParse
00197   and will not be in any way supported by anyone at ANAG.
00198 */
00199 
00200 template <class T>
00201 class PP_CpPtr
00202 {
00203 public:
00204     //
00205     //@ManDoc: The default constructor.  The wrapped pointer is null.
00206     //
00207     PP_CpPtr ();
00208     //
00209     //@ManDoc: Construct a PP_CpPtr<T> setting the wrapped pointer to rhs.
00210     //
00211     /*explicit*/ PP_CpPtr (T* rhs);
00212     //
00213     //@ManDoc: The destructor.  Deletes the wrapped pointer.
00214     //
00215     ~PP_CpPtr ();
00216 
00217     /*@ManDoc: The copy constructor.  If the pointer wrapped by rhs is null,
00218                the wrapped pointer is null here as well.  Otherwise,
00219                the contained pointer here is set to a new'd copy of that
00220                wrapped by rhs, with the two pointed-to values being identical.
00221                This assumes that type T has a well-defined and accessible copy
00222                constructor.  T must also be a concrete type, not a abstract
00223                type.
00224     */
00225     PP_CpPtr (const PP_CpPtr<T>& rhs);
00226 
00227     /*@ManDoc: Sets the wrapped pointer to rhs.  Deletes the previously
00228                wrapped pointer.
00229     */
00230     PP_CpPtr<T>& operator= (T* rhs);
00231 
00232     /*@ManDoc: The copy assignment operator.  If the pointer wrapped by rhs
00233                is null, the wrapped pointer is null here as well.  Otherwise,
00234                the contained pointer here is set to a new'd copy of that
00235                wrapped by rhs, with the two pointed-to values being identical.
00236                This assumes that type T has a well-defined and accessible copy
00237                constructor.  T must also be a concrete type, not a abstract
00238                type.
00239     */
00240     PP_CpPtr<T>& operator= (const PP_CpPtr<T>& rhs);
00241 
00242     /*@ManDoc: Returns a reference to the value pointed to by the wrapped
00243                pointer; i.e. dereferencing this PP_CpPtr<T>, returns the
00244                dereferenced wrapped pointer.  It is an error if the wrapped
00245                pointer is null.
00246     */
00247     T& operator* () const;
00248     //
00249     //@ManDoc: Returns true if the wrapped pointer null.
00250     //
00251     bool isNull () const;
00252     //
00253     //@ManDoc: Sets the wrapped pointer to null and returns the previous value.
00254     //
00255     T* release ();
00256     //
00257     //@ManDoc: Are the two pointers (not the values to which they point) equal?
00258     //
00259     bool operator== (const PP_CpPtr<T>& rhs) const;
00260     //
00261     //@ManDoc: Are the two pointers not equal?
00262     //
00263     bool operator!= (const PP_CpPtr<T>& rhs) const;
00264 
00265 protected:
00266     T* ptr;
00267 };
00268 
00269 //
00270 //@Man:
00271 //@Memo: A Smart Pointer for User-Defined Types for ParmParse
00272 /*@Doc:
00273 
00274   The template class PP_CpClassPtr<T> is derived from PP_CpPtr<T>.  It provides a
00275   simple wrapper around a pointer to type T (a T*) that "does the right thing"
00276   when copied from one PP_CpPtr<T> to another.  The type T MUST be a user-defined
00277   type, not an intrinsic type.  Given this restriction, we can supply
00278   an operator->().
00279 
00280 
00281   This is a convenience class  for ParmParse
00282   and will not be in any way supported by anyone at ANAG.
00283 */
00284 
00285 template<class T>
00286 class PP_CpClassPtr :
00287     public PP_CpPtr<T>
00288 {
00289 public:
00290     //
00291     //@ManDoc: The default constructor.  The wrapped pointer is null.
00292     //
00293     PP_CpClassPtr ();
00294     //
00295     //@ManDoc: Construct a PP_CpPtr<T> setting the wrapped pointer to rhs.
00296     //
00297     /*explicit*/ PP_CpClassPtr (T* rhs);
00298 
00299     /*@ManDoc: The copy constructor.  If the pointer wrapped by rhs is null,
00300                the wrapped pointer is null here as well.  Otherwise,
00301                the contained pointer here is set to a new'd copy of that
00302                wrapped by rhs, with the two pointed-to values being identical.
00303                This assumes that type T has a well-defined and accessible copy
00304                constructor.  T must also be a concrete type, not a abstract
00305                type.
00306     */
00307     PP_CpClassPtr (const PP_CpClassPtr<T>& rhs);
00308 
00309     /*@ManDoc: Sets the wrapped pointer to rhs.  Deletes the previously
00310                wrapped pointer.
00311     */
00312     PP_CpClassPtr<T>& operator= (T* rhs);
00313 
00314     /*@ManDoc: The copy assignment operator.  If the pointer wrapped by rhs
00315                is null, the wrapped pointer is null here as well.  Otherwise,
00316                the contained pointer here is set to a new'd copy of that
00317                wrapped by rhs, with the two pointed-to values being identical.
00318                This assumes that type T has a well-defined and accessible copy
00319                constructor.  T must also be a concrete type, not a abstract
00320                type.
00321     */
00322     PP_CpClassPtr<T>& operator= (const PP_CpClassPtr<T>& rhs);
00323     //
00324     //@ManDoc: Applies operator-> to the wrapped pointer.
00325     //
00326     T* operator-> () const;
00327 };
00328 
00329 //
00330 //@Man:
00331 //@Memo: A Reference Counted Smart Pointer for Intrinsic or User-Defined Types for ParmParse
00332 /*@Doc:
00333 
00334   The template class PP_LnPtr<T> provides a reference counted wrapper around a
00335   pointer to type T (a T*).  This "smart" pointer is intended for use with
00336   any type type T, including the intrinsic types.  For this reason, we do
00337   not supply an operator->(), as such an operator on intrinsic types has only
00338   recently become a part of the C++ language and many compilers do not yet
00339   implement it.
00340 
00341 
00342   This is a convenience class  for ParmParse
00343   and will not be in any way supported by anyone at ANAG.
00344 */
00345 
00346 template<class T>
00347 class PP_LnPtr
00348 {
00349 public:
00350     //
00351     //@ManDoc: The default constructor.  The wrapped pointer is null.
00352     //
00353     PP_LnPtr ();
00354     //
00355     //@ManDoc: Construct a PP_LnPtr<T> setting the wrapped pointer to rhs.
00356     //
00357     /*explicit*/ PP_LnPtr (T* rhs);
00358 
00359     /*@ManDoc: The copy assignment operator.  The contained pointer is set
00360                to the one wrapped by rhs.  The reference count is decremented
00361                on this object and the reference count is incremented for
00362                the newly wrapped pointer.
00363     */
00364     PP_LnPtr<T>& operator= (const PP_LnPtr<T>& rhs);
00365 
00366     /*@ManDoc: Sets the wrapped pointer to rhs.  Decrements the count
00367                on the previously wrapped pointer and deletes it if there
00368                was only one reference.
00369     */
00370     PP_LnPtr<T>& operator= (T* rhs)
00371     {
00372         //
00373         // This is inlined here as OCC won't have it any other way :-(
00374         //
00375         if (unique())
00376             delete ptr;
00377         ptr = rhs;
00378         ucnt = PP_UseCount();
00379         return *this;
00380     }
00381 
00382     /*@ManDoc: The destructor -- decrements the reference count and deletes
00383                the wrapped pointer if there is only one reference.
00384     */
00385     ~PP_LnPtr ();
00386     //
00387     //@ManDoc: Returns true if only one reference to the wrapped pointer.
00388     //
00389     bool unique () const;
00390     //
00391     //@ManDoc: Returns the number of references to the wrapped pointer.
00392     //
00393     int linkCount () const;
00394 
00395     /*@ManDoc: Returns a reference to the value pointed to by the wrapped
00396                pointer; i.e. dereferencing this PP_LnPtr<T>, returns the
00397                dereferenced wrapped pointer.  It is an error if the wrapped
00398                pointer is null.
00399     */
00400     T& operator* () const;
00401     //
00402     //@ManDoc: Returns true if the wrapped pointer is null.
00403     //
00404     bool isNull () const;
00405     //
00406     //@ManDoc: Are the two pointers (not the values to which they point) equal?
00407     //
00408     bool operator== (const PP_LnPtr<T>& rhs) const;
00409     //
00410     //@ManDoc: Are the two pointers not equal?
00411     //
00412      bool operator!= (const PP_LnPtr<T>& rhs) const;
00413 
00414 protected:
00415     T*       ptr;
00416 
00417 private:
00418     PP_UseCount ucnt;
00419 };
00420 
00421 //
00422 //@Man:
00423 //@Memo: A Smart Reference Counted Pointer for User-Defined Types for ParmParse
00424 /*@Doc:
00425 
00426   The template class PP_LnClassPtr<T> is derived from PP_LnPtr<T>.  It provides a
00427   reference counted wrapper around a pointer to type T (a T*).  The type T
00428   MUST be a user-defined type, not an intrinsic type.  Given this
00429   restriction, we can supply an operator->().
00430 
00431 
00432   This is a convenience class  for ParmParse
00433   and will not be in any way supported by anyone at ANAG.
00434 */
00435 
00436 template<class T>
00437 class PP_LnClassPtr
00438     : public PP_LnPtr<T>
00439 {
00440 public:
00441     //
00442     //@ManDoc: The default constructor.  The wrapped pointer is null.
00443     //
00444     PP_LnClassPtr ();
00445     //
00446     //@ManDoc: Construct a PP_LnPtr<T> setting the wrapped pointer to rhs.
00447     //
00448     /*explicit*/ PP_LnClassPtr (T* rhs);
00449 
00450     /*@ManDoc: The copy assignment operator.  The contained pointer is set
00451                to the one wrapped by rhs.  The reference count is decremented
00452                on this object and the reference count is incremented for
00453                the newly wrapped pointer.
00454     */
00455     PP_LnClassPtr<T>& operator= (const PP_LnClassPtr<T>& rhs);
00456 
00457     /*@ManDoc: Sets the wrapped pointer to rhs.  Decrements the count
00458                on the previously wrapped pointer and deletes it if there
00459                was only one reference.
00460     */
00461     PP_LnClassPtr<T>& operator= (T* rhs);
00462     //
00463     //@ManDoc: Applies operator-> to the wrapped pointer.
00464     //
00465     T* operator->() const;
00466 };
00467 
00468 //
00469 // Inlines.
00470 //
00471 
00472 template <class T>
00473 inline
00474 PP_CpPtr<T>::PP_CpPtr ()
00475     : ptr(0)
00476 {}
00477 
00478 template <class T>
00479 inline
00480 PP_CpPtr<T>::PP_CpPtr(T* rhs)
00481     : ptr(rhs)
00482 {}
00483 
00484 template <class T>
00485 inline
00486 PP_CpPtr<T>::~PP_CpPtr()
00487 {
00488     delete ptr;
00489 }
00490 
00491 template <class T>
00492 inline
00493 bool
00494 PP_CpPtr<T>::isNull () const
00495 {
00496     return ptr == 0;
00497 }
00498 
00499 template <class T>
00500 inline
00501 PP_CpPtr<T>::PP_CpPtr (const PP_CpPtr<T>& rhs)
00502 {
00503     ptr = rhs.isNull() ?  0 : new T(*rhs.ptr);
00504 }
00505 
00506 template <class T>
00507 inline
00508 PP_CpPtr<T>&
00509 PP_CpPtr<T>::operator= (const PP_CpPtr<T>& rhs)
00510 {
00511     if (!(ptr == rhs.ptr))
00512     {
00513         delete ptr;
00514         ptr = rhs.isNull() ? 0 : new T(*rhs.ptr);
00515     }
00516     return *this;
00517 }
00518 
00519 template <class T>
00520 inline
00521 PP_CpPtr<T>&
00522 PP_CpPtr<T>::operator= (T* rhs)
00523 {
00524     delete ptr;
00525     ptr = rhs;
00526     return *this;
00527 }
00528 
00529 template <class T>
00530 inline
00531 T&
00532 PP_CpPtr<T>::operator* () const
00533 {
00534     assert(ptr != 0);
00535     return *ptr;
00536 }
00537 
00538 template <class T>
00539 inline
00540 T*
00541 PP_CpPtr<T>::release ()
00542 {
00543     T* old = ptr;
00544     ptr = 0;
00545     return old;
00546 }
00547 
00548 template <class T>
00549 inline
00550 bool
00551 PP_CpPtr<T>::operator== (const PP_CpPtr<T>& rhs) const
00552 {
00553     return ptr == rhs.ptr;
00554 }
00555 
00556 template <class T>
00557 inline
00558 bool
00559 PP_CpPtr<T>::operator!= (const PP_CpPtr<T>& rhs) const
00560 {
00561     return ptr != rhs.ptr;
00562 }
00563 
00564 template <class T>
00565 inline
00566 PP_CpClassPtr<T>::PP_CpClassPtr ()
00567     : PP_CpPtr<T>()
00568 {}
00569 
00570 template <class T>
00571 inline
00572 PP_CpClassPtr<T>::PP_CpClassPtr (T* rhs)
00573     : PP_CpPtr<T>(rhs)
00574 {}
00575 
00576 template <class T>
00577 inline
00578 PP_CpClassPtr<T>::PP_CpClassPtr (const PP_CpClassPtr<T>& rhs)
00579     : PP_CpPtr<T>(rhs) {}
00580 
00581 template <class T>
00582 inline
00583 PP_CpClassPtr<T>&
00584 PP_CpClassPtr<T>::operator= (T* rhs)
00585 {
00586     PP_CpPtr<T>::operator= (rhs);
00587     return *this;
00588 }
00589 
00590 template <class T>
00591 inline
00592 PP_CpClassPtr<T>&
00593 PP_CpClassPtr<T>::operator= (const PP_CpClassPtr<T>& rhs)
00594 {
00595     PP_CpPtr<T>::operator= (rhs);
00596     return *this;
00597 }
00598 
00599 template <class T>
00600 inline
00601 T*
00602 PP_CpClassPtr<T>::operator-> () const
00603 {
00604     return ptr;
00605 }
00606 
00607 template <class T>
00608 inline
00609 PP_LnPtr<T>::PP_LnPtr ()
00610     : ptr(0)
00611 {}
00612 
00613 template <class T>
00614 inline
00615 PP_LnPtr<T>::PP_LnPtr(T* rhs)
00616     : ptr(rhs)
00617 {}
00618 
00619 template <class T>
00620 inline
00621 bool
00622 PP_LnPtr<T>::unique () const
00623 { 
00624     return ucnt.unique();
00625 }
00626 
00627 template <class T>
00628 inline
00629 PP_LnPtr<T>::~PP_LnPtr ()
00630 { 
00631     if (ucnt.unique())
00632         delete ptr;
00633 }
00634 
00635 template <class T>
00636 inline
00637 PP_LnPtr<T>&
00638 PP_LnPtr<T>::operator= (const PP_LnPtr<T>& rhs)
00639 {
00640     if (ptr != rhs.ptr)
00641     {
00642         if (unique())
00643             delete ptr;
00644         ptr = rhs.ptr;
00645         ucnt = rhs.ucnt;
00646     }
00647     return *this;
00648 }
00649 
00650 template <class T>
00651 inline
00652 int
00653 PP_LnPtr<T>::linkCount () const
00654 { 
00655     return ucnt.linkCount();
00656 }
00657 
00658 template <class T>
00659 inline
00660 T&
00661 PP_LnPtr<T>::operator* () const
00662 {
00663     assert(ptr != 0);
00664     return *ptr;
00665 }
00666 
00667 template <class T>
00668 inline
00669 bool
00670 PP_LnPtr<T>::isNull () const
00671 {
00672     return ptr == 0;
00673 }
00674 
00675 template <class T>
00676 inline
00677 bool
00678 PP_LnPtr<T>::operator== (const PP_LnPtr<T>& rhs) const
00679 {
00680     return ptr == rhs.ptr;
00681 }
00682 
00683 template <class T>
00684 inline
00685 bool
00686 PP_LnPtr<T>::operator!= (const PP_LnPtr<T>& rhs) const
00687 {
00688     return ptr != rhs.ptr;
00689 }
00690 
00691 template <class T>
00692 inline
00693 PP_LnClassPtr<T>::PP_LnClassPtr ()
00694 {}
00695 
00696 template <class T>
00697 inline
00698 PP_LnClassPtr<T>::PP_LnClassPtr (T* rhs)
00699     : PP_LnPtr<T>(rhs)
00700 {}
00701 
00702 template <class T>
00703 inline
00704 PP_LnClassPtr<T>&
00705 PP_LnClassPtr<T>::operator= (const PP_LnClassPtr<T>& rhs)
00706 {
00707     PP_LnPtr<T>::operator=(rhs);
00708     return *this;
00709 }
00710 
00711 template <class T>
00712 inline
00713 PP_LnClassPtr<T>&
00714 PP_LnClassPtr<T>::operator= (T* rhs)
00715 {
00716     PP_LnPtr<T>::operator=(rhs);
00717     return *this;
00718 }
00719 
00720 template <class T>
00721 inline
00722 T*
00723 PP_LnClassPtr<T>::operator->() const
00724 {
00725     return ptr;
00726 }
00727 
00728 
00729 
00730 //
00731 // Helper class for class PP_String.
00732 //
00733 
00734 class PP_StringRep
00735 {
00736     friend class PP_String;
00737     char* s;
00738     int   bufferlength;
00739 public:
00740     /*explicit*/ PP_StringRep (int _len = 0);
00741     ~PP_StringRep ();
00742     //
00743     // Resized the buffer and copies the contents of old buffer to new one.
00744     //
00745     void resize (int n);
00746 };
00747 
00748 //
00749 // PP_StringRep inlines.
00750 //
00751 
00752 inline
00753 PP_StringRep::PP_StringRep (int _len)
00754 {
00755     bufferlength = _len;
00756     s = new char [bufferlength];
00757 }
00758 
00759 inline
00760 PP_StringRep::~PP_StringRep ()
00761 {
00762     delete [] s;
00763     s = 0;
00764 }
00765 
00766 //
00767 //@Man:
00768 //@Memo: A String Class for ParmParse
00769 /*@Doc:
00770 
00771   The class PP_String is used to store and manipulate character strings.  It
00772   has an efficient underlying storage mechanism and some useful string
00773   manipulation operations.
00774 
00775   The PP_String class is implemented using a character array and reference
00776   count. Two PP_Strings may reference the same underlying character array with
00777   a reference count of two.  When an PP_String copy constructor or copy
00778   operator is applied the reference count on the underlying character array
00779   is incremented but the actual string is not copied.  That is, copying an
00780   PP_String is an inexpensive operation.  When an PP_String is destructed, the
00781   reference count is decremented.  The underlying character array is deleted
00782   only when the reference count goes to zero.  Any operator that modifies an
00783   PP_String will make its own copy of the character array before the
00784   modification, unless it's the sole owner of the character array in the
00785   PP_String.
00786 
00787 
00788   This is a convenience class  for ParmParse
00789   and will not be in any way supported by anyone at ANAG.
00790 
00791 */
00792 
00793 class PP_String
00794 {
00795 public:
00796     //
00797     //@ManDoc: Constructs an empty string.
00798     //
00799     PP_String ();
00800 
00801     /*@ManDoc: Constructs an PP_String containing the single character c.
00802                If c is the null character then this will be the empty string.
00803     */
00804     /*explicit*/ PP_String (char c);
00805 
00806     /*@ManDoc: Constructs an empty PP_String but allocates enough space to hold
00807                a character string of length len.  This may be useful when
00808                reading in very long lines with the `getline' function; i.e.
00809                it may be slightly more efficient to allocate a very large
00810                PP_String once and then use `getline' than to use `getline'
00811                on an empty string.  In general though, you won't notice any
00812                difference and you really shouldn't use this constructor.
00813     */
00814     /*explicit*/ PP_String (int len);
00815 
00816     /*@ManDoc: Constructs an PP_String initialized to the character string s.
00817                It is an error is `s' is the null string.
00818     */
00819     PP_String (const char* s);
00820     //
00821     //@ManDoc: The copy constructor.
00822     //
00823     PP_String (const PP_String& rhs);
00824     //
00825     //@ManDoc: The assignment operator
00826     //
00827     PP_String& operator= (const PP_String& rhs);
00828 
00829     /*@ManDoc: Catenate PP_String right onto end of this PP_String.  Return a
00830                reference to self to allow for operator chaining.
00831     */
00832     PP_String& operator+= (const PP_String& right);
00833 
00834     /*@ManDoc: Catenate character string right onto end of this PP_String.
00835                Returns a reference to self to allow for operator chaining.
00836                It is an error is `right' is the null string.
00837     */
00838     PP_String& operator+= (const char* right);
00839 
00840     /*@ManDoc: Catenate character c onto end of this PP_String.
00841                Returns a reference to self to allow for operator chaining.
00842                This does nothing if c is the null character.
00843     */
00844     PP_String& operator+= (char c);
00845 
00846     /*@ManDoc: Converts all characters in this PP_String to upper case.
00847                Returns a reference to self to allow for operator chaining.
00848     */
00849     PP_String& toUpper ();
00850 
00851     /*@ManDoc: Converts all characters in this PP_String to lower case.
00852                Returns a reference to self to allow for operator chaining.
00853     */
00854     PP_String& toLower ();
00855 
00856     /*@ManDoc: Read the next line from the input stream strm and store it
00857                as the value of the string.  The delimiter for a line of text
00858                is the newline character.  The newline is extracted from the
00859                istream, but it is NOT stored in the PP_String.  There is no
00860                limit to the length of string that can be extracted.
00861     */
00862     std::istream& getline (std::istream& strm);
00863 
00864     /*@ManDoc: Returns the number of characters stored in this PP_String.
00865                This does not include the terminating null character.
00866     */
00867     int length () const;
00868 
00869     //
00870     //@ManDoc: Returns true if this is the null string.
00871     //
00872     bool isNull () const;
00873 
00874     /*@ManDoc: Returns a reference to the kth character in the string.  An
00875                error occurs if k < 0 or k >= length().
00876     */
00877     char& operator [] (int k);
00878 
00879     /*@ManDoc: Returns kth character in the string.  An error occurs
00880                if k < 0 or k >= length().
00881     */
00882     char operator[] (int k) const;
00883 
00884     /*@ManDoc: Convert an PP_String to a const char *.  This allows an PP_String
00885                to be used in any context where a const char* type is needed.
00886     */
00887     const char* c_str () const;
00888 
00889     /*@ManDoc: Returns the value of the string as a double.  In the case
00890                when the string is empty or when the initial characters
00891                in the string are strictly alphabetic characters, this
00892                returns zero.  It's equivalent to `atof(c\_str())'.
00893     */
00894     double toDouble () const;
00895 
00896     /*@ManDoc: Returns the value of the string as a integer.  In the case
00897                when the string is empty or when the initial characters
00898                in the string are strictly alphabetic characters, this
00899                returns zero.  It's equivalent to `atoi(c\_str())'.
00900     */
00901     int toInteger () const;
00902 
00903     /*@ManDoc: Returns the value of the string as a long.  In the case
00904                when the string is empty or when the initial characters
00905                in the string are strictly alphabetic characters, this
00906                returns zero.  It's equivalent to `atol(c\_str())'.
00907     */
00908     long toLong () const;
00909     //
00910     //@ManDoc: Write to an ostream in ASCII format.
00911     //
00912     friend std::ostream& operator<< (std::ostream&       os,
00913                                 const PP_String& str);
00914 
00915     /*@ManDoc: Read a whitespace delimited string from an istream.
00916                This function discards leading whitespace and then reads
00917                in non-whitespace character until the next whitespace
00918                character or end-of-file.  Note that there is no limit,
00919                on the length of the character that can be read in, except
00920                that dictated by the resources of the machine.
00921                Note  also that operator>> and operator<< are not completely
00922                symmetrical in the case where operator<< writes out a
00923                string that contains whitespace.  If you're trying to
00924                read in a string that contains whitespace, you might
00925                want to use getline() instead.
00926     */
00927     friend std::istream& operator>> (std::istream& is,
00928                                 PP_String& str);
00929 
00930 protected:
00931     void copyModify ();
00932 
00933 private:
00934     PP_LnClassPtr<PP_StringRep> p;
00935     int                   len;
00936 
00937     //
00938     // None of the following functions need to be friends.  I've made
00939     // them friends solely so they'll show up nicely in the HTML documentaion
00940     // spewed out by doc++.
00941     //
00942 
00943     //
00944     // Is left lexically less than right?
00945     //
00946     friend inline bool operator<  (const PP_String& left,
00947                                    const PP_String& right);
00948     //
00949     // Is left lexically less than or equal to right?
00950     //
00951     friend inline bool operator<= (const PP_String& left,
00952                                    const PP_String& right);
00953     //
00954     // Is left not equal to right?
00955     //
00956     friend inline bool operator!= (const PP_String& left,
00957                                    const PP_String& right);
00958     //
00959     // Is left equal to right?
00960     //
00961     friend inline bool operator== (const PP_String& left,
00962                                    const PP_String& right);
00963     //
00964     // Is left lexically greater than or equal to right?
00965     //
00966     friend inline bool operator>= (const PP_String& left,
00967                                    const PP_String& right);
00968     //
00969     // Is left lexically greater than right?
00970     //
00971     friend inline bool operator>  (const PP_String& left,
00972                                    const PP_String& right);
00973     //
00974     // Is left lexically less than right?
00975     //
00976     friend inline bool operator<  (const PP_String& left,
00977                                    const char*    right);
00978     //
00979     // Is left lexically less than or equal to right?
00980     //
00981     friend inline bool operator<= (const PP_String& left,
00982                                    const char*    right);
00983     //
00984     // Is left not equal to right?
00985     //
00986     friend inline bool operator!= (const PP_String& left,
00987                                    const char*    right);
00988     //
00989     // Is left equal to right?
00990     //
00991     friend inline bool operator== (const PP_String& left,
00992                                    const char*    right);
00993     //
00994     // Is left lexically greater than or equal to right?
00995     //
00996     friend inline bool operator>= (const PP_String& left,
00997                                    const char*    right);
00998     //
00999     // Is left lexically greater than right?
01000     //
01001     friend inline bool operator>  (const PP_String& left,
01002                                    const char*    right);
01003     //
01004     // Is left lexically less than right?
01005     //
01006     friend inline bool operator<  (const char*    left,
01007                                    const PP_String& right);
01008     //
01009     // Is left lexically less than or equal to right?
01010     //
01011     friend inline bool operator<= (const char*    left,
01012                                    const PP_String& right);
01013     //
01014     // Is left not equal to right?
01015     //
01016     friend inline bool operator!= (const char*    left,
01017                                    const PP_String& right);
01018     //
01019     // Is left equal to right?
01020     //
01021     friend inline bool operator== (const char*    left,
01022                                    const PP_String& right);
01023     //
01024     // Is left lexically greater than or equal to right?
01025     //
01026     friend inline bool operator>= (const char*    left,
01027                                    const PP_String& right);
01028     //
01029     // Is left lexically greater than right?
01030     //
01031     friend inline bool operator>  (const char*    left,
01032                                    const PP_String& right);
01033 };
01034 
01035 //
01036 // PP_String inlines.
01037 //
01038 
01039 inline
01040 bool
01041 PP_String::isNull () const
01042 {
01043     return len == 0;
01044 }
01045 
01046 inline
01047 int
01048 PP_String::length () const
01049 {
01050     return len;
01051 }
01052 
01053 inline
01054 double
01055 PP_String::toDouble () const
01056 {
01057     return len == 0 ? 0 : std::atof(p->s);
01058 }
01059 
01060 inline
01061 int
01062 PP_String::toInteger () const
01063 {
01064     return len == 0 ? 0 : atoi(p->s);
01065 }
01066 
01067 inline
01068 long
01069 PP_String::toLong () const
01070 {
01071     return len == 0 ? 0 : atol(p->s);
01072 }
01073 
01074 inline
01075 const char*
01076 PP_String::c_str () const
01077 {
01078     return p->s;
01079 }
01080 
01081 inline
01082 char
01083 PP_String::operator[] (int index) const
01084 {
01085     assert(index >=0 && index < len);
01086     return p->s[index];
01087 }
01088 
01089 inline
01090 PP_String
01091 operator+ (const PP_String& left,
01092            const PP_String& right)
01093 {
01094     PP_String result(left);
01095     return result += right;
01096 }
01097 
01098 inline
01099 bool
01100 operator< (const PP_String& left,
01101            const PP_String& right)
01102 {
01103     return ::strcmp(left.c_str(), right.c_str()) < 0;
01104 }
01105 
01106 inline
01107 bool
01108 operator<= (const PP_String& left,
01109             const PP_String& right)
01110 {
01111     return ::strcmp(left.c_str(), right.c_str()) <= 0;
01112 }
01113 
01114 inline
01115 bool
01116 operator!= (const PP_String& left,
01117             const PP_String& right)
01118 {
01119     return ::strcmp(left.c_str(), right.c_str()) != 0;
01120 }
01121 
01122 inline
01123 bool
01124 operator== (const PP_String& left,
01125             const PP_String& right)
01126 {
01127     return ::strcmp(left.c_str(), right.c_str()) == 0;
01128 }
01129 
01130 inline
01131 bool
01132 operator>= (const PP_String& left,
01133             const PP_String& right)
01134 {
01135     return ::strcmp(left.c_str(), right.c_str()) >= 0;
01136 }
01137 
01138 inline
01139 bool
01140 operator>  (const PP_String& left,
01141             const PP_String& right)
01142 {
01143     return ::strcmp(left.c_str(), right.c_str()) > 0;
01144 }
01145 
01146 inline
01147 bool
01148 operator< (const PP_String& left,
01149            const char*    right)
01150 {
01151     return ::strcmp(left.c_str(), right) < 0;
01152 }
01153 
01154 inline
01155 bool
01156 operator<= (const PP_String& left,
01157             const char*    right)
01158 {
01159     return ::strcmp(left.c_str(), right) <= 0;
01160 }
01161 
01162 inline
01163 bool
01164 operator!= (const PP_String& left,
01165             const char*    right)
01166 {
01167     return ::strcmp(left.c_str(), right) != 0;
01168 }
01169 
01170 inline
01171 bool
01172 operator== (const PP_String& left,
01173             const char*    right)
01174 {
01175     return ::strcmp(left.c_str(), right) == 0;
01176 }
01177 
01178 inline
01179 bool
01180 operator>= (const PP_String& left,
01181             const char*    right)
01182 {
01183     return ::strcmp(left.c_str(), right) >= 0;
01184 }
01185 
01186 inline
01187 bool
01188 operator>  (const PP_String& left,
01189             const char*    right)
01190 {
01191     return ::strcmp(left.c_str(), right) > 0;
01192 }
01193 
01194 inline
01195 bool
01196 operator< (const char*    left,
01197            const PP_String& right)
01198 {
01199     return ::strcmp(left, right.c_str()) < 0;
01200 }
01201 
01202 inline
01203 bool
01204 operator<= (const char*    left,
01205             const PP_String& right)
01206 {
01207     return ::strcmp(left, right.c_str()) <= 0;
01208 }
01209 
01210 inline
01211 bool
01212 operator!= (const char*    left, 
01213            const PP_String& right)
01214 {
01215     return ::strcmp(left, right.c_str()) != 0;
01216 }
01217 
01218 inline
01219 bool
01220 operator== (const char*    left,
01221             const PP_String& right)
01222 {
01223     return ::strcmp(left, right.c_str()) == 0;
01224 }
01225 
01226 inline
01227 bool
01228 operator>= (const char*    left,
01229             const PP_String& right)
01230 {
01231     return ::strcmp(left, right.c_str()) >= 0;
01232 }
01233 
01234 inline
01235 bool
01236 operator>  (const char*    left,
01237             const PP_String& right)
01238 {
01239     return ::strcmp(left, right.c_str()) > 0;
01240 }
01241 
01242 
01243 //#include <List.H>
01244 
01245 template <class T> class PP_ListLink;
01246 template <class T> class PP_ListIterator;
01247 template <class T> class PP_List;
01248 
01249 template <class T>
01250 class PP_ListLink
01251 {
01252 private:
01253     friend class PP_List<T>;
01254     friend class PP_ListIterator<T>;
01255 
01256     PP_ListLink (const T&     _val,
01257               PP_ListLink<T>* _pre,
01258               PP_ListLink<T>* _suc)
01259         :
01260         val(_val),
01261         pre(_pre),
01262         suc(_suc) {}
01263 
01264 private:
01265     T            val;
01266     PP_ListLink<T>* pre;
01267     PP_ListLink<T>* suc;
01268 };
01269 
01270 //
01271 //@Man:
01272 //@Memo: Iterate over a List for ParmParse
01273 /*@Doc:
01274 
01275   The class PP_ListIterator<T> is an iterator over class PP_List<T>.
01276 
01277   This class does NOT provide a default constructor or an assignment operator.
01278 
01279 
01280   This is a convenience class  for ParmParse
01281   and will not be in any way supported by anyone at ANAG.
01282 */
01283 
01284 
01285 template <class T>
01286 class PP_ListIterator
01287 {
01288 public:
01289     //
01290     //@ManDoc: Construct a PP_ListIterator<T> to first element of aList.
01291     //
01292     /*explicit*/ PP_ListIterator (const PP_List<T>& aList);
01293     //
01294     //@ManDoc: The copy constructor.
01295     //
01296     PP_ListIterator (const PP_ListIterator<T>& rhs);
01297 
01298     /*@ManDoc: Reset this PP_ListIterator<T> to point to the first element
01299                in the PP_List<T>.
01300     */
01301     void rewind ();
01302 
01303     /*@ManDoc: Return a constant reference to the object in the PP_List<T>
01304                currently pointed to by this PP_ListIterator<T>.
01305     */
01306     const T& operator() () const;
01307 
01308     /*@ManDoc: Return a constant reference to the object in the PP_List<T>
01309                currently pointed to by this PP_ListIterator<T>.
01310     */
01311     const T& operator* () const;
01312 
01313     /*@ManDoc: This is a conversion operator that makes the iterator look
01314                like a pointer.  This operator makes it easy to check if the
01315                iterator is pointing to an element on the PP_List<T>.  If the
01316                iterator has been moved off the PP_List<T> or if the PP_List<T> is
01317                empty, this conversion returns the NULL pointer.
01318     */
01319     operator void* ();
01320 
01321     /*@ManDoc: Returns true if PP_ListIterator<T> doesn't point to any
01322                element on the PP_List<T>.
01323     */
01324     bool operator! () const;
01325 
01326     /*@ManDoc: Return a constant reference to the object in the PP_List<T>
01327                currently pointed to by the iterator.
01328     */
01329     const T& value () const;
01330 
01331     /*@ManDoc: This is the prefix auto-increment operator.  It advances the
01332                PP_ListIterator<T> to point to the next element on the PP_List<T>.
01333                It then returns a reference to itself to allow for chaining
01334                with other operators.
01335     */
01336     PP_ListIterator<T>& operator++ ();
01337 
01338     /*@ManDoc: This is the prefix auto-decrement operator.  It moves the
01339                PP_ListIterator<T> to point to the previous element on the
01340                PP_List<T>.  It then returns a reference to itself to allow for
01341                chaining with other operators.
01342     */
01343     PP_ListIterator<T>& operator-- ();
01344 
01345     /*@ManDoc: This is the postfix auto-decrement operator.  It moves the
01346                PP_ListIterator<T> to point to the previous element on the
01347                PP_List<T>.  It then returns a PP_ListIterator<T> that points to
01348                the old element to allow for chaining with other operators.
01349 
01350     */
01351     PP_ListIterator<T> operator-- (int);
01352 
01353     /*@ManDoc: This is the postfix auto-increment operator.  It advances the
01354                PP_ListIterator<T> to point to the next element on the PP_List<T>.
01355                It then returns a PP_ListIterator<T> that points to the old
01356                element to allow for chaining with other operators.
01357     */
01358     PP_ListIterator<T> operator++ (int);
01359 
01360     /*@ManDoc: Do the two PP_ListIterator<T>s point to the same PP_List<T> and
01361                the same element within the PP_List<T>?
01362     */
01363     bool operator== (const PP_ListIterator<T>&) const;
01364     //
01365     //@ManDoc: Are the PP_ListIterator<T>s not equal?
01366     //
01367     bool operator!= (const PP_ListIterator<T>&) const;
01368 
01369 protected:
01370     //
01371     // Construct a PP_ListIterator<T> to a PP_List<T> and object in that PP_List<T>.
01372     //
01373     PP_ListIterator (const PP_List<T>& _list,
01374                      PP_ListLink<T>*   _p);
01375     //
01376     // A reference to the PP_List<T> to which we point.
01377     //
01378     const PP_List<T>& list;
01379     //
01380     // A pointer to the element in the PP_List<T> to which we point.
01381     //
01382     PP_ListLink<T>* p;
01383 
01384 private:
01385     friend class PP_List<T>;
01386     //
01387     // These are disallowed.
01388     //
01389     PP_ListIterator ();
01390     PP_ListIterator<T>& operator= (const PP_ListIterator<T>&);
01391 };
01392 
01393 //
01394 //@Man:
01395 //@Memo: A Doubly-Linked List for ParmParse
01396 /*@Doc:
01397 
01398   The PP_List<T> class is a template class that implements a doubly-linked list
01399   of objects.  A PP_List<T> is a useful container class when the number of
01400   objects in the collection is not known ahead of time.   A PP_List<T> can
01401   contain an arbitrary number of elements; operations such as insertion,
01402   deletion, and catenation are easily implemented and inexpensive.
01403 
01404   The only difficulty when defining a list class is devising a mechanism to
01405   access the elements.  In an array, an element is accessed using an
01406   integer index.  Since the elements in a PP_List<T> are ordered by position,
01407   we could define an integer indexing operation that walks along the
01408   PP_List<T> links from the beginning until the numbered element is found.
01409   Unfortunately, this would be very inefficient when accessing elements near
01410   the  end of a long list.  Another solution is to allow user access to the
01411   individual link objects that contain the element as well as the forward and
01412   backward pointers.  This is not a satisfactory solution since it allows
01413   user access to the internal representation of the class.  The solution
01414   chosen is to define a PP_ListIterator<T> template class.
01415 
01416   Think of a PP_ListIterator<T> as a pointer to an object in the PP_List<T>.  You
01417   can access the element currently pointed to by the iterator, move the
01418   iterator forward and backward through the PP_List<T>, and use it as a
01419   mechanism to define where elements should be inserted and deleted.  If the
01420   iterator is moved off the end of the list it behaves as a null pointer.
01421 
01422   This is a concrete class, not a polymorphic one.
01423 
01424 
01425   This is a convenience class  for ParmParse
01426   and will not be in any way supported by anyone at ANAG.
01427 */
01428 
01429 template <class T>
01430 class PP_List
01431 {
01432 public:
01433     //
01434     //@ManDoc: Construct an empty PP_List<T>.
01435     //
01436     PP_List ();
01437     //
01438     //@ManDoc: The copy constructor.
01439     //
01440     PP_List (const PP_List<T>& rhs);
01441     //
01442     //@ManDoc: The assignment operator.
01443     //
01444     PP_List<T>& operator= (const PP_List<T>& rhs);
01445     //
01446     //@ManDoc: The destructor.
01447     //
01448     ~PP_List();
01449     //
01450     //@ManDoc: Adds a copy of the value to the beginning of the PP_List<T>.
01451     //
01452     void prepend (const T& value);
01453     //
01454     //@ManDoc: Adds a copy of the value to the end of the PP_List<T>.
01455     //
01456     void append (const T& value);
01457     //
01458     //@ManDoc: Adds a copy of the value to the end of the PP_List<T>.
01459     //
01460     void add (const T& value);
01461     //
01462     //@ManDoc: Appends a copy of all items in PP_List<T> src to this PP_List<T>.
01463     //
01464     void join (const PP_List<T>& src);
01465 
01466     /*@ManDoc: Appends a copy of all items in PP_List<T> src to this PP_List<T>.
01467                This differs from join() in that it unlinks the objects from
01468                the PP_List<T> src and glues them to the end of this PP_List<T>,
01469                leaving PP_List<T> src empty.  This is more efficient that
01470                join() if src is no longer needed.
01471     */
01472     void catenate (PP_List<T>& src);
01473     //
01474     //@ManDoc: Removes all objects from the PP_List<T>.
01475     //
01476     void clear ();
01477     //
01478     //@ManDoc: Returns a reference to the first element in the PP_List<T>.
01479     //
01480     T& firstElement () const;
01481     //
01482     //@ManDoc: Returns a reference to the last element in the PP_List<T>.
01483     //
01484     T& lastElement () const;
01485 
01486     /*@ManDoc: Returns true if the PP_List<T> contains an object identical
01487                to value.  Type T must have an operator==() defined, or
01488                be an intrinsic type.
01489     */
01490     bool includes (const T& value) const;
01491 
01492     /*@ManDoc: Returns true if the this and rhs are memberwise equal;
01493                i.e. the two lists are the same size and each of the
01494                elements in the list compare equal. Type T must have an
01495                operator==() defined, or be an intrinsic type.
01496     */
01497     bool operator== (const PP_List<T>& rhs) const;
01498     //
01499     //@ManDoc: Returns true if the this and rhs are not equal.
01500     //
01501     bool operator!= (const PP_List<T>& rhs) const;
01502     //
01503     //@ManDoc: Returns true if the PP_List<T> is empty.
01504     //
01505     bool isEmpty () const;
01506     //
01507     //@ManDoc: Returns true if the PP_List<T> is not empty.
01508     //
01509     bool isNotEmpty () const;
01510     //
01511     //@ManDoc: Returns the number of objects in the PP_List<T>.
01512     //
01513     int length () const;
01514     //
01515     //@ManDoc: Removes the first element in the PP_List<T>.
01516     //
01517     void removeFirst ();
01518     //
01519     //@ManDoc: Removes the last element in the PP_List<T>.
01520     //
01521     void removeLast ();
01522     //
01523     //@ManDoc: Returns reference to object pointed to by the PP_ListIterator<T>.
01524     //
01525     const T& operator[] (const PP_ListIterator<T>& li) const;
01526     //
01527     //@ManDoc: Returns reference to object pointed to by the PP_ListIterator<T>.
01528     //
01529     T& operator[] (const PP_ListIterator<T>& li);
01530     //
01531     //@ManDoc: Removes all objects in the PP_List<T> equal to value.
01532     //
01533     void remove (const T& value);
01534 
01535     /*@ManDoc: Removes all objects in the PP_List<T> equal to any of the
01536                values in lst.
01537     */
01538     void remove (const PP_List<T>& lst);
01539     //
01540     //@ManDoc: Removes the object pointed to by the PP_ListIterator<T>.
01541     //
01542     void remove (PP_ListIterator<T>& lit);
01543     //
01544     //@ManDoc: Replace the value pointed to by the PP_ListIterator<T> by val.
01545     //
01546     void replace (PP_ListIterator<T>& li,
01547                          const T&         val);
01548 
01549     /*@ManDoc: Insert val into PP_List<T> after the object pointed to by
01550                PP_ListIterator<T>.
01551     */
01552     void addAfter (PP_ListIterator<T>& lit,
01553                    const T&         val);
01554 
01555     /*@ManDoc: Insert val into PP_List<T> before the object pointed to by
01556                PP_ListIterator<T>.
01557     */
01558     void addBefore (PP_ListIterator<T>& lit,
01559                     const T&         val);
01560     //
01561     //@ManDoc: Returns a PP_ListIterator<T> to the first object in this PP_List<T>.
01562     //
01563     PP_ListIterator<T> first () const;
01564     //
01565     //@ManDoc: Returns a PP_ListIterator<T> to the last object in this PP_List<T>.
01566     //
01567     PP_ListIterator<T> last () const;
01568 
01569 protected:
01570     //
01571     // A helper function for removing nodes.
01572     //
01573     void remove (PP_ListLink<T> *ln);
01574     //
01575     // A helper function for adding nodes.
01576     //
01577     PP_ListLink<T>* addBefore (PP_ListLink<T>* ln,
01578                             const T&     val);
01579     //
01580     // A helper function for adding nodes.
01581     //
01582     PP_ListLink<T>* addAfter (PP_ListLink<T>* ln,
01583                            const T&     val);
01584     //
01585     // The head of the list.
01586     //
01587     PP_ListLink<T>* head;
01588     //
01589     // The tail of the list.
01590     //
01591     PP_ListLink<T>* tail;
01592     //
01593     // Our good and trusted friend.
01594     //
01595     friend class PP_ListIterator<T>;
01596 };
01597 
01598 //
01599 // Inlines.
01600 //
01601 
01602 //
01603 // The ListIterator stuff.
01604 //
01605 
01606 template <class T>
01607 inline
01608 PP_ListIterator<T>::PP_ListIterator (const PP_List<T>& _list,
01609                                PP_ListLink<T>*   _p)
01610     :
01611     list(_list),
01612     p(_p)
01613 {}
01614 
01615 template <class T>
01616 inline
01617 PP_ListIterator<T>::PP_ListIterator (const PP_List<T>& aList)
01618     :
01619     list(aList)
01620 {
01621     p = list.head;
01622 }
01623 
01624 template <class T>
01625 inline
01626 PP_ListIterator<T>::PP_ListIterator (const PP_ListIterator<T>& li)
01627     :
01628     list(li.list),
01629     p(li.p)
01630 {}
01631 
01632 template <class T>
01633 inline
01634 void
01635 PP_ListIterator<T>::rewind ()
01636 {
01637     p = list.head;
01638 }
01639 
01640 template <class T>
01641 inline
01642 const T&
01643 PP_ListIterator<T>::operator() () const
01644 {
01645     assert(p != 0);
01646     return p->val;
01647 }
01648 
01649 template <class T>
01650 inline
01651 const T&
01652 PP_ListIterator<T>::operator* () const
01653 {
01654     assert(p != 0);
01655     return p->val;
01656 }
01657 
01658 template <class T>
01659 inline
01660 PP_ListIterator<T>::operator void* ()
01661 {
01662     return p != 0 ? this : 0;
01663 }
01664 
01665 template <class T>
01666 inline
01667 bool
01668 PP_ListIterator<T>::operator! () const
01669 {
01670     return p == 0 ? true : false;
01671 }
01672 
01673 template <class T>
01674 inline
01675 const T&
01676 PP_ListIterator<T>::value () const
01677 {
01678     assert(p != 0);
01679     return p->val;
01680 }
01681 
01682 template <class T>
01683 inline
01684 PP_ListIterator<T>&
01685 PP_ListIterator<T>::operator++ ()
01686 {
01687     if (p)
01688         p = p->suc;
01689     return *this;
01690 }
01691 
01692 template <class T>
01693 inline
01694 PP_ListIterator<T>&
01695 PP_ListIterator<T>::operator-- ()
01696 {
01697     if (p)
01698         p = p->pre;
01699     return *this;
01700 }
01701 
01702 template <class T>
01703 inline
01704 PP_ListIterator<T>
01705 PP_ListIterator<T>::operator++ (int)
01706 {
01707     const PP_ListIterator<T> li = *this;
01708     ++(*this);
01709     return li;
01710 }
01711 
01712 template <class T>
01713 inline
01714 PP_ListIterator<T>
01715 PP_ListIterator<T>::operator-- (int)
01716 {
01717     const PP_ListIterator<T> li = *this;
01718     --(*this);
01719     return li;
01720 }
01721 
01722 template <class T>
01723 inline
01724 bool
01725 PP_ListIterator<T>::operator== (const PP_ListIterator<T>& _li) const
01726 {
01727     return (&list == &_li.list && p == _li.p) ? true : false;
01728 }
01729 
01730 template <class T>
01731 inline
01732 bool
01733 PP_ListIterator<T>::operator!= (const PP_ListIterator<T>& _li) const
01734 {
01735     return ! PP_ListIterator<T>::operator==(_li);
01736 }
01737 
01738 //
01739 // List stuff.
01740 //
01741 
01742 template <class T>
01743 inline
01744 PP_List<T>::PP_List ()
01745     :
01746     head(0),
01747     tail(0)
01748 {}
01749 
01750 template <class T>
01751 inline
01752 PP_List<T>::~PP_List ()
01753 {
01754     clear();
01755 }
01756 
01757 template <class T>
01758 inline
01759 void
01760 PP_List<T>::prepend (const T& value)
01761 {
01762     addBefore(head, value);
01763 }
01764 
01765 template <class T>
01766 inline
01767 void
01768 PP_List<T>::append (const T& value)
01769 {
01770     addAfter(tail, value);
01771 }
01772 
01773 template <class T>
01774 inline
01775 T&
01776 PP_List<T>::firstElement () const
01777 {
01778     assert(head != 0);
01779     return head->val;
01780 }
01781 
01782 template <class T>
01783 inline
01784 T&
01785 PP_List<T>::lastElement () const
01786 {
01787     assert(tail != 0);
01788     return tail->val;
01789 }
01790 
01791 template <class T>
01792 inline
01793 bool
01794 PP_List<T>::isEmpty () const
01795 {
01796     return head == 0 && tail == 0;
01797 }
01798 
01799 template <class T>
01800 inline
01801 bool
01802 PP_List<T>::isNotEmpty () const
01803 {
01804     return !isEmpty();
01805 }
01806 
01807 template <class T>
01808 inline
01809 void
01810 PP_List<T>::removeFirst ()
01811 {
01812     remove(head);
01813 }
01814 
01815 template <class T>
01816 inline
01817 void
01818 PP_List<T>::removeLast ()
01819 {
01820     remove(tail);
01821 }
01822 
01823 template <class T>
01824 inline
01825 const T&
01826 PP_List<T>::operator[] (const PP_ListIterator<T>& li) const
01827 {
01828     assert(li.p != 0);
01829     return li.p->val;
01830 }
01831 
01832 template <class T>
01833 inline
01834 T&
01835 PP_List<T>::operator[] (const PP_ListIterator<T>& li)
01836 {
01837     assert(li.p != 0);
01838     return li.p->val;
01839 }
01840 
01841 template <class T>
01842 inline
01843 void
01844 PP_List<T>::replace (PP_ListIterator<T>& li,
01845                   const T&         _val)
01846 {
01847     assert(li.p != 0);
01848     li.p->val = _val;
01849 }
01850 
01851 template <class T>
01852 inline
01853 void
01854 PP_List<T>::addAfter (PP_ListIterator<T>& lit,
01855                    const T&         val)
01856 {
01857     addAfter(lit.p, val);
01858 }
01859 
01860 template <class T>
01861 inline
01862 void
01863 PP_List<T>::addBefore (PP_ListIterator<T>& lit,
01864                     const T&         val)
01865 {
01866     addBefore(lit.p, val);
01867 }
01868 
01869 template <class T>
01870 inline
01871 PP_ListIterator<T>
01872 PP_List<T>::first () const
01873 {
01874     return PP_ListIterator<T>(*this,head);
01875 }
01876 
01877 template <class T>
01878 inline
01879 PP_ListIterator<T>
01880 PP_List<T>::last () const
01881 {
01882     return PP_ListIterator<T>(*this,tail);
01883 }
01884 
01885 //
01886 // List members
01887 //
01888 
01889 template <class T>
01890 inline
01891 PP_List<T>::PP_List (const PP_List<T>& source)
01892     :
01893     head(0),
01894     tail(0)
01895 {
01896     if (source.isEmpty())
01897         tail = head = 0;
01898     else
01899         for (PP_ListIterator<T> li(source); li; ++li)
01900             append(li());
01901 }
01902 
01903 //
01904 // This isn't inlined as it's declared virtual.
01905 //
01906 
01907 template <class T>
01908 inline void
01909 PP_List<T>::add (const T& value)
01910 {
01911     append(value);
01912 }
01913 
01914 template <class T>
01915 inline
01916 int
01917 PP_List<T>::length () const
01918 {
01919     int len = 0;
01920     for (PP_ListIterator<T> li(*this); li; ++li)
01921         len++;
01922     return len;
01923 }
01924 
01925 template <class T>
01926 inline
01927 PP_List<T>&
01928 PP_List<T>::operator= (const PP_List<T>& source)
01929 {
01930     if (!(this == &source))
01931     {
01932         clear();
01933         for (PP_ListIterator<T> li(source); li; ++li)
01934             append(li());
01935     }
01936     return *this;
01937 }
01938 
01939 template <class T>
01940 inline PP_ListLink<T> *
01941 PP_List<T>::addBefore (PP_ListLink<T>* ln,
01942                     const T&     val)
01943 {
01944     assert(ln != 0 || head == 0);
01945 
01946     PP_ListLink<T>* newlink;
01947 
01948     if (ln == head)
01949     {
01950         head = newlink = new PP_ListLink<T>(val, 0, head);
01951 
01952         if (tail == 0)
01953             tail = head;
01954         else
01955             head->suc->pre = newlink;
01956     }
01957     else
01958     {
01959         newlink = new PP_ListLink<T>(val, ln->pre, ln);
01960 
01961         ln->pre->suc = newlink;
01962         ln->pre = newlink;
01963     }
01964 
01965     return newlink;
01966 }
01967 
01968 template <class T>
01969 inline
01970 PP_ListLink<T>*
01971 PP_List<T>::addAfter (PP_ListLink<T>* ln,
01972                    const T&     val)
01973 {
01974     assert(ln != 0 || tail == 0);
01975 
01976     PP_ListLink<T>* newlink;
01977 
01978     // trying this here to satisfy icc -O2 (ndk)
01979     // this worked for me -- but since we aren't actively using icc, i'll
01980     // leave it commented.
01981     //newlink = new PP_ListLink<T>(val,tail,0);
01982     //delete newlink;
01983 
01984     if (ln == tail)
01985     {
01986         tail = newlink = new PP_ListLink<T>(val,tail,0);
01987 
01988         if (head == 0)
01989             head = tail;
01990         else
01991             tail->pre->suc = newlink;
01992     }
01993     else
01994     {
01995         newlink = new PP_ListLink<T>(val, ln, ln->suc);
01996 
01997         ln->suc->pre = newlink;
01998         ln->suc = newlink;
01999     }
02000 
02001     return newlink;
02002 }
02003 
02004 template <class T>
02005 inline void
02006 PP_List<T>::join (const PP_List<T>& list2)
02007 {
02008     for (PP_ListIterator<T> li2(list2); li2; ++li2)
02009         append(li2());
02010 }
02011 
02012 template <class T>
02013 inline void
02014 PP_List<T>::catenate (PP_List<T>& list2)
02015 {
02016     if (list2.isEmpty())
02017         //
02018         // Do nothing.
02019         //
02020         ;
02021     else if (isEmpty())
02022     {
02023        head = list2.head;
02024        tail = list2.tail;
02025        list2.head = 0;
02026        list2.tail = 0;
02027     }
02028     else
02029     {
02030         tail->suc = list2.head;
02031         list2.head->pre = tail;
02032         tail = list2.tail;
02033         list2.head = 0;
02034         list2.tail = 0;
02035     }
02036 }
02037 
02038 template <class T>
02039 inline void
02040 PP_List<T>::clear ()
02041 {
02042     PP_ListLink<T>* next = 0;
02043 
02044     for (PP_ListLink<T>* p = head; p != 0; p = next)
02045     {
02046         next = p->suc;
02047         p->suc = 0;
02048         delete p;
02049     }
02050     tail = head = 0;
02051 }
02052 
02053 template <class T>
02054 inline bool
02055 PP_List<T>::includes (const T& v) const
02056 {
02057     bool rc = false;
02058     for (PP_ListIterator<T> li(*this); li && !rc; ++li)
02059         if (v == li())
02060             rc = true;
02061     return rc;
02062 }
02063 
02064 template<class T>
02065 inline bool
02066 PP_List<T>::operator== (const PP_List<T>& rhs) const
02067 {
02068     if (length() == rhs.length())
02069     {
02070         for (PP_ListIterator<T> li(*this), ri(rhs); li; ++li, ++ri)
02071             if (li() != ri())
02072                 return false;
02073         return true;
02074     }
02075 
02076     return false;
02077 }
02078 
02079 template<class T>
02080 inline bool
02081 PP_List<T>::operator!= (const PP_List<T>& rhs) const
02082 {
02083     return !operator==(rhs);
02084 }
02085 
02086 template <class T>
02087 inline void
02088 PP_List<T>::remove (PP_ListIterator<T>& li)
02089 {
02090     PP_ListLink<T> *np = li.p->suc;
02091     remove(li.p);
02092     li.p = np;
02093 }
02094 
02095 template <class T>
02096 inline void
02097 PP_List<T>::remove (const T& _v)
02098 {
02099     for (PP_ListIterator<T> litr(*this); litr; ++litr)
02100         if (litr() == _v)
02101             remove(litr);
02102 }
02103 
02104 template <class T>
02105 inline void
02106 PP_List<T>::remove (const PP_List<T>& _lv)
02107 {
02108     for (PP_ListIterator<T> litr(_lv); litr; ++litr)
02109         remove(litr());
02110 }
02111 
02112 template <class T>
02113 inline void
02114 PP_List<T>::remove (PP_ListLink<T>* ln)
02115 {
02116     assert(head !=0 && tail != 0);
02117 
02118     if (head == ln && tail == ln)
02119         head = tail = 0;
02120     else if (head == ln)
02121     {
02122         assert(ln->pre == 0);
02123         head = ln->suc;
02124         head->pre = 0;
02125     }
02126     else if (tail == ln)
02127     {
02128         assert(ln->suc == 0);
02129         tail = ln->pre;
02130         tail->suc  = 0;
02131     }
02132     else
02133     {
02134         assert(ln->suc != 0 && ln->pre != 0);
02135         ln->suc->pre = ln->pre;
02136         ln->pre->suc = ln->suc;
02137     }
02138     delete ln;
02139     ln = 0;
02140 }
02141 
02142 
02143 //#include <Array.H>
02144 
02145 
02146 template <class T> class PP_Array;
02147 
02148 //
02149 //@Man:
02150 //@Memo: An Array of Objects of Type T for ParmParse
02151 /*@Doc: 
02152 
02153    This class implements an array of objects of the parameterized type
02154    T.  In contrast with the predefined C++ array type, an `PP_Array<T>'
02155    object knows its length, can be dynamically resized, and provides
02156    automatic bounds checking.  The bounds checking can be turned off by
02157    specifying the -DNDEBUG flag on the command line when compiling the
02158    BOXLIB library.  The main reason for defining the PP_Array class is that
02159    it is used, either by composition or inheritance, to implement many of
02160    the other classes in the BOXLIB library.
02161 
02162    The `PP_Array<T>' class works by storing copies of the objects it
02163    contains.  If the objects are large, such as `FARRAYBOX's it is
02164    probably better to use the `PArray' class which is an array class that
02165    stores pointers to the objects (avoiding expensive copies).
02166    The `PP_Array<T>' class destructs all objects in the array when it is 
02167    itself destructed.  If this is not the desired action, the `PArray' class
02168    should be used.
02169 
02170    In the PP_Array<T> class, there are two different concepts of size: the amount
02171    of space allocated, and the amount of space actually used.  Obviously, the 
02172    allocated space must be larger than the used space.  We separate these two
02173    concepts to allow the user to optionally avoid memory allocation costs.
02174    Rather than construct and destroy a temporary PP_Array<T> many times, it may 
02175    be less expensive to allocate it once with enough memory to handle all uses,
02176    and resize the PP_Array<T> for each particular use.  See the member functions
02177    `reserve', `shrinkWrap', and `resize'. 
02178 
02179    Note that care must be taken when deriving classes from `PP_Array<T>'.  It is
02180    a concrete class, not a polymorphic one.
02181 
02182    This class does NOT provide an assignment operator for assigning an integer
02183    to an PP_Array<T>.
02184 
02185 
02186   This is a convenience class  for ParmParse
02187   and will not be in any way supported by anyone at ANAG.
02188 */
02189 
02190 template <class T>
02191 class PP_Array
02192 {
02193 public:
02194     //
02195     //@ManDoc: Constructs an `PP_Array<T>' with no elements
02196     //
02197     PP_Array ();
02198 
02199     /*@ManDoc: Constructs an `PP_Array<T>' of length len with the value of each
02200       element defined by the default constructor for `T'.
02201     */
02202     /*explicit*/ PP_Array (long len);
02203 
02204     /*@ManDoc: Constructs an `PP_Array<T>' of length len with the value of each
02205                elements given by initialvalue.
02206     */
02207     PP_Array (long     len,
02208            const T& initialvalue);
02209 
02210     /*@ManDoc: Constructs an `PP_Array<T>' of length len in which the K'th
02211                value is a copy of vec[K].
02212     */
02213     PP_Array (const T* vec,
02214            long     len);
02215     //
02216     //@ManDoc: The copy constructor.
02217     //
02218     PP_Array (const PP_Array<T>& rhs);
02219 
02220     /*@ManDoc: This operator deletes the current `PP_Array<T>' and replaces it 
02221                with a copy of rhs.
02222     */
02223     PP_Array<T>& operator= (const PP_Array<T>& rhs);
02224     //
02225     //@ManDoc: Deletes the `PP_Array<T>' and all objects it contains.
02226     //
02227     ~PP_Array ();
02228 
02229     /*@ManDoc: Destructs each element in this `PP_Array<T>'.  The resulting array
02230                has length zero.
02231     */
02232     void clear ();
02233     //
02234     //@ManDoc: Returns true if this `PP_Array<T>' is not empty.
02235     //
02236     bool ready  () const;
02237 
02238     /*@ManDoc: Reserve space for future expansion of memory.  You still must
02239                `resize' to address the memory.
02240     */
02241     void reserve (long _truesize);
02242 
02243     /*@ManDoc: Shrink allocated memory to be just enough for elements in
02244                PP_Array.  This is useful if you allocated a lot of memory to
02245                avoid memory allocation delays as you add elements.  Once all
02246                the elements are added, you can reduce memory usage to
02247                the minimum by calling this function.
02248     */
02249     void shrinkWrap ();
02250 
02251     /*@ManDoc: This function changes the size of this `PP_Array<T>' to newlen
02252                while preserving the value of as many array elements as
02253                possible.  If newlen is greater than the current length, the
02254                array is grown and the new elements have the value given by
02255                the default constructor for `T'.  If newlen is less than the
02256                current length the array is cropped with the remaining
02257                elements retaining their original values.
02258     */
02259     void resize (long newlen);
02260 
02261     /*@ManDoc: This function changes the size of this `PP_Array<T>' to newlen
02262                while preserving the value of as many array elements as
02263                possible.  If newlen is greater than the current length, the
02264                array is grown and the new elements have the value given by
02265                initialvalue.  If newlen is less than the current length the
02266                array is cropped with the remaining elements retaining their
02267                original values.
02268     */
02269     void resize (long     newlen,
02270                  const T& initialvalue);
02271     //
02272     //@ManDoc: Return number of elements in the array.
02273     //
02274     long length () const;
02275 
02276     /*@ManDoc: Return the maximum number of elements the array can hold
02277                without doing a `resize'.
02278     */
02279     long trueSize () const;
02280 
02281     /*@ManDoc: Returns a reference to the K'th element in this `PP_Array<T>'.
02282                The element can be modified through this reference.  The
02283                result can be used as an L-value.
02284     */
02285     T& operator[] (long K);
02286     //
02287     //@ManDoc: Same as above, except acts on const PP_Array's.
02288     //
02289     const T& operator[] (long K) const;
02290     //
02291     //@ManDoc: Different syntax for operator[] (long i).
02292     //
02293     T& get (long i);
02294     //
02295     //@ManDoc: Different syntax for const operator[] (long i).
02296     //
02297     const T& get (long i) const;
02298 
02299     /*@ManDoc: Returns pointer to vector of data.  This function breaks object
02300                encapsulation and should only be used for interfacing to
02301                Fortran subroutines.
02302     */
02303     T* dataPtr ();
02304     //
02305     //@ManDoc: Same as above for constant PP_Arrays.
02306     //
02307     const T* dataPtr () const;
02308     //
02309     //@ManDoc: Changes the i'th element of this `PP_Array<T>' to elem.
02310     //
02311     void set (long     i,
02312               const T& elem);
02313     //
02314     //@ManDoc: This function swaps the i'th and j'th element of the PP_Array.
02315     //
02316     void swap (long i,
02317                long j);
02318     //
02319     //@ManDoc: Test for equality.
02320     //
02321     bool operator== (const PP_Array<T>& rhs) const;
02322     //
02323     //@ManDoc: Test for inequality.
02324     //
02325     bool operator!= (const PP_Array<T>& rhs) const;
02326 
02327 protected:
02328     //
02329     // The true size of the PP_Array.
02330     //
02331     long truesize;
02332     //
02333     // The number of elements in the PP_Array.
02334     //
02335     long nelem;
02336     //
02337     // The array itself.
02338     //
02339     T* vp;
02340 
02341 private:
02342     //
02343     // This is disallowed.
02344     //
02345     PP_Array<T>& operator= (int);
02346 };
02347 
02348 //
02349 // Inlines.
02350 //
02351 
02352 template <class T>
02353 inline
02354 PP_Array<T>::PP_Array ()
02355 {
02356     nelem    = 0;
02357     vp       = new T[1];
02358     truesize = 1;
02359 }
02360 
02361 template <class T>
02362 inline
02363 PP_Array<T>::PP_Array (long len)
02364 {
02365     assert(len >= 0);
02366     nelem    = len;
02367     vp       = new T[len];
02368     truesize = nelem;
02369 }
02370 
02371 template <class T>
02372 inline
02373 void
02374 PP_Array<T>::clear ()
02375 {
02376     delete [] vp;
02377     vp       = 0;
02378     nelem    = 0;
02379     truesize = 0;
02380 }
02381 
02382 template <class T>
02383 inline
02384 PP_Array<T>::~PP_Array ()
02385 {
02386     clear();
02387 }
02388 
02389 template <class T>
02390 inline
02391 bool
02392 PP_Array<T>::ready () const
02393 {
02394     return vp != 0 && nelem != 0;
02395 }
02396 
02397 template <class T>
02398 inline
02399 long
02400 PP_Array<T>::length () const
02401 {
02402     return nelem;
02403 }
02404 
02405 template <class T>
02406 inline
02407 long
02408 PP_Array<T>::trueSize () const
02409 {
02410     return truesize;
02411 }
02412 
02413 template <class T>
02414 inline
02415 T&
02416 PP_Array<T>::operator[] (long i)
02417 {
02418     assert(vp != 0);
02419     assert(i >= 0 && i < nelem);
02420     return vp[i];
02421 }
02422 
02423 template <class T>
02424 inline
02425 const T&
02426 PP_Array<T>::operator[] (long i) const
02427 {
02428     assert(vp != 0);
02429     assert(i >= 0 && i < nelem);
02430     return vp[i];
02431 }
02432 
02433 template <class T>
02434 inline
02435 T&
02436 PP_Array<T>::get (long i)
02437 {
02438     assert(vp != 0);
02439     assert(i >= 0 && i < nelem);
02440     return vp[i];
02441 }
02442 
02443 template <class T>
02444 inline
02445 const T&
02446 PP_Array<T>::get (long i) const
02447 {
02448     assert(vp != 0);
02449     assert(i >= 0 && i < nelem);
02450     return vp[i];
02451 }
02452 
02453 template <class T>
02454 inline
02455 void
02456 PP_Array<T>::set (long     i,
02457                const T& elem)
02458 {
02459     assert(vp != 0);
02460     assert(i >= 0 && i < nelem);
02461     vp[i] = elem;
02462 }
02463 
02464 template <class T>
02465 inline
02466 T*
02467 PP_Array<T>::dataPtr ()
02468 {
02469     return vp;
02470 }
02471 
02472 template <class T>
02473 inline
02474 const T*
02475 PP_Array<T>::dataPtr () const
02476 {
02477     return vp;
02478 }
02479 
02480 template <class T>
02481 inline
02482 void
02483 PP_Array<T>::swap (long i,
02484                 long j)
02485 {
02486     assert(i >= 0 && i < nelem);
02487     assert(j >= 0 && j < nelem);
02488     T tmp = vp[i];
02489     vp[i] = vp[j];
02490     vp[j] = tmp;
02491 }
02492 
02493 template <class T>
02494 inline
02495 bool
02496 PP_Array<T>::operator!= (const PP_Array<T>& rhs) const
02497 {
02498     return !(operator==(rhs));
02499 }
02500 
02501 //
02502 // Non-inlined stuff.
02503 //
02504 
02505 template <class T>
02506 PP_Array<T>::PP_Array (long     len,
02507                  const T& initialValue)
02508 {
02509     assert(len >= 0);
02510     nelem = len;
02511     vp    = new T[len];
02512     truesize = nelem;
02513     for(long i = 0; i < nelem; ++i)
02514         vp[i] = initialValue;
02515 }
02516 
02517 template <class T>
02518 PP_Array<T>::PP_Array (const T* vec,
02519                  long     len)
02520 {
02521     assert(len >= 0);
02522     nelem = len;
02523     vp    = new T[len];
02524     truesize = nelem;
02525     for(long i = 0; i < nelem; ++i)
02526         vp[i] = vec[i];
02527 }
02528 
02529 template <class T>
02530 PP_Array<T>::PP_Array (const PP_Array<T>& a)
02531 {
02532     nelem = a.nelem;
02533     vp    = new T[nelem];
02534     truesize = nelem;
02535     for (long i = 0; i < nelem; i++)
02536         vp[i] = a.vp[i];
02537 }
02538 
02539 template <class T>
02540 PP_Array<T>&
02541 PP_Array<T>::operator= (const PP_Array<T>& sa)
02542 {
02543     if (this != &sa)
02544     {
02545         clear();
02546         vp       = new T[sa.nelem];
02547         nelem    = sa.nelem;
02548         truesize = nelem;
02549         for(long i = 0; i < nelem; i++)
02550             vp[i] = sa.vp[i];
02551     }
02552     return *this;
02553 }
02554 
02555 template <class T>
02556 inline
02557 void
02558 PP_Array<T>::resize (long newlen)
02559 {
02560     if (newlen == nelem)
02561         return;
02562     if (newlen <= truesize)
02563     {
02564         nelem = newlen;
02565         return;
02566     }
02567     T* newvp = new T[newlen];
02568     long len = Min(newlen,nelem);
02569     for (long i = 0; i < len; i++)
02570         newvp[i] = vp[i];
02571     delete [] vp;
02572     vp = newvp;
02573     nelem = newlen;
02574     truesize = newlen;
02575 }
02576 
02577 template <class T>
02578 inline
02579 void PP_Array<T>::resize (long     newlen,
02580                        const T& initialValue)
02581 {
02582     if (newlen == nelem)
02583         return;
02584     if (newlen <= truesize)
02585     {
02586         for(long i = nelem; i < newlen; ++i)
02587             vp[i] = initialValue;
02588         nelem = newlen;
02589         return;
02590     }
02591     T* newvp = new T[newlen];
02592     long len = Min(newlen,nelem);
02593     long i;
02594     for (i = 0; i < len; i++)
02595         newvp[i] = vp[i];
02596     for(i = len; i < newlen; ++i)
02597         newvp[i] = initialValue;
02598     delete [] vp;
02599     vp = newvp;
02600     nelem = newlen;
02601     truesize = newlen;
02602 }
02603 
02604 template <class T>
02605 void
02606 PP_Array<T>::reserve (long _truesize)
02607 {
02608     if (_truesize > truesize)
02609     {
02610         T* newvp = new T[_truesize];
02611         for (long i = 0; i < nelem; i++)
02612             newvp[i] = vp[i];
02613         delete [] vp;
02614         vp = newvp;
02615         truesize = _truesize;
02616     }
02617 }
02618 
02619 template <class T>
02620 void
02621 PP_Array<T>::shrinkWrap ()
02622 {
02623     if (nelem != truesize)
02624     {
02625         T* newvp = new T[nelem];
02626         for (long i = 0; i < nelem; i++)
02627             newvp[i] = vp[i];
02628         delete [] vp;
02629         vp = newvp;
02630         truesize = nelem;
02631     }
02632 }
02633 
02634 template <class T>
02635 bool
02636 PP_Array<T>::operator== (const PP_Array<T>& rhs) const
02637 {
02638     if (length() != rhs.length())
02639         return false;
02640 
02641     for (long i = 0; i < length(); ++i)
02642         if (!((*this)[i] == rhs[i]))
02643             return false;
02644 
02645     return true;
02646 }
02647 
02648 
02649 
02650 // -----------------------------------------------------------------
02651 // ----------------------- COMMENTS -------------------------------
02652 // -----------------------------------------------------------------
02653 // The ParmParse class implements a simple database for the storage
02654 // and retrieval of command-line and input-file arguments.  The
02655 // entries are stored in a static table in (name,value_list) pairs.
02656 //
02657 // The format of the input file is a series of OPTIONS and DEFINITIONS.
02658 //
02659 // An OPTION is an entry of the form:  -<name> and has no associated list
02660 // of values.  For example, the command line:
02661 //        prog -verbose -no_opt
02662 // has two options: "verbose" and "no_opt".
02663 //
02664 // A DEFINITION is of the form  <name> = <value> <value> ...
02665 // The equal sign is important since the list of values can span multiple
02666 // lines.
02667 //
02668 // Comments in an input file include all text from a '#' character to the
02669 // end of the line.  Here is an example input file:
02670 //
02671 //   -no_garbage                # an OPTION
02672 //   niter = 100                # niter is an integer
02673 //   title = "Double Wammy"     # example of a string with spaces
02674 //   cell_size = 0.5 0.75       # cell spacing in each dimension
02675 //   plot.var = Density 1 10    # a list of values
02676 //   plot.var = Energy  5 12    # another list of values
02677 //   bigarray = 1 2 3 4 5 6 7 8 # first part of array
02678 //              9 10 11 12      # continuation of bigarray
02679 //   test = apple "boy blue" 10 20 30 40
02680 //   FILE = prob_file           # insert contents of this "prob_file" here
02681 //
02682 // The "FILE = <filename>" definition is special.  Rather than just
02683 // adding this entry to the database, it reads the contents of <filename>
02684 // into the database.
02685 //
02686 // ParmParse stores all entries in a static table which is built the
02687 // first time a ParmParse object is constructed (usually in main()).
02688 // Subsequent invocations have access to this table.
02689 // A ParmParse constructor has an optional "prefix" argument that will
02690 // limit the searches to only those entries of the table with this prefix
02691 // in name.  For example:
02692 //     ParmParse pp("plot");
02693 // will find only those entries with name given by "plot.<string>".
02694 //
02695 // All values in the table are stored as strings.  For example, the
02696 // values of "cell_size" in the above input file are stored as the
02697 // strings "0.5" and "0.75".  These strings can be returned as either
02698 // string of numeric values by the query functions.
02699 // Character strings with spaces must be delimited by double quotes
02700 // in the input file but the quotes are stripped before they are entered
02701 // into the table.  For example, 'title' in the above input file has a
02702 // single value, the string 'Double Wammy' (without the quotes).
02703 // Each value in the list associated with a definition can be referred to
02704 // by its index number.  The index numbers start at 0 just like an array
02705 // in the C programming language.  Consider the definition of "test" in
02706 // the above input file.  The first value 'apple'is a string with index
02707 // 0.  The second value 'boy blue' is a string with index 1.  The
02708 // remaining four values are integers indexed 2, 3, 4, and 5.
02709 //
02710 // For a string value to represent an integer or float it must fit the
02711 // following regular experssion:
02712 //   Sign    ::= '+' | '-'
02713 //   Digit   ::= '0' | '1' | ... | '9'
02714 //   Integer ::= [Sign]Digit+
02715 //   Exp     ::= ('e'|'E')Integer
02716 //   Float   ::= ( Integer[.Digit*][Exp] | [Integer].Digit+[Exp] )
02717 //
02718 // Where '+' indicates one or more occurences, '*' represents zero or
02719 // more occurences, '|' means one or the other and '[]' represents zero
02720 // or one occurence.
02721 //
02722 // Note that floats and doubles have the same string representation and
02723 // that the FORTRAN "double" exponent format is not supported.
02724 // That is, 1.0d+3 is not a valid representation of a floating point
02725 // number but that 1.0e+3 is acceptable.
02726 //
02727 // There are a host of functions allowing the user to query the database
02728 // and retrieve values.  Here are some general rules about the names of
02729 // the member functions:
02730 //
02731 // * Functions with the string "get" in their names attempt to get a
02732 //   value or an array of values from the table.  They generate a
02733 //   run-time error if they are not successful.
02734 //
02735 // * Functions with the string "query" in their names attempt to get a
02736 //   value or an array of values from the table.  They return the value 1
02737 //   (true) if they are successful and 0 (false) if not.
02738 //
02739 // * Functions with the string "arr" in their names get an Array of
02740 //   values from the given entry in the table.  The array argument is
02741 //   resized (if necessary) to hold all the values requested.
02742 //
02743 // * Functions without the string "arr" in their names get single
02744 //   values from the given entry in the table.
02745 //
02746 // The following is a code sample showing how to use ParmParse:
02747 //
02748 // main(int argc, char **argv)
02749 // {
02750 //     char* in_file_name = argv[1];
02751 //     ParmParse pp(argc-2, argv+2, 0, in_file_name);
02752 //
02753 //     // was the "-verbose" command line argument set?
02754 //     int verbose = pp.contains("verbose");
02755 //
02756 //     // Query table for value of "niter".  If not in table
02757 //     // then set to default value
02758 //     if (!pp.query("niter",niter)) niter = 20;
02759 //
02760 //     // read array of cell sizes if in table
02761 //     std::vector<float> dx;
02762 //     if (nx=pp.countval("cell_size")) {
02763 //        // get nx values starting at index 0 and store in dx.
02764 //        // dx is automatically resized here.
02765 //        pp.getarr("cell_size",dx,0,nx);
02766 //     }
02767 // }
02768 //
02769 // void do_graphics()
02770 // {
02771 //    //
02772 //    // Will only query entries with the "plot" prefix:
02773 //    //
02774 //    ParmParse pp("plot");
02775 //    //
02776 //    // Read all variables with "plot.var" keyword.
02777 //    //
02778 //    std::string var_name;
02779 //    std::vector<int> range;
02780 //    int num = pp.countname("var");
02781 //    //
02782 //    // Element 0 in list is a string.
02783 //    //
02784 //    pp.get("var",var_name,0);
02785 //    //
02786 //    // Elements 1 and 2 are integers.
02787 //    // Note that "range" will be resized to hold 2 elements.
02788 //    //
02789 //    pp.getarr("var",range,1,2);
02790 //    cout << "variable = " << var_name << "lo, hi = ",
02791 //         << range[0] << " " << range[1] << endl;
02792 // }
02793 // -----------------------------------------------------------------
02794 // -----------------------  END COMMENTS ---------------------------
02795 // -----------------------------------------------------------------
02796 
02797 //
02798 // Forward reference to private class.
02799 //
02800 class PP_entry;
02801 
02802 //@Man:
02803 //@Memo: Parse Parameters From Command Line and Input Files
02804 /*@Doc:
02805 
02806   The ParmParse class is used to interpret parameters passed in to a program
02807   from the command line and an arbitrary collection of input files.  The
02808   parameters are stored in static table that can be queried by any object
02809   of type ParmParse.  A parameter can be either an "option" (usually
02810   specified on the command line) or a "definition".  An option is of the form
02811   "-<name>" and is stored in the table without the hyphen.  A definition is
02812   of the form "<name> = <value><value>...<value>".  It is stored in the table
02813   as a name, value-list pair.
02814 
02815   In the following example, verbose and no\_opt are stored in the table as
02816   options.  niter is a definition with the single integer value 10; name is
02817   a definition with the string value "big code" and dx is a definition with
02818   the two floating point values 0.5 and 0.75.
02819 
02820   prog -verbose -no\_opt niter = 10 name = "big code" dx = 0.5 0.75
02821 
02822   The ParmParse class has two constructors.  The first is responsible for
02823   building the table and is usually called by the main routine of an
02824   application.  It has arguments for the command line argc and argv parameters,
02825   as well as an optional filename argument for reading definitions from an
02826   input file.  The table is built by reading the input file first (if it
02827   exists) with the command line arguments added to the end of the table.
02828   The order of a definition in the table is significant, so command line
02829   parameters can be used to override definitions in the input file.  A
02830   definition of the explicit form: FILE=<filename> is not added to the table
02831   but is a directive to include the named file at that point in the table.
02832 
02833   The second constructor is generally used by other classes in the code.  It
02834   permits access to the table via a large collection of query functions.
02835   Both constructors have an optional prefix argument that narrows the search
02836   to entries in the table with the same prefix.  For example, let PlanR be a
02837   ParmParse object with code prefix "ope".  PlanR.get("val",v) will look for
02838   an entry in the parameter list of the form: ope.val==<value>, and will
02839   reject all entries not starting with the correct code prefix.
02840 
02841   The query functions search the table for definition names that match a given
02842   string (and prefix) and return values from the corresponding value list.
02843   The values can be returned as ints, Array<int>s, floats, std::vector<float>s,
02844   doubles, std::vector<double>s, std::strings, or std::vector<std::sring>s.  All values in the
02845   table are stored as PP_String objects, but if an int, float, or double is
02846   requested, the translation is done automatically.  In the previous example,
02847   the value of niter could be returned as either an std::string, an int, a double,
02848   or a float.  The values of dx can be returned as std::strings, floats, or
02849   doubles, but the value of name can be returned only as an std::string.
02850 
02851   Comments in an input file include all text from a `\#' character to the
02852   end of the line.  Here is a sample input file:
02853 
02854      -no\_garbage
02855 
02856      niter = 100
02857 
02858      title = "Double Wammy"
02859 
02860      cell\_size = 0.5 0.75
02861 
02862      plot.var = Density 1 10
02863 
02864      plot.var = Energy  5 12
02865 
02866      bigarray = 1 2 3 4 5 6 7 8
02867 
02868                 9 10 11 12
02869 
02870      test = apple "boy blue" 10 20 30 40
02871 
02872      FILE = prob\_file
02873 */
02874 
02875 class ParmParse
02876 {
02877     friend class PP_entry;
02878 public:
02879 
02881 
02882     /*@ManDoc: Construct an initial ParmParse object from the argc and argv
02883                passed in to main().  An error will be signalled if another
02884                ParmParse object currently exists.  If parfile is specified,
02885                read the parameters in from that file first and then append
02886                those derived from argv to the table.  If prefix is specified,
02887                load this string as the code prefix for this particular
02888                ParmParse object.
02889     */
02890     ParmParse (int         argc,
02891                char**      argv,
02892                const char* prefix  = 0,
02893                const char* parfile = 0);
02894 
02895     /*@ManDoc: Construct an additional ParmParse object sharing the same
02896                internal table as any other such objects in existence.  If
02897                prefix is specified, load this string as the code prefix
02898                for this particular ParmParse object.
02899     */
02900     /*explicit*/ ParmParse (const char* prefix = 0);
02901 
02902     /*@ManDoc: The destructor.  The internal static table will only be deleted
02903                if there are no other ParmParse objects in existence.
02904     */
02905     ~ParmParse();
02906 
02908 
02910 
02913     bool contains (const char* name);
02914 
02916 
02919     bool contains (const std::string& name);
02920 
02921     /*@ManDoc: Returns the number of values associated with nth occurence of
02922                name (prepended with the prefix) in the table.  n == -1 implies
02923                the last occurence.
02924     */
02925     int countval (const char* name,
02926                   int         n = -1);
02927 
02928     /*@ManDoc: Returns the number of times the given name (prepended with
02929                prefix) appears in the table.
02930     */
02931     int countname (const char* name);
02932 
02933     /*@ManDoc: Returns the number of times the given name (prepended with
02934                prefix) appears in the table.
02935     */
02936     int countname (const std::string& name);
02937     //
02938     //@ManDoc: Write the contents of the table in ASCII to the ostream.
02939     //
02940     void dumpTable (std::ostream& os);
02941 
02943 
02945 
02946     /*@ManDoc: Get the ival'th value of last occurrence of the requested name.
02947                If successful, the value is converted to an int and stored
02948                in reference ref.  If the name does not exist or
02949                ival'th value does not exist, or if the printed representation
02950                of the value cannot be converted to an int, an error message is
02951                output and the program halts.   Note that ival == 0 is the first
02952                value in the list.
02953     */
02954     void get (const char* name,
02955               int&        ref,
02956               int         ival=0);
02957 
02958   /*@ManDoc: Get the ival'th value of last occurrence of the
02959                requested name.  If successful, the value is converted
02960                to an int and stored in reference ref.  Returns 1 if
02961                successful.  Returns 0 if the name does not exist.  If
02962                ival'th value does not exist, or if the printed
02963                representation of the value cannot be converted to an
02964                int, an error message is output and the program halts.
02965                Note that ival == 0 is the first value in the list.  
02966     */
02967     int query (const char* name,
02968                int&        ref,
02969                int         ival=0);
02970 
02971     /*@ManDoc: Get the ival'th value of last occurrence of the requested name.
02972                If successful, the value is converted to a float and stored
02973                in reference ref.  If the name does not exist or
02974                ival'th value does not exist, or if the printed representation
02975                of the value cannot be converted to a float, an error message is
02976                output and the program halts.   Note that ival == 0 is the first
02977                value in the list.
02978     */
02979     void get (const char* name,
02980               float&      ref,
02981               int         ival=0);
02982 
02983   /*@ManDoc: Get the ival'th value of last occurrence of the
02984                requested name.  If successful, the value is converted
02985                to a float and stored in reference ref.  Returns 1 if
02986                successful.  Returns 0 if the name does not exist.  If
02987                ival'th value does not exist, or if the printed
02988                representation of the value cannot be converted to a float,
02989                an error message is output and the program halts.
02990                Note that ival == 0 is the first value in the list.  
02991     */
02992     int query (const char* name,
02993                float&      ref,
02994                int         ival=0);
02995 
02996 
02997     /*@ManDoc: Get the ival'th value of last occurrence of the requested name.
02998                If successful, the value is converted to a double and stored
02999                in reference ref.  If the name does not exist or
03000                ival'th value does not exist, or if the printed representation
03001                of the value cannot be converted to a double, an error message is
03002                output and the program halts.   Note that ival == 0 is the first
03003                value in the list.
03004     */
03005     void get (const char* name,
03006               double&     ref,
03007               int         ival=0);
03008 
03009   /*@ManDoc: Get the ival'th value of last occurrence of the
03010                requested name.  If successful, the value is converted
03011                to a double and stored in reference ref.  Returns 1 if
03012                successful.  Returns 0 if the name does not exist.  If
03013                ival'th value does not exist, or if the printed
03014                representation of the value cannot be converted to a double,
03015                an error message is output and the program halts.
03016                Note that ival == 0 is the first value in the list.  
03017     */
03018     int query (const char* name,
03019                double&     ref,
03020                int         ival=0);
03021 
03022     /*@ManDoc: Get the ival'th value of last occurrence of the requested name.
03023                If successful, the value is converted to a string and stored
03024                in reference ref.  If the name does not exist or
03025                ival'th value does not exist, or if the printed representation
03026                of the value cannot be converted to a string, an error message is
03027                output and the program halts.   Note that ival == 0 is the first
03028                value in the list.
03029     */
03030     void get (const char*  name,
03031               std::string& ref,
03032               int          ival=0);
03033 
03034   /*@ManDoc: Get the ival'th value of last occurrence of the
03035                requested name.  If successful, the value is converted
03036                to a string and stored in reference ref.  Returns 1 if
03037                successful.  Returns 0 if the name does not exist.  If
03038                ival'th value does not exist, or if the printed
03039                representation of the value cannot be converted to a string,
03040                an error message is output and the program halts.
03041                Note that ival == 0 is the first value in the list.  
03042     */
03043     int query (const char*  name,
03044                std::string& ref,
03045                int          ival=0);
03046 
03048 
03049     /*@ManDoc: Gets a std::vector<int> of num\_val values from last
03050                occurrence of given name.  If successful, the values
03051                are converted to an int and stored in the
03052                std::vector<int> object ref.  ref is resized (if
03053                necessary) to hold num\_val values.  The value in the
03054                list indexed by start\_ix is copied into
03055                std::vector<int>[0], std::vector<int>[1] holds
03056                start\_ix+1, etc.  If there are fewer than start\_ix +
03057                num\_val values associated with the last occurrence, or
03058                if some of the values cannot be converted to an int, an
03059                error message is reported and the program halts.  
03060     */
03061     void getarr (const char* name,
03062                  Vector<int>& ref,
03063                  int         start_ix,
03064                  int         num_val);
03065 
03066     void getarr (const char* name,
03067                  std::vector<int>& ref,
03068                  int         start_ix,
03069                  int         num_val);
03070 
03071     /*@ManDoc: Gets a std::vector<int> of num\_val values from last
03072                occurrence of given name.  If successful, the values
03073                are converted to an int and stored in the
03074                std::vector<int> object ref.  ref is resized (if
03075                necessary) to hold num\_val values.  The value in the
03076                list indexed by start\_ix is copied into
03077                std::vector<int>[0], std::vector<int>[1] holds
03078                start\_ix+1, etc.  Returns 0 if the name does not
03079                exist.  If there are fewer than start\_ix + num\_val
03080                values associated with the last occurrence, or if some
03081                of the values cannot be converted to an int, an error
03082                message is reported and the program halts.  
03083     */
03084     int queryarr (const char* name,
03085                   Vector<int>& ref,
03086                   int         start_ix,
03087                   int         num_val);
03088 
03089 
03090     int queryarr (const char* name,
03091                   std::vector<int>& ref,
03092                   int         start_ix,
03093                   int         num_val);
03094 
03095     /*@ManDoc: Gets a std::vector<float> of num\_val values from last
03096                occurrence of given name.  If successful, the values
03097                are converted to a float and stored in the
03098                std::vector<float> object ref.  ref is resized (if
03099                necessary) to hold num\_val values.  The value in the
03100                list indexed by start\_ix is copied into
03101                std::vector<float>[0], std::vector<float>[1] holds
03102                start\_ix+1, etc.  If there are fewer than start\_ix +
03103                num\_val values associated with the last occurrence, or
03104                if some of the values cannot be converted to a float, an
03105                error message is reported and the program halts.  
03106     */
03107     void getarr (const char*   name,
03108                  Vector<float>& ref,
03109                  int           start_ix,
03110                  int           num_val);
03111 
03112 
03113     void getarr (const char*   name,
03114                  std::vector<float>& ref,
03115                  int           start_ix,
03116                  int           num_val);
03117 
03118 
03119     /*@ManDoc: Gets a std::vector<float> of num\_val values from last
03120                occurrence of given name.  If successful, the values
03121                are converted to a float and stored in the
03122                std::vector<float> object ref.  ref is resized (if
03123                necessary) to hold num\_val values.  The value in the
03124                list indexed by start\_ix is copied into
03125                std::vector<float>[0], std::vector<float>[1] holds
03126                start\_ix+1, etc.  Returns 0 if the name does not
03127                exist.  If there are fewer than start\_ix + num\_val
03128                values associated with the last occurrence, or if some
03129                of the values cannot be converted to a float, an error
03130                message is reported and the program halts.  
03131     */
03132     int queryarr (const char*   name,
03133                   Vector<float>& ref,
03134                   int           start_ix,
03135                   int           num_val);
03136 
03137 
03138     int queryarr (const char*   name,
03139                   std::vector<float>& ref,
03140                   int           start_ix,
03141                   int           num_val);
03142 
03143 
03144     /*@ManDoc: Gets a std::vector<double> of num\_val values from last
03145                occurrence of given name.  If successful, the values
03146                are converted to a double and stored in the
03147                std::vector<double> object ref.  ref is resized (if
03148                necessary) to hold num\_val values.  The value in the
03149                list indexed by start\_ix is copied into
03150                std::vector<double>[0], std::vector<double>[1] holds
03151                start\_ix+1, etc.  If there are fewer than start\_ix +
03152                num\_val values associated with the last occurrence, or
03153                if some of the values cannot be converted to a double, an
03154                error message is reported and the program halts.  
03155     */
03156     void getarr (const char*    name,
03157                  Vector<double>& ref,
03158                  int            start_ix,
03159                  int            num_val);
03160 
03161     void getarr (const char*    name,
03162                  std::vector<double>& ref,
03163                  int            start_ix,
03164                  int            num_val);
03165 
03166     /*@ManDoc: Gets a std::vector<double> of num\_val values from last
03167                occurrence of given name.  If successful, the values
03168                are converted to a double and stored in the
03169                std::vector<double> object ref.  ref is resized (if
03170                necessary) to hold num\_val values.  The value in the
03171                list indexed by start\_ix is copied into
03172                std::vector<double>[0], std::vector<double>[1] holds
03173                start\_ix+1, etc.  Returns 0 if the name does not
03174                exist.  If there are fewer than start\_ix + num\_val
03175                values associated with the last occurrence, or if some
03176                of the values cannot be converted to a double, an error
03177                message is reported and the program halts.  
03178     */
03179     int queryarr (const char*    name,
03180                   Vector<double>& ref,
03181                   int            start_ix,
03182                   int            num_val);
03183 
03184     int queryarr (const char*    name,
03185                   std::vector<double>& ref,
03186                   int            start_ix,
03187                   int            num_val);
03188 
03189     /*@ManDoc: Gets a std::vector<string> of num\_val values from last
03190                occurrence of given name.  If successful, the values
03191                are converted to a string and stored in the
03192                std::vector<string> object ref.  ref is resized (if
03193                necessary) to hold num\_val values.  The value in the
03194                list indexed by start\_ix is copied into
03195                std::vector<string>[0], std::vector<string>[1] holds
03196                start\_ix+1, etc.  If there are fewer than start\_ix +
03197                num\_val values associated with the last occurrence, or
03198                if some of the values cannot be converted to a string, an
03199                error message is reported and the program halts.  
03200     */
03201     void getarr (const char*     name,
03202                  Vector<std::string>& ref,
03203                  int             start_ix,
03204                  int             num_val);
03205 
03206     void getarr (const char*     name,
03207                  std::vector<std::string>& ref,
03208                  int             start_ix,
03209                  int             num_val);
03210 
03211     /*@ManDoc: Gets a std::vector<string> of num\_val values from last
03212                occurrence of given name.  If successful, the values
03213                are converted to a string and stored in the
03214                std::vector<string> object ref.  ref is resized (if
03215                necessary) to hold num\_val values.  The value in the
03216                list indexed by start\_ix is copied into
03217                std::vector<string>[0], std::vector<string>[1] holds
03218                start\_ix+1, etc.  Returns 0 if the name does not
03219                exist.  If there are fewer than start\_ix + num\_val
03220                values associated with the last occurrence, or if some
03221                of the values cannot be converted to a string, an error
03222                message is reported and the program halts.  
03223     */
03224     int queryarr (const char*               name,
03225                   Vector<std::string>& ref,
03226                   int                       start_ix,
03227                   int                       num_val);
03228     //
03229 
03230     int queryarr (const char*               name,
03231                   std::vector<std::string>& ref,
03232                   int                       start_ix,
03233                   int                       num_val);
03234     //
03235     // This should be protected, but cfront-derived compilers complain :-(
03236     //
03237     enum PPType
03238     {
03239         ppDefn,
03240         ppOption,
03241         ppInt,
03242         ppFloat,
03243         ppDouble,
03244         ppString,
03245         ppEQ_sign,
03246         ppEOF
03247     };
03248 protected:
03249 
03250     //
03251     // Table of entries common to all objects.
03252     //
03253     static PP_List<PP_entry*> table;
03254     //
03255     // Command line arguments.
03256     //
03257     static int    xargc;
03258     static char** xargv;
03259     //
03260     // Keep track of number of ParmParse objects out there.
03261     //
03262     static int num_obj;
03263     //
03264     // Parses string and builds table.
03265     //
03266     void bldTable (const char*      str,
03267                    int              lenstr,
03268                    PP_List<PP_entry*>& tab);
03269     //
03270     // Add defn to table, check for file inclusion.
03271     //
03272     void addDefn (PP_String&         def,
03273                   PP_List<PP_String>&   val,
03274                   PP_List<PP_entry*>& tab);
03275     //
03276     // Reads file into string then parses it with call to bldTable.
03277     //
03278     void read_file (const char*      fname,
03279                     PP_List<PP_entry*>& tab);
03280     //
03281     // Lexical analyser called by bldTable.
03282     //
03283     PPType getToken (const char*,
03284                      int&,
03285                      int,
03286                      char*);
03287     //
03288     // Reclaims memory used in table.
03289     //
03290     void rmTable ();
03291     //
03292     // Prefix used in keyword search.
03293     //
03294     PP_String thePrefix;
03295     //
03296     // Used by constructor to build table.
03297     //
03298     void ppinit (const char* parfile);
03299     //
03300     // Find n'th occurence of name in table.
03301     //
03302     const PP_entry* ppindex (int         n,
03303                              const char* name) const;
03304     //
03305     // Get ival_th value of k_th occurence of given name.
03306     // If k_th occurence does not exist or ival_th value does
03307     // not exist or if ival_type does not match with type, an
03308     // error message is reported and the program halts.
03309     // If successful, value is stored in ptr.
03310     // same as above but searches for last occurence of name.
03311     //
03312     void  getval (const char* name,
03313                   const PPType type,
03314                   void*        ptr,
03315                   int          ival,
03316                   int          k=-1);
03317     //
03318     // Get an array of values.
03319     //
03320     void getarr (const char*  name,
03321                  const PPType type,
03322                  void*        ptr,
03323                  int          start_ix,
03324                  int          num_val,
03325                  int          k=-1);
03326     int queryval (const char*  name,
03327                   const PPType type,
03328                   void*        ptr,
03329                   int          ival,
03330                   int          k=-1);
03331     int queryarr (const char*  name,
03332                   const PPType type,
03333                   void*        ptr,
03334                   int          start_ix,
03335                   int          num_val,
03336                   int          k=-1);
03337 
03338     bool isInteger (const PP_String& str,
03339                     int&           val);
03340     int isDouble (const PP_String& str,
03341                   double&        val);
03342 };
03343 
03344 class PP_entry
03345 {
03346 private:
03347     friend class ParmParse;
03348     PP_entry() {}
03349     PP_entry (PP_String&          name,
03350               ParmParse::PPType typ,
03351               PP_List<PP_String>&    vals);
03352     ~PP_entry() {}
03353 
03354     PP_String               defname;
03355     ParmParse::PPType     deftype;
03356     PP_Array<PP_String>        val;
03357 
03358     void dump (std::ostream& os) const;
03359 };
03360 
03361 //
03362 // Inlines.
03363 //
03364 
03365 inline
03366 int
03367 ParmParse::countval (const char* name,
03368                      int         n)
03369 {
03370     //
03371     // First find n'th occurance of name in table.
03372     //
03373     const PP_entry* def = ppindex(n,name);
03374     return def == 0 ? 0 : def->val.length();
03375 }
03376 
03377 
03378 inline
03379 void
03380 ParmParse::get (const char* name,
03381                 int&        ptr,
03382                 int ival)
03383 {
03384     getval(name,ppInt,&ptr,ival,-1);
03385 }
03386 
03387 
03388 inline
03389 int
03390 ParmParse::query (const char* name,
03391                   int&        ptr,
03392                   int         ival)
03393 {
03394     return queryval(name,ppInt,&ptr,ival,-1);
03395 }
03396 
03397 
03398 inline
03399 void
03400 ParmParse::get (const char* name,
03401                 float&      ptr,
03402                 int         ival)
03403 {
03404     getval(name,ppFloat,&ptr,ival,-1);
03405 }
03406 
03407 
03408 inline
03409 int
03410 ParmParse::query (const char* name,
03411                   float&      ptr,
03412                   int         ival)
03413 {
03414     return queryval(name,ppFloat,&ptr,ival,-1);
03415 }
03416 
03417 
03418 inline
03419 void
03420 ParmParse::get (const char* name,
03421                 double&     ptr,
03422                 int         ival)
03423 {
03424     getval(name,ppDouble,&ptr,ival,-1);
03425 }
03426 
03427 
03428 inline
03429 int
03430 ParmParse::query (const char* name,
03431                   double&     ptr,
03432                   int         ival)
03433 {
03434     return queryval(name,ppDouble,&ptr,ival,-1);
03435 }
03436 
03437 
03438 inline
03439 void
03440 ParmParse::get (const char*  name,
03441                 std::string& ptr,
03442                 int          ival)
03443 {
03444     PP_String pp_string;
03445     getval(name,ppString,&pp_string,ival,-1);
03446     ptr = pp_string.c_str();
03447 }
03448 
03449 
03450 inline
03451 int
03452 ParmParse::query (const char*  name,
03453                   std::string& ptr,
03454                   int          ival)
03455 {
03456     PP_String pp_string;
03457     int status = queryval(name,ppString,&pp_string,ival,-1);
03458     if (status != 0) 
03459       ptr = pp_string.c_str();
03460     return status;
03461 }
03462 
03463 
03464 inline
03465 void
03466 ParmParse::getarr (const char* name,
03467                    std::vector<int>& ptr,
03468                    int         start_ix,
03469                    int         num_val)
03470 {
03471     if (ptr.size() < num_val)
03472         ptr.resize(num_val);
03473     int* c_array = new int[num_val];
03474     getarr(name,ppInt,c_array,start_ix,num_val,-1);
03475     for (int i = 0; i < num_val; ++i)
03476     {
03477         ptr[i] = c_array[i];
03478     }
03479     delete[] c_array;
03480 }
03481 
03482 
03483 inline
03484 void
03485 ParmParse::getarr (const char* name,
03486                    Vector<int>& ptr,
03487                    int         start_ix,
03488                    int         num_val)
03489 {
03490     if (ptr.size() < num_val)
03491         ptr.resize(num_val);
03492     int* c_array = new int[num_val];
03493     getarr(name,ppInt,c_array,start_ix,num_val,-1);
03494     for (int i = 0; i < num_val; ++i)
03495     {
03496         ptr[i] = c_array[i];
03497     }
03498     delete[] c_array;
03499 }
03500 
03501 
03502 inline
03503 int
03504 ParmParse::queryarr (const char* name,
03505                      std::vector<int>& ptr,
03506                      int         start_ix,
03507                      int         num_val)
03508 {
03509     if (ptr.size() < num_val)
03510         ptr.resize(num_val);
03511     int* c_array = new int[num_val];
03512     int status = queryarr(name,ppInt,c_array,start_ix,num_val,-1);
03513     if (status != 0 ) 
03514     {
03515       for (int i = 0; i < num_val; ++i)
03516       {
03517         ptr[i] = c_array[i];
03518       }
03519     }
03520     return status;
03521 }
03522 
03523 inline
03524 int
03525 ParmParse::queryarr (const char* name,
03526                      Vector<int>& ptr,
03527                      int         start_ix,
03528                      int         num_val)
03529 {
03530     if (ptr.size() < num_val)
03531         ptr.resize(num_val);
03532     int* c_array = new int[num_val];
03533     int status = queryarr(name,ppInt,c_array,start_ix,num_val,-1);
03534     if (status != 0 ) 
03535     {
03536       for (int i = 0; i < num_val; ++i)
03537       {
03538         ptr[i] = c_array[i];
03539       }
03540     }
03541     return status;
03542 }
03543 
03544 
03545 inline
03546 void
03547 ParmParse::getarr (const char*   name,
03548                    std::vector<float>& ptr,
03549                    int           start_ix,
03550                    int           num_val)
03551 {
03552     if (ptr.size() < num_val)
03553         ptr.resize(num_val);
03554     float* c_array = new float[num_val];
03555     getarr(name,ppFloat,c_array,start_ix,num_val,-1);
03556     for (int i = 0; i < num_val; ++i)
03557     {
03558         ptr[i] = c_array[i];
03559     }
03560     delete[] c_array;
03561 }
03562 
03563 inline
03564 void
03565 ParmParse::getarr (const char*   name,
03566                    Vector<float>& ptr,
03567                    int           start_ix,
03568                    int           num_val)
03569 {
03570     if (ptr.size() < num_val)
03571         ptr.resize(num_val);
03572     float* c_array = new float[num_val];
03573     getarr(name,ppFloat,c_array,start_ix,num_val,-1);
03574     for (int i = 0; i < num_val; ++i)
03575     {
03576         ptr[i] = c_array[i];
03577     }
03578     delete[] c_array;
03579 }
03580 
03581 
03582 inline
03583 int
03584 ParmParse::queryarr (const char*   name,
03585                      std::vector<float>& ptr,
03586                      int           start_ix,
03587                      int           num_val)
03588 {
03589     if (ptr.size() < num_val)
03590         ptr.resize(num_val);
03591     float* c_array = new float[num_val];
03592     int status = queryarr(name,ppFloat,c_array,start_ix,num_val,-1);
03593     if (status != 0) 
03594     {
03595       for (int i = 0; i < num_val; ++i)
03596       {
03597         ptr[i] = c_array[i];
03598       }
03599     }
03600     delete[] c_array;
03601     return status;
03602 }
03603 
03604 
03605 inline
03606 int
03607 ParmParse::queryarr (const char*   name,
03608                      Vector<float>& ptr,
03609                      int           start_ix,
03610                      int           num_val)
03611 {
03612     if (ptr.size() < num_val)
03613         ptr.resize(num_val);
03614     float* c_array = new float[num_val];
03615     int status = queryarr(name,ppFloat,c_array,start_ix,num_val,-1);
03616     if (status != 0) 
03617     {
03618       for (int i = 0; i < num_val; ++i)
03619       {
03620         ptr[i] = c_array[i];
03621       }
03622     }
03623     delete[] c_array;
03624     return status;
03625 }
03626 
03627 
03628 inline
03629 void
03630 ParmParse::getarr (const char*    name,
03631                    std::vector<double>& ptr,
03632                    int            start_ix,
03633                    int            num_val)
03634 {
03635     if (ptr.size() < num_val)
03636         ptr.resize(num_val);
03637     double* c_array = new double[num_val];
03638     int status = queryarr(name,ppDouble,c_array,start_ix,num_val,-1);
03639     if (status == 0)
03640     {
03641       cerr << "ParmParse::getarr(): " 
03642            << name 
03643            << " not found in table" << endl;
03644       dumpTable(cerr);      
03645       MayDay::Abort();
03646     }
03647     for (int i = 0; i < num_val; ++i)
03648     {
03649         ptr[i] = c_array[i];
03650     }
03651     delete[] c_array;
03652 }
03653 
03654 
03655 inline
03656 void
03657 ParmParse::getarr (const char*    name,
03658                    Vector<double>& ptr,
03659                    int            start_ix,
03660                    int            num_val)
03661 {
03662     if (ptr.size() < num_val)
03663         ptr.resize(num_val);
03664     double* c_array = new double[num_val];
03665     int status = queryarr(name,ppDouble,c_array,start_ix,num_val,-1);
03666     if (status == 0)
03667     {
03668       cerr << "ParmParse::getarr(): " 
03669            << name 
03670            << " not found in table" << endl;
03671       dumpTable(cerr);      
03672       MayDay::Abort();
03673     }
03674     for (int i = 0; i < num_val; ++i)
03675     {
03676         ptr[i] = c_array[i];
03677     }
03678     delete[] c_array;
03679 }
03680 
03681 
03682 inline
03683 int
03684 ParmParse::queryarr (const char*    name,
03685                      std::vector<double>& ptr,
03686                      int            start_ix,
03687                      int            num_val)
03688 {
03689     if (ptr.size() < num_val)
03690         ptr.resize(num_val);
03691     double* c_array = new double[num_val];
03692     int status = queryarr(name,ppDouble,c_array,start_ix,num_val,-1);
03693     if (status != 0) 
03694     {
03695       for (int i = 0; i < num_val; ++i)
03696       {
03697         ptr[i] = c_array[i];
03698       }
03699     }
03700     delete[] c_array;
03701     return status;
03702 }
03703 
03704 
03705 
03706 
03707 inline
03708 int
03709 ParmParse::queryarr (const char*    name,
03710                      Vector<double>& ptr,
03711                      int            start_ix,
03712                      int            num_val)
03713 {
03714     if (ptr.size() < num_val)
03715         ptr.resize(num_val);
03716     double* c_array = new double[num_val];
03717     int status = queryarr(name,ppDouble,c_array,start_ix,num_val,-1);
03718     if (status != 0) 
03719     {
03720       for (int i = 0; i < num_val; ++i)
03721       {
03722         ptr[i] = c_array[i];
03723       }
03724     }
03725     delete[] c_array;
03726     return status;
03727 }
03728 
03729 
03730 inline
03731 void
03732 ParmParse::getarr (const char*     name,
03733                    std::vector<std::string>& ptr,
03734                    int             start_ix,
03735                    int             num_val)
03736 {
03737     if (ptr.size() < num_val)
03738         ptr.resize(num_val);
03739     PP_String* c_array = new PP_String[num_val];
03740     getarr(name,ppString,c_array,start_ix,num_val,-1);
03741     for (int i = 0; i < num_val; ++i)
03742     {
03743         ptr[i] = c_array[i].c_str();
03744     }
03745     delete[] c_array;
03746 }
03747 
03748 
03749 
03750 inline
03751 void
03752 ParmParse::getarr (const char*     name,
03753                    Vector<std::string>& ptr,
03754                    int             start_ix,
03755                    int             num_val)
03756 {
03757     if (ptr.size() < num_val)
03758         ptr.resize(num_val);
03759     PP_String* c_array = new PP_String[num_val];
03760     getarr(name,ppString,c_array,start_ix,num_val,-1);
03761     for (int i = 0; i < num_val; ++i)
03762     {
03763         ptr[i] = c_array[i].c_str();
03764     }
03765     delete[] c_array;
03766 }
03767 
03768 
03769 inline
03770 int
03771 ParmParse::queryarr (const char*     name,
03772                      std::vector<std::string>& ptr,
03773                      int             start_ix,
03774                      int             num_val)
03775 {
03776     if (ptr.size() < num_val)
03777         ptr.resize(num_val);
03778     PP_String* c_array = new PP_String[num_val];
03779     int status = queryarr(name,ppString,c_array,start_ix,num_val,-1);
03780     if (status != 0) 
03781     {
03782       for (int i = 0; i < num_val; ++i)
03783       {
03784         ptr[i] = c_array[i].c_str();
03785       }
03786     }
03787     delete[] c_array;
03788     return status;
03789 }
03790 
03791 
03792 inline
03793 int
03794 ParmParse::queryarr (const char*     name,
03795                      Vector<std::string>& ptr,
03796                      int             start_ix,
03797                      int             num_val)
03798 {
03799     if (ptr.size() < num_val)
03800         ptr.resize(num_val);
03801     PP_String* c_array = new PP_String[num_val];
03802     int status = queryarr(name,ppString,c_array,start_ix,num_val,-1);
03803     if (status != 0) 
03804     {
03805       for (int i = 0; i < num_val; ++i)
03806       {
03807         ptr[i] = c_array[i].c_str();
03808       }
03809     }
03810     delete[] c_array;
03811     return status;
03812 }
03813 
03814 
03815 inline
03816 bool
03817 ParmParse::isInteger (const PP_String& str,
03818                       int&           val)
03819 {
03820     //
03821     // Start token scan.
03822     //
03823     char* endp = 0;
03824     val = (int) strtol(str.c_str(), &endp, 10);
03825     return *endp == 0;
03826 }
03827 
03828 
03829 inline
03830 int
03831 ParmParse::isDouble (const PP_String& str,
03832                      double&        val)
03833 {
03834    char* endp = 0;
03835    val = std::strtod(str.c_str(), &endp);
03836    return *endp == 0;
03837 }
03838 
03839 
03840 inline
03841 int
03842 ParmParse::countname (const std::string& name)
03843 {
03844     return countname(name.c_str());
03845 }
03846 
03847 #endif /*CH_PARMPARSE_H*/

Generated on Thu Aug 29 11:05:45 2002 for Chombo&INS by doxygen1.2.16