collection.h

00001 /*
00002   -------------------------------------------------------------------
00003   
00004   Copyright (C) 2006, 2007, Andrew W. Steiner
00005   
00006   This file is part of O2scl.
00007   
00008   O2scl is free software; you can redistribute it and/or modify
00009   it under the terms of the GNU General Public License as published by
00010   the Free Software Foundation; either version 3 of the License, or
00011   (at your option) any later version.
00012   
00013   O2scl is distributed in the hope that it will be useful,
00014   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016   GNU General Public License for more details.
00017   
00018   You should have received a copy of the GNU General Public License
00019   along with O2scl. If not, see <http://www.gnu.org/licenses/>.
00020 
00021   -------------------------------------------------------------------
00022 */
00023 #ifndef O2SCL_COLLECTION_H
00024 #define O2SCL_COLLECTION_H
00025 
00026 #include <iostream>
00027 #include <fstream>
00028 #include <string>
00029 #include <vector>
00030 #include <map>
00031 #include <set>
00032 #include <sstream>
00033 #include <o2scl/misc.h>
00034 #include <o2scl/err_hnd.h>
00035 #include <o2scl/test_mgr.h>
00036 #include <o2scl/text_file.h>
00037 #include <o2scl/file_format.h>
00038 #include <o2scl/file_detect.h>
00039 #include <o2scl/ovector_tlate.h>
00040 #include <o2scl/omatrix_tlate.h>
00041 #include <o2scl/ovector_cx_tlate.h>
00042 #include <o2scl/omatrix_cx_tlate.h>
00043 /* \file collection.h
00044    \brief Brief desc.
00045 */
00046 
00047 #ifndef DOXYGENP
00048 namespace o2scl {
00049 #endif
00050 
00051   /// An entry in a collection
00052   typedef struct {
00053     /// The pointer to the object
00054     void *data;
00055     /// The first size parameter
00056     int size;
00057     /// The second size parameter
00058     int size2;
00059     /// True if the collection owns this object
00060     bool owner;
00061     /// A pointer to the corresponding \ref io_base object
00062     class io_base *iop;
00063   } collection_entry;
00064 
00065   /// A pointer output structure
00066   typedef struct {
00067     /// The name of the pointer
00068     std::string name;
00069     /// Pointer to the collection entry
00070     collection_entry *ep;
00071     /// True if the pointer has been written to the file
00072     bool output;
00073   } pointer_output;
00074   
00075   /// A pointer input structure
00076   typedef struct {
00077     /// The name of the pointer
00078     std::string name;
00079     /// The pointer
00080     void **ptr;
00081     /// The type of the object pointed to
00082     std::string stype;
00083   } pointer_input;
00084 
00085   class cinput;
00086   class coutput;
00087 
00088   /** 
00089       \brief I/O base class
00090 
00091 
00092 
00093       This class is necessary so that the collection method source code
00094       and the io_base method source code doesn't have to go in header files.
00095       
00096       \todo Should the remove() functions be moved to class collection?
00097   */
00098   class io_base {
00099    
00100 #ifndef DOXYGEN_INTERNAL
00101 
00102   protected:
00103     /// for io_type_info.add_type().
00104     friend class io_type_info;
00105    
00106     /// for stat_in and stat_out
00107     friend class collection;
00108 
00109     friend class cinput;
00110     friend class coutput;
00111     friend class io_manager;
00112 
00113     /// A pointer to the type manager
00114     static class io_manager *iom;
00115     
00116     /// A count of the number of objects
00117     static int objs_count;
00118 
00119     /// Automatically create an object for stat_in
00120     virtual int stat_in_noobj(cinput *co, in_file_format *ins);
00121   
00122     /// Automatically create an object for stat_out
00123     virtual int stat_out_noobj(coutput *co, out_file_format *outs);
00124   
00125     /** \brief Allocate memory and input an object
00126      */
00127     virtual int in_wrapper(cinput *co, in_file_format *ins, void *&vp);
00128     
00129     /** \brief Allocate memory and input an array of objects
00130     */
00131     virtual int in_wrapper(cinput *co, in_file_format *ins, void *&vp, 
00132                            int &sz);
00133 
00134     /** \brief Allocate memory and input a 2-d array of objects 
00135     */
00136     virtual int in_wrapper(cinput *co, in_file_format *ins, void *&vp, 
00137                            int &sz, int &sz2);
00138     
00139     /** \brief Internal function to output an object (or an array
00140         or 2-d array) 
00141     */
00142     virtual int out_wrapper(coutput *co, out_file_format *outs, 
00143                             void *vp, int sz, int sz2);
00144 
00145     /// Input an object (no memory allocation)
00146     virtual int object_in_void(cinput *cin, in_file_format *ins, void *op,
00147                                std::string &name);
00148     
00149     /// Input an array of objects (no memory allocation)
00150     virtual int object_in_void(cinput *cin, in_file_format *ins, void *op, 
00151                                int sz, std::string &name);
00152     
00153     /// Input a 2-d array of objects (no memory allocation)
00154     virtual int object_in_void(cinput *cin, in_file_format *ins, void *op, 
00155                                int sz, int sz2, std::string &name);
00156     
00157     /// Input an object (no memory allocation)
00158     virtual int object_in_mem_void(cinput *cin, in_file_format *ins, 
00159                                    void *&op, std::string &name);
00160     
00161     /// Input an array of objects (no memory allocation)
00162     virtual int object_in_mem_void(cinput *cin, in_file_format *ins, 
00163                                    void *&op, int &sz, std::string &name);
00164     
00165     /// Input a 2-d array of objects (no memory allocation)
00166     virtual int object_in_mem_void(cinput *cin, in_file_format *ins, 
00167                                    void *&op, int &sz, int &sz2,
00168                                    std::string &name);
00169     
00170     /// Output an object, an array of objects, or a 2-d array of objects
00171     virtual int object_out_void(coutput *cout, out_file_format *outs, 
00172                                 void *op, int sz, int sz2, 
00173                                 std::string name="");
00174 
00175     /** \brief Store the value of \c sw given in the constructor so
00176         that we know if we need to remove the type in the destructor
00177     */
00178     int sw_store;
00179 
00180     /** \name Functions to remove the memory that was allocated for an object
00181      */
00182     //@{
00183     /// Remove the memory for an object
00184     virtual int remove(void *vp) { return 0; }
00185     
00186     /// Remove the memory for an array of objects
00187     virtual int remove_arr(void *vp) { 
00188       return 0; 
00189     }
00190 
00191     /// Remove the memory for a 2-dimensional array of objects
00192     virtual int remove_2darr(void *vp, int sz) { return 0; }
00193     //@}
00194 
00195 #endif
00196   
00197   public:
00198 
00199     /** 
00200         \brief Create a new I/O object 
00201         
00202         If \c sw is different from zero, then the type will not
00203         be added to the io_manager. This is useful if you want
00204         an object to be its own I/O class, in which case you
00205         may want to make sure that the io_manager only tries
00206         to add the type once. There is no need to have an I/O 
00207         object for every instance of a particular type.
00208     */
00209     io_base(int sw=0);
00210 
00211     /** \brief Create a new object only if an I/O object for type \c t
00212         is not yet present
00213     */
00214     io_base(const char *t);
00215 
00216     virtual ~io_base();
00217     
00218     /// \name Functions to be overloaded in descendants of io_base
00219     //@{
00220     /// Return the type of an object
00221     virtual const char *type() { return "io_base"; }
00222     
00223     /// If true, then the object contains static data
00224     virtual bool has_static_data() { return false; }
00225     //@}
00226     
00227     /** \name Functions useful for in in() and out()
00228      */
00229     //@{
00230     /// Input a pointer
00231     virtual int pointer_in(cinput *co, in_file_format *ins, void **pp, 
00232                            std::string &stype);
00233 
00234     /** 
00235         \brief Output an object to \c outs of type \c stype 
00236 
00237         This is useful for to output a pointer to an object in the
00238         out() or stat_out() functions for a class. The data for
00239         the object which is pointed to is separate from the object
00240         and is only referred to once if more than one objects
00241         point to it.
00242     */
00243     virtual int pointer_out(coutput *co, out_file_format *outs, void *ptr, 
00244                             std::string stype);
00245     //@}
00246     
00247   };
00248  
00249   /** 
00250       \brief Manage I/O type information
00251 
00252 
00253       
00254       This class is automatically created, utilized, and destroyed by
00255       \ref io_base.
00256   */
00257   class io_manager {
00258 
00259   public:
00260 
00261     /** 
00262         \brief Add a type to the list
00263 
00264         Unfortunately, add_type() cannot ensure that no type is added
00265         more than once, since the type is not specified until the 
00266         entire constructor hierarchy has been executed and add_type()
00267         is called at the top of this hierarchy.
00268     */
00269     int add_type(io_base *iop);
00270 
00271     /// Return 0 if \c iop points to a valid type
00272     int is_type(io_base *iop);
00273 
00274     /// Add type \c iop to the manager assuming the type name \c t
00275     int add_type(io_base *iop, const char *t);
00276 
00277     /// Remove a type from the list
00278     int remove_type(io_base *iop);
00279 
00280 #ifndef DOXYGEN_INTERNAL
00281 
00282   protected:
00283 
00284     /// So that io_base can access add_type().
00285     friend class io_base;
00286 
00287     /// So that collections can access get_ptr
00288     friend class collection;
00289 
00290     /// So that cinputs can access get_ptr()
00291     friend class cinput;
00292 
00293     /// So that coutputs can access get_ptr()
00294     friend class coutput;
00295 
00296     // So that io_type_info can access tlist
00297     friend class io_type_info;
00298 
00299     /// Get a pointer to type \c stype 
00300     io_base *get_ptr(std::string stype);
00301   
00302     /// The list of types in the form of io_base pointers
00303     std::vector<io_base *> tlist;
00304   
00305     /// A useful definition for iterating through types
00306     typedef std::vector<io_base *>::iterator titer;
00307 
00308     /// Empty constructor
00309     io_manager() {};
00310   
00311 #endif
00312 
00313   };
00314 
00315   // ----------------------------------------------------------------
00316   // Start of class io_type_info
00317   // ----------------------------------------------------------------
00318 
00319   /** 
00320       \brief User interface to provide I/O type information
00321 
00322 
00323   */
00324   class io_type_info : public io_base {
00325 
00326 #ifndef DOXYGEN_INTERNAL
00327 
00328   protected:
00329 
00330     /// So that collection::fout() can access static_fout().
00331     friend class collection;
00332     
00333     /// Output the static information for the I/O types
00334     int static_fout(coutput *co, out_file_format *out);
00335     
00336     /// Output the static information for the I/O types not in the list
00337     int static_fout_restricted(coutput *co, out_file_format *out,
00338                                std::set<std::string,string_comp> list);
00339   
00340     /// A useful definition for iterating through types
00341     typedef std::vector<io_base *>::iterator titer;
00342 
00343 #endif
00344   
00345   public:
00346 
00347     io_type_info();
00348 
00349     virtual ~io_type_info();
00350 
00351     /** \name Type manipulation 
00352      */
00353     //@{
00354 
00355     /// Return 0 if \c stype is a valid I/O type
00356     int is_type(std::string stype);
00357 
00358     /** 
00359         \brief Remove \c stype from the list of valid I/O types
00360 
00361         This method is dangerous, as it can't check to ensure that
00362         no collection has remaining objects of the type to be
00363         removed.
00364      */
00365     int remove_type(std::string stype);
00366 
00367     /** 
00368         \brief Remove all types in the list of valid I/O types
00369 
00370         This method is dangerous as it doesn't ensure that
00371         all collections are empty.
00372     */
00373     virtual int clear_types();
00374 
00375     /// Print a summary of valid types to the \c outs stream
00376     void type_summary(std::ostream *outs, bool pointers=false);
00377 
00378     /// Add an I/O type to the list
00379     int add_type(io_base *iop) { return iom->add_type(iop); }
00380     //@}
00381 
00382   };
00383   
00384   // ----------------------------------------------------------------
00385   // End of class io_type_info
00386   // ----------------------------------------------------------------
00387 
00388   // ----------------------------------------------------------------
00389   // Start of class collection
00390   // ----------------------------------------------------------------
00391 
00392   /** 
00393       \brief Collection of objects
00394 
00395 
00396 
00397       By default, the fout() functions alphabetize the objects by name,
00398       but this is not a requirement for files read using fin().
00399     
00400       Important issues:
00401       1. Pointers are not set until after an entire file is read so that
00402       objects that are pointed to may occur anywhere in a file. This
00403       means that the information that is pointed to cannot be used in
00404       the io_tlate_d::input() function.
00405       
00406       \todo
00407       - If pointer_in gets a null pointer it does nothing. Should we
00408       replace this behaviour by two pointer_in() functions. One which
00409       does nothing if it gets a null pointer, and one which will
00410       go ahead and set the pointer to null. This is useful for 
00411       output object which have default values to be used if
00412       they are given a null pointer.
00413       - More testing on rewrite() function.
00414       - Think more about adding arrays of pointers? pointers to arrays?
00415       - Modify static data output so that if no objects of a type
00416       are included, then no static data is output for that type?
00417       (No, it's too hard to go through all objects looking for
00418       an object of a particular type).
00419       
00420       \bug
00421       - Ensure that the user cannot add a object with a name of ptrXXX.
00422       - Test_type does not test handle static data or pointers.
00423       - Check strings and words for characters that we can't handle
00424       - The present version of a text-file requires
00425       strings to contain at least one printable character.
00426       - Ensure that all matching is done by both type and name if 
00427       possible.
00428 
00429       Structure:
00430       collection::fout() does the following:
00431       - create an object of type coutput
00432       - Add all objects in the list to the pointer map \c ptr_map 
00433       (with \c output=true ) so that they can be referred to by
00434       pointers later
00435       - Output all static data using io_type_info::static_fout()
00436       - Output all of the items in the list \c plist  (see
00437       below). Any pointers which are not already in \c ptr_map  are
00438       added at this point (with \c output=false 
00439       - Call coutput::pointer_map_fout() to output all objects that
00440       were referred to but not in the list
00441 
00442       To output individual items, collection::fout() does the following:
00443       - Call either io_base::out_wrapper() or io_base::out_hc_wrapper()
00444       - In turn, these functions call io_base::output(), which the user
00445       has overloaded
00446       - If the function io_base::output() calls io_tlate::object_out() then the
00447       io_base::output() function appropriate for that object is called.
00448       No type or name information is included, but size integers are
00449       included if the object is a 1- or 2-d array.
00450       - If the function io_base::output() calls io_base::pointer_out(), then 
00451       the object is searched for in the \c ptr_map . If it is 
00452       not there, then the object is added and assigned a name. The
00453       type and name are then output. If the pointer is NULL, then
00454       both the type and the name are set to \c null .
00455 
00456   */
00457   class collection : public io_base {
00458 
00459 #ifndef DOXYGEN_INTERNAL
00460   
00461   protected:
00462 
00463     friend class io_base;
00464     friend class cinput;
00465     friend class coutput;
00466   
00467     /// A convenient iterator definition for the collection
00468     typedef std::map<std::string,collection_entry,string_comp>::iterator 
00469       piter;
00470   
00471     /// The actual collection
00472     std::map<std::string,collection_entry,string_comp> plist;
00473 
00474 #endif
00475 
00476   public:
00477     
00478     collection() : io_base(1) {
00479     };
00480     ~collection();
00481 
00482     /** \name Output to file methods */
00483     //@{
00484 
00485     /// Output entire list to \c outs 
00486     int fout(out_file_format *outs);
00487 
00488     /// Output entire list to a textfile named \c filename
00489     int fout(std::string filename);
00490     //@}
00491     
00492     /** \name Input from file methods 
00493         If \c overwrt is true, then any objects which
00494         already exist with the same name are overwritten
00495         with the objects in the file. The collection
00496         owns all the objects read. (Since it created them,
00497         the collection assumes it ought to be responsible
00498         to destroy them.)
00499     */
00500     //@{
00501     /// Read a collection from text file named \c file_name
00502     int fin(std::string file_name, bool overwrt=false, int verbose=0);
00503 
00504     /// Read a collection from \c ins
00505     int fin(in_file_format *ins, bool overwrt=false, int verbose=0);
00506     //@}
00507 
00508     /** \name Miscellaneous methods
00509      */
00510     //@{
00511 
00512     /// Test the output for type \c stype.
00513     int test_type(o2scl::test_mgr &t, std::string stype, void *obj,
00514                   void *&newobj, bool scrout=false);
00515 
00516     /** 
00517         \brief Update a file containing a collection
00518  
00519         This method loads the file from "fin" and produces a file at
00520         "fout" containing all of the objects from "fin", updated by
00521         their new values in the present list if possible. Then, it adds
00522         to the end of "fout" any objects in the present list that were
00523         not originally contained in "fin".
00524     */
00525     int rewrite(std::string in_name, std::string out_name);
00526 
00527     /** \brief Force the collection to assume that the ownership
00528         of \c name is external.
00529 
00530         This allows the user to take over ownership of the object
00531         named \c name. This is particularly useful if the object is
00532         read from a file (since then object is owned initially by the
00533         collection), and you want to delete the collection, but retain
00534         the object.  
00535     */
00536     int disown(std::string name);
00537 
00538     /** \brief Summarize contents of collection
00539      */
00540     int summary(std::ostream *out, bool show_addresses=false);
00541 
00542     /** 
00543         \brief Remove an object for the collection
00544 
00545         Free the memory \c name if it is owned by the collection 
00546         and then remove it from the collection.  
00547     */
00548     int remove(std::string name);
00549     
00550     /** \brief Remove all objects from the list
00551      */
00552     void clear();
00553 
00554     /** 
00555         \brief Count number of objects */
00556     int npa();
00557 
00558     //@}
00559 
00560     /** \name Generic add methods
00561         
00562         If \c overwrt is true, then any objects which already exist
00563         with the same name as \c name are overwritten. If owner=true,
00564         then the collection will own the memory allocated for the
00565         object and will free that memory with delete when the object
00566         is removed or the collection is deleted.
00567     */
00568     //@{
00569     int add(std::string name, io_base *tio, void *vec, int sz=0, int sz2=0,
00570             bool overwrt=true, bool owner=false);
00571     
00572     int add(std::string name, std::string stype, 
00573             void *vec, int sz=0, int sz2=0,
00574             bool overwrt=true, bool owner=false);
00575     //@}
00576 
00577     /** 
00578         \name Generic get methods 
00579     */
00580     //@{
00581     /** 
00582         \brief Get an object
00583     */
00584     int get(std::string tname, void *&vec);
00585     /** 
00586         \brief Get an array of objects
00587     */
00588     int get(std::string tname, void *&vec, int &sz);
00589     /** 
00590         \brief Get a 2-d array of objects
00591     */
00592     int get(std::string tname, void *&vec, int &sz, int &sz2);
00593     /** 
00594         \brief Get an object and its type
00595     */
00596     int get(std::string tname, std::string &stype, void *&vec);
00597     /** 
00598         \brief Get an array of objects and their type
00599     */
00600     int get(std::string tname, std::string &stype, void *&vec, int &sz);
00601     /** 
00602         \brief Get a 2-d array of objects and their type
00603     */
00604     int get(std::string tname, std::string &stype, void *&vec, int &sz, 
00605             int &sz2);
00606     /** 
00607         \brief Get an object (alternative form)
00608     */
00609     void *get(std::string name) {
00610       void *vp;
00611       get(name,vp);
00612       return vp;
00613     }
00614     //@}
00615 
00616     /// Output object of type \c stype and name \c name to output \c tof
00617     int get_type(text_out_file &tof, std::string stype, std::string name);
00618 
00619     /// Output object with name \c name to output \c tof
00620     int get(text_out_file &tof, std::string &stype, std::string name);
00621     
00622     /// Set object named \c name with input from \c tif
00623     int set(std::string name, text_in_file &tif);
00624 
00625     /// Set object named \c name with input from \c val
00626     int set(std::string name, std::string val);
00627 
00628     /** \name Input and output of individual objects */
00629     //@{
00630     /** 
00631         \brief Output one object to a file
00632 
00633         This does not disturb any objects in the collection. The 
00634         pointer specified does not need to be in the collection and
00635         is not added to the collection.
00636     */
00637     int out_one(out_file_format *outs, std::string stype, std::string name,
00638                 void *vp, int sz=0, int sz2=0);
00639 
00640     /** 
00641         \brief Output one object to a file
00642 
00643         This does not disturb any objects in the collection. The 
00644         pointer specified does not need to be in the collection and
00645         is not added to the collection.
00646     */
00647     int out_one(std::string fname, std::string stype, std::string name,
00648                 void *vp, int sz=0, int sz2=0);
00649 
00650     /** 
00651         \brief Input one object from a file with name \c name 
00652       
00653         This does not disturb any objects in the collection. The
00654         pointer specified does not need to be in the collection and is
00655         not added to the collection.
00656     */
00657     int in_one_name(in_file_format *ins, std::string stype, std::string name,
00658                     void *&vp, int &sz, int &sz2);
00659   
00660     /** 
00661         \brief Input one object from a file
00662       
00663         This does not disturb any objects in the collection. The
00664         pointer specified does not need to be in the collection and is
00665         not added to the collection.
00666     */
00667     int in_one(in_file_format *ins, std::string stype, std::string &name,
00668                void *&vp, int &sz, int &sz2);
00669 
00670     /** 
00671         \brief Input one object from a file
00672       
00673         This does not disturb any objects in the collection. The
00674         pointer specified does not need to be in the collection and is
00675         not added to the collection.
00676     */
00677     int in_one(std::string fname, std::string stype, std::string &name,
00678                void *&vp, int &sz, int &sz2);
00679     //@}
00680 
00681     /** 
00682         \brief An iterator for stepping through a collection
00683      */
00684     class iterator {
00685       
00686 #ifndef DOXYGEN_INTERNAL
00687 
00688     protected:
00689       
00690       friend class collection;
00691 
00692       /// Create an iterator from the STL iterator
00693       iterator(piter p) { pit=p; }
00694       
00695       /// Local storage for the STL iterator
00696       piter pit;
00697 
00698 #endif
00699       
00700     public:
00701       
00702       /// Prefix increment
00703       iterator operator++() {
00704         pit++;
00705         return *this;
00706       }
00707 
00708       /// Postfix increment
00709       iterator operator++(int unused) {
00710         pit++;
00711         return *this;
00712       }
00713 
00714       /// Prefix decrement
00715       iterator operator--() {
00716         pit--;
00717         return *this;
00718       }
00719       
00720       /// Dereference
00721       collection_entry *operator->() const {
00722         return &(pit->second);
00723       };
00724 
00725       /// Return the name of the collection entry
00726       std::string name() {
00727         return pit->first;
00728       }
00729 
00730       friend int operator==(const iterator &i1, const iterator &i2);
00731       
00732       friend int operator!=(const iterator &i1, const iterator &i2);
00733       
00734     };
00735 
00736     /** 
00737         \brief An iterator for stepping through the entries
00738         in a collection of a particular type
00739      */
00740     class type_iterator {
00741       
00742 #ifndef DOXYGEN_INTERNAL
00743 
00744     protected:
00745       
00746       friend class collection;
00747       
00748       /// Local storage for the type
00749       std::string ltype;
00750 
00751       /// Store a pointer to the collection
00752       collection *lcop;
00753       
00754       /// Constructor
00755       type_iterator(piter p, std::string type, collection *cop) { 
00756         pit=p; 
00757         ltype=type;
00758         lcop=cop;
00759         while (pit!=lcop->plist.end() && 
00760                pit->second.iop->type()!=ltype) pit++;
00761       }
00762       
00763       /// The STL iterator
00764       piter pit;
00765 
00766 #endif
00767 
00768     public:
00769 
00770       /// Prefix increment
00771       type_iterator operator++() {
00772         if (pit!=lcop->plist.end()) pit++;
00773         while (pit!=lcop->plist.end() && 
00774                pit->second.iop->type()!=ltype) pit++;
00775         return *this;
00776       }
00777 
00778       /// Postfix increment
00779       type_iterator operator++(int unused) {
00780         if (pit!=lcop->plist.end()) pit++;
00781         while (pit!=lcop->plist.end() && 
00782                pit->second.iop->type()!=ltype) pit++;
00783         return *this;
00784       }
00785 
00786       /// Dereference
00787       collection_entry *operator->() const {
00788         return &(pit->second);
00789       };
00790 
00791       /// Return the name of the collection entry
00792       std::string name() {
00793         return pit->first;
00794       }
00795 
00796       friend int operator==(const type_iterator &i1, const type_iterator &i2);
00797       
00798       friend int operator!=(const type_iterator &i1, const type_iterator &i2);
00799       
00800     };
00801 
00802     /** \name Iterator functions
00803      */
00804     //@{
00805     /// Return an iterator to the start of the collection
00806     iterator begin() {
00807       return iterator(plist.begin());
00808     }
00809 
00810     /// Return an iterator to the end of the collection
00811     iterator end() {
00812       return iterator(plist.end());
00813     }
00814 
00815     /** \brief Return an iterator to the first element of type \c utype 
00816         in the collection
00817     */
00818     type_iterator begin(std::string utype) {
00819       return type_iterator(plist.begin(),utype,this);
00820     }
00821     
00822     /// Return an iterator to the end of the collection
00823     type_iterator end(std::string utype) {
00824       return type_iterator(plist.end(),utype,this);
00825     }
00826     //@}
00827     
00828   };
00829   // ----------------------------------------------------------------
00830   // End of class collection
00831   // ----------------------------------------------------------------
00832 
00833   /// Equality comparison for two iterators
00834   int operator==(const collection::iterator &i1, 
00835                  const collection::iterator &i2);
00836   
00837   /// Inequality comparison for two iterators
00838   int operator!=(const collection::iterator &i1, 
00839                  const collection::iterator &i2);
00840 
00841   /// Equality comparison for two iterators
00842   int operator==(const collection::type_iterator &i1, 
00843                  const collection::type_iterator &i2);
00844   
00845   /// Inequality comparison for two iterators
00846   int operator!=(const collection::type_iterator &i1, 
00847                  const collection::type_iterator &i2);
00848 
00849   /** 
00850       \brief Class to control object input
00851 
00852 
00853   */
00854   class cinput {
00855 
00856   public:
00857 
00858     /// Input an object
00859     int object_in(std::string type, in_file_format *ins, void *vp,
00860                   std::string &name);
00861 
00862     /// Input an array of objects
00863     int object_in(std::string type, in_file_format *ins, void *vp,
00864                   int sz, std::string &name);
00865 
00866     /// Input a 2-d array of objects
00867     int object_in(std::string type, in_file_format *ins, void *vp,
00868                   int sz, int sz2, std::string &name);
00869     
00870     /// Input an object, allocating memory first
00871     int object_in_mem(std::string type, in_file_format *ins, void *&vp,
00872                       std::string &name);
00873     
00874     /// Input an array of objects, allocating memory first
00875     int object_in_mem(std::string type, in_file_format *ins, void *&vp,
00876                       int &sz, std::string &name);
00877     
00878     /// Input a 2-d array of objects, allocating memory first
00879     int object_in_mem(std::string type, in_file_format *ins, void *&vp,
00880                       int &sz, int &sz2, std::string &name);
00881 
00882 #ifndef DOXYGEN_INTERNAL
00883 
00884   protected:
00885 
00886     /// Create a new input object for a collection 
00887     cinput(collection *co) {
00888       cop=co;
00889     }
00890 
00891     friend class collection;
00892     friend class io_base;
00893   
00894     /// The pointers that need to be set
00895     std::vector<pointer_input> input_ptrs;
00896 
00897     /// An iterator for the input pointers
00898     typedef std::vector<pointer_input>::iterator ipiter;
00899   
00900     /// Assign all of the pointers read with the appropriate objects
00901     int assign_pointers(collection *co);
00902 
00903     /// The pointer to the collection stored in the constructor
00904     collection *cop;
00905 
00906 #endif
00907 
00908   };
00909 
00910   /** 
00911       \brief Class to control object output
00912 
00913 
00914   */
00915   class coutput {
00916 
00917   public:
00918 
00919     /// Output an object
00920     int object_out(std::string type, out_file_format *outs,
00921                    void *op, int sz=0, int sz2=0, std::string name="");
00922 
00923 #ifndef DOXYGEN_INTERNAL
00924 
00925   protected:
00926 
00927     friend class collection;
00928     friend class io_base;
00929   
00930     /// Create a new object from a pointer to a collection
00931     coutput(class collection *co) {
00932       cop=co;
00933       npointers=0;
00934     };
00935 
00936     /// Order the pointers by numeric value
00937     struct ltptr {
00938       /// Returns  \f$ p_1 < p_2 \f$ 
00939       bool operator()(const void * p1, const void * p2) const {
00940         return p1<p2;
00941       }
00942     };
00943     
00944     /// The list pointers to object to be written to the file
00945     std::map<void *,pointer_output,ltptr> ptr_map;
00946     
00947     /// A convenient iterator for the pointer list
00948     typedef std::map<void *,pointer_output,ltptr>::iterator pmiter;
00949     
00950     /** 
00951         \brief Look for an object in the collection given a pointer
00952         
00953         Lookup the pointer \c vp  in the collection, and return
00954         its name and collection_entry
00955     */
00956     int pointer_lookup(void *vp, std::string &name, collection_entry *&ep);
00957 
00958     /// The pointer to the collection stored in the constructor
00959     collection *cop;
00960   
00961     /// Output all of the remaining pointers to 'out'
00962     int pointer_map_fout(out_file_format *out);
00963     
00964     /** 
00965         \brief Keep track of the number of pointers added to ptr_map
00966     
00967         These are counted for the purposes of making a unique name. 
00968         This is initialized
00969         in fout() and incremented in io_base::pointer_out
00970     */
00971     int npointers;
00972     
00973 #endif
00974 
00975   };
00976 
00977   /** 
00978       
00979   \brief A template for adding I/O classes
00980 
00981 
00982   */
00983   template <class object> class io_vtlate : public io_base {
00984     
00985   public:
00986     
00987     /** \name Functions to be overloaded 
00988         
00989         These functions should be overloaded in all descendants of
00990         io_tlate.
00991     */
00992     //@{
00993     
00994     /** \brief The name of the type to be processed */
00995     virtual const char *type() { return "io_tlate"; }
00996     
00997     /** \brief Method for reading an object from \c ins  */
00998     virtual int input(cinput *cin, in_file_format *ins, object *op) 
00999       { return 0; }
01000     
01001     /** 
01002         \brief Method for writing an object to \c outs  */
01003     virtual int output(coutput *cout, out_file_format *outs, object *op) 
01004       { return 0; }
01005     //@}
01006     
01007     /** \name Functions to be overloaded for static data
01008         
01009         These functions should be overloaded in all descendants of
01010         io_tlate which control I/O for classes which contain static
01011         data.
01012     */
01013     //@{
01014     
01015     /** \brief \c true  if the object contains static I/O data */
01016     virtual bool has_static_data() { return false; }
01017     
01018     /** \brief Method for reading static data for an object 
01019         from \c ins 
01020         
01021         One must be careful about objects which set the static data in
01022         their constructors. An object is automatically created in order
01023         to read its static data. This means that if the static data is
01024         set in the constructor, then possibly useful information will be
01025         overwritten through the creation of this temporary object. 
01026         
01027         If one needs to set static data in the constructor of a
01028         singleton object, then the create() and remove() functions
01029         should be empty and a separate pointer to the singleton should
01030         be provided instead of void *vp.
01031         
01032         This is only used if has_static_data() returns true;
01033     */
01034     virtual int stat_input(cinput *cin, in_file_format *ins, object *op) 
01035       { return 0; }
01036     
01037     /** \brief Method for writing static data for an object 
01038         to \c outs  
01039     */
01040     virtual int stat_output(coutput *cout, out_file_format *outs, 
01041                             object *op) 
01042       { return 0; }
01043     //@}
01044   };
01045   
01046   /** \brief A template for adding I/O classes (documents template
01047       io_tlate) 
01048 
01049 
01050 
01051       Note that the generic interface here only works with
01052       pointers, not with the actual objects themselves. This
01053       is important, because it avoids the problem of I/O
01054       for an object with private copy and assigment operators.
01055       For basic types (bool, char, double, int, etc.),
01056       some additional add() and get() functions are defined.
01057       
01058   */
01059   template <class object> class io_tlate : public io_base {
01060       
01061   public:
01062       
01063     /// Create an I/O class for type \c object.
01064     io_tlate() : io_base() {};
01065 
01066     /** 
01067         \brief Create an I/O class for type \c object only if another
01068         object of type \c t is not yet present
01069     */
01070     io_tlate(const char *t) : io_base(t) {};
01071 
01072     /** \name Functions to be overloaded 
01073 
01074         These functions should be overloaded in all descendants of
01075         io_tlate.
01076     */
01077     //@{
01078     
01079     /** \brief The name of the type to be processed */
01080     virtual const char *type() { return "io_tlate"; }
01081 
01082     /** \brief Method for reading an object from \c ins  */
01083     virtual int input(cinput *cin, in_file_format *ins, object *op) 
01084       { return 0; }
01085 
01086     /** 
01087         \brief Method for writing an object to \c outs  */
01088     virtual int output(coutput *cout, out_file_format *outs, object *op) 
01089       { return 0; }
01090     //@}
01091 
01092     /** \name Functions to be overloaded for static data
01093         
01094         These functions should be overloaded in all descendants of
01095         io_tlate which control I/O for classes which contain static
01096         data.
01097     */
01098     //@{
01099 
01100     /** \brief \c true  if the object contains static I/O data */
01101     virtual bool has_static_data() { return false; }
01102 
01103     /** \brief Method for reading static data for an object 
01104         from \c ins 
01105 
01106         One must be careful about objects which set the static data in
01107         their constructors. An object is automatically created in order
01108         to read its static data. This means that if the static data is
01109         set in the constructor, then possibly useful information will be
01110         overwritten through the creation of this temporary object. 
01111       
01112         If one needs to set static data in the constructor of a
01113         singleton object, then the create() and remove() functions
01114         should be empty and a separate pointer to the singleton should
01115         be provided instead of void *vp.
01116 
01117         This is only used if has_static_data() returns true;
01118     */
01119     virtual int stat_input(cinput *cin, in_file_format *ins, object *op) 
01120       { return 0; }
01121     
01122     /** \brief Method for writing static data for an object 
01123         to \c outs  
01124     */
01125     virtual int stat_output(coutput *cout, out_file_format *outs, 
01126                             object *op) 
01127       { return 0; }
01128     //@}
01129 
01130 #ifndef DOXYGEN_INTERNAL
01131 
01132   protected:  
01133     
01134     virtual int object_in_void(cinput *cin, in_file_format *ins, void *op,
01135                                std::string &name) {
01136       return object_in(cin,ins,(object *)op,name);
01137     }
01138     
01139     virtual int object_in_void(cinput *cin, in_file_format *ins, void *op, 
01140                                int sz, std::string &name) {
01141       return object_in(cin,ins,(object *)op,sz,name);
01142     }
01143     
01144     virtual int object_in_void(cinput *cin, in_file_format *ins, void *op, 
01145                                int sz, int sz2, std::string &name) {
01146       return object_in(cin,ins,(object **)op,sz,sz2,name);
01147     }
01148 
01149     virtual int object_in_mem_void(cinput *cin, in_file_format *ins, 
01150                                    void *&vp, std::string &name) {
01151       object *op;
01152       int ret=object_in_mem(cin,ins,op,name);
01153       vp=(void *)op;
01154       return ret;
01155     }
01156     
01157     virtual int object_in_mem_void(cinput *cin, in_file_format *ins, void *&vp,
01158                                    int &sz,std::string &name) {
01159       object *op;
01160       int ret=object_in_mem(cin,ins,op,sz,name);
01161       vp=(void *)op;
01162       return ret;
01163     }
01164     
01165     virtual int object_in_mem_void(cinput *cin, in_file_format *ins, void *&vp,
01166                                    int &sz, int &sz2, std::string &name) {
01167       object **op;
01168       int ret=object_in_mem(cin,ins,op,sz,sz2,name);
01169       vp=(void *)op;
01170       return ret;
01171     }
01172 
01173     virtual int object_out_void(coutput *cout, out_file_format *outs, 
01174                                 void *op, int sz=0, int sz2=0, 
01175                                 std::string name="") {
01176       if (sz2==0) {
01177         return object_out(cout,outs,(object *)op,sz,name);
01178       } 
01179       return object_out(cout,outs,(object **)op,sz,sz2,name);
01180     }
01181 
01182     virtual int stat_in_noobj(cinput *cin, in_file_format *ins) { 
01183       int ret;
01184       object *op=new object;
01185       ret=stat_input(cin,ins,op);
01186       return ret; 
01187     };
01188   
01189     virtual int stat_out_noobj(coutput *cout, out_file_format *outs) {
01190       int ret;
01191       object *op=new object;
01192       ret=stat_output(cout,outs,op);
01193       return ret; 
01194     };
01195 
01196     int in_wrapper(cinput *cin, in_file_format *ins, void *&vp) {
01197       object *op;
01198       if (vp==NULL) {
01199         op=new object;
01200       } else {
01201         op=(object *)vp;
01202       }
01203       input(cin,ins,op);
01204       if (vp==NULL) vp=(void *)op;
01205       return 0;
01206     }
01207   
01208     int in_wrapper(cinput *cin, in_file_format *ins, void *&vp, int &sz) {
01209       object *op;
01210       ins->int_in(sz);
01211       if (vp==NULL) {
01212         op=new object[sz];
01213       } else {
01214         op=(object *)vp;
01215       }
01216       for(int i=0;i<sz;i++) {
01217         input(cin,ins,&(op[i]));
01218       }
01219       if (vp==NULL) vp=(void *)op;
01220       return 0;
01221     }
01222   
01223     int in_wrapper(cinput *cin, in_file_format *ins, void *&vp, int &sz, 
01224                    int &sz2) {
01225       object **op;
01226       ins->int_in(sz);
01227       ins->int_in(sz2);
01228       if (vp==NULL) {
01229         op=new object *[sz];
01230       } else {
01231         op=(object **)vp;
01232       }
01233       for(int i=0;i<sz;i++) {
01234         if (vp==NULL) op[i]=new object[sz2];
01235         for(int j=0;j<sz2;j++) {
01236           input(cin,ins,&(op[i][j]));
01237         }
01238       }
01239       if (vp==NULL) vp=(void *)op;
01240       return 0;
01241     }
01242   
01243     int out_wrapper(coutput *cout, out_file_format *outs, void *vp, int sz, 
01244                     int sz2) {
01245       int i, j;
01246       std::string stype;
01247       object *op=(object *)vp;
01248 
01249       if (sz==0 && sz2==0) {
01250         output(cout,outs,op);
01251       } else if (sz2==0) {
01252         outs->int_out(sz);
01253         for(i=0;i<sz;i++) {
01254           output(cout,outs,&(op[i]));
01255         }
01256       } else {
01257         object **aop=(object **)vp;
01258         outs->int_out(sz);
01259         outs->int_out(sz2);
01260         for(i=0;i<sz;i++) {
01261           for(j=0;j<sz2;j++) {
01262             output(cout,outs,&(aop[i][j]));
01263           }
01264         }
01265       }
01266       return 0;
01267     }
01268 
01269     /// Remove the memory for an object
01270     virtual int remove(void *vp) {
01271       object *op=(object *)vp;
01272       delete op;
01273       return 0;
01274     }  
01275       
01276     /// Remove the memory for an array of objects
01277     virtual int remove_arr(void *vp) {
01278       object *op=(object *)vp;
01279       delete[] op;
01280       return 0;
01281     }  
01282     
01283     /// Remove the memory for a 2-dimensional array of objects
01284     virtual int remove_2darr(void *vp, int sz) {
01285       object **op=(object **)vp;
01286       for(int i=0;i<sz;i++) {
01287         delete[] op[i];
01288       }
01289       delete[] op;
01290       return 0;
01291     }  
01292 
01293     /// Static input for an object
01294     virtual int stat_in_wrapper(cinput *cin, in_file_format *ins, void *vp) {
01295       object *op=(object *)vp;
01296       stat_input(cin,ins,op);
01297       return 0;
01298     }
01299   
01300     /// Static output for an object
01301     virtual int stat_out_wrapper(coutput *cout, out_file_format *outs, 
01302                                  void *vp) {
01303       object *op=(object *)vp;
01304       outs->start_object(type());
01305       stat_output(cout,outs,op);
01306       outs->end_object();
01307       return 0;
01308     }
01309 
01310 #endif
01311 
01312   public:
01313 
01314     /** \name Input functions
01315      */
01316     //@{
01317 
01318     /** \brief Read an object from \c ins  */
01319     virtual int object_in(cinput *cin, in_file_format *ins, object *op,
01320                           std::string &name) {
01321       int i, j;
01322       
01323       std::string typ;
01324       ins->start_object(typ,name);
01325       input(cin,ins,op);
01326       ins->end_object();
01327       return 0;
01328     }
01329     
01330     /** \brief Read an array of objects from \c ins */
01331     virtual int object_in(cinput *cin, in_file_format *ins, object *op, 
01332                           int sz, std::string &name) {
01333       int i;
01334     
01335       std::string typ;
01336       ins->start_object(typ,name);
01337       ins->int_in(sz);
01338       for(i=0;i<sz;i++) {
01339         input(cin,ins,&op[i]);
01340       }
01341       ins->end_object();
01342       return 0;
01343     }
01344     
01345     /** \brief Read a 2-d array of objects from \c ins */
01346     virtual int object_in(cinput *cin, in_file_format *ins, object **op, 
01347                           int sz, int sz2, std::string &name) {
01348       int i, j;
01349       
01350       std::string typ;
01351       ins->start_object(typ,name);
01352       ins->int_in(sz);
01353       ins->int_in(sz2);
01354         
01355       for(i=0;i<sz;i++) {
01356         object *opx=op[i];
01357         for(j=0;j<sz2;j++) {
01358           input(cin,ins,&opx[j]);
01359         }
01360       }
01361       ins->end_object();
01362       return 0;
01363     }
01364     
01365     /** \brief Create memory for a 2-d array of objects 
01366         and read it from \c ins  
01367     */
01368     template<size_t N>
01369       int object_in(cinput *co, in_file_format *ins, 
01370                     object op[][N], int sz, std::string &name) {
01371       int i, j;
01372         
01373       std::string typ;
01374       ins->start_object(typ,name);
01375       ins->int_in(sz);
01376       ins->int_in(((int)N));
01377         
01378       for(i=0;i<sz;i++) {
01379         for(j=0;j<N;j++) {
01380           input(co,ins,&op[i][j]);
01381         }
01382       }
01383       ins->end_object();
01384 
01385       return 0;
01386     }
01387 
01388     /** \brief Create memory for an object and read it from \c ins  */
01389     virtual int object_in_mem(cinput *cin, in_file_format *ins, 
01390                               object *&op, std::string &name) {
01391       int i, j;
01392       op=new object;
01393       std::string typ;
01394       ins->start_object(typ,name);
01395       input(cin,ins,op);
01396       ins->end_object();
01397       return 0;
01398     }
01399     
01400     /** \brief Create memory for an object and read it from \c ins  */
01401     virtual int object_in_mem(cinput *cin, in_file_format *ins, object *&op, 
01402                               int &sz, std::string &name) {
01403       int i, j;
01404       
01405       std::string typ;
01406       ins->start_object(typ,name);
01407       ins->int_in(sz);
01408       op=new object[sz];
01409       for(i=0;i<sz;i++) {
01410         input(cin,ins,&op[i]);
01411       }
01412       ins->end_object();
01413       return 0;
01414     }
01415     
01416     /** \brief Create memory for an object and read it from \c ins  */
01417     virtual int object_in_mem(cinput *cin, in_file_format *ins, 
01418                               object **&op, int &sz, int &sz2,
01419                               std::string &name) {
01420       int i, j;
01421       
01422       std::string typ;
01423       ins->start_object(typ,name);
01424       ins->int_in(sz);
01425       ins->int_in(sz2);
01426       
01427       op=new object *[sz];
01428       for(i=0;i<sz;i++) {
01429         op[i]=new object[sz2];
01430         for(j=0;j<sz2;j++) {
01431           input(cin,ins,&op[i][j]);
01432         }
01433       }
01434       ins->end_object();
01435       
01436       return 0;
01437     }
01438     
01439     /** \brief Create memory for a 2-d array of objects 
01440         and read it from \c ins  
01441         
01442         Note that you must specify in advance the size \c N.
01443     */
01444     template<size_t N>
01445       int object_in_mem(cinput *co, in_file_format *ins, 
01446                         object op[][N], int &sz, std::string &name) {
01447       int i, j;
01448       
01449       std::string typ;
01450       ins->start_object(typ,name);
01451       ins->int_in(sz);
01452       ins->int_in(((int)N));
01453       
01454       // commented out on 3/10/05 - i don't think this should be here
01455       //        op=new object *[sz];
01456       for(i=0;i<sz;i++) {
01457         // commented out on 3/10/05 - i don't think this should be here
01458         //        op[i]=new object[N];
01459         for(j=0;j<N;j++) {
01460           input(co,ins,&op[i][j]);
01461         }
01462       }
01463       ins->end_object();
01464       
01465       return 0;
01466     }
01467     
01468     //@}
01469     
01470     /** \name Output functions
01471      */
01472     //@{
01473     /** \brief Output an object (or an array of objects) to \c outs 
01474      */
01475     virtual int object_out(coutput *cout, out_file_format *outs, object *op, 
01476                            int sz=0, std::string name="") {
01477       if (sz==0) {
01478         outs->start_object(type(),name);
01479         output(cout,outs,op);
01480       } else {
01481         outs->start_object(((std::string)(type()))+"[]",name);
01482         outs->int_out(sz);
01483         for(int i=0;i<sz;i++) {
01484           output(cout,outs,&op[i]);
01485         }
01486       }
01487       outs->end_object();
01488       return 0;
01489     }
01490       
01491     /** \brief Output an object (or an array of objects) to \c outs 
01492      */
01493     virtual int object_out(coutput *cout, out_file_format *outs, object **op, 
01494                            int sz, int sz2, std::string name="") {
01495       int i, j;
01496       
01497       outs->start_object(((std::string)(type()))+"[][]",name);
01498       outs->int_out(sz);
01499       outs->int_out(sz2);
01500       for(i=0;i<sz;i++) {
01501         for(j=0;j<sz2;j++) {
01502           output(cout,outs,&(op[i][j]));
01503         }
01504       }
01505       outs->end_object();
01506       return 0;
01507     }
01508       
01509     /** \brief Output a 2-d array of objects to \c outs 
01510      */
01511     template<size_t N>
01512       int object_out(coutput *cout, out_file_format *outs, 
01513                      object op[][N], int sz, std::string name="") {
01514       int i, j;
01515       
01516       outs->start_object(((std::string)(type()))+"[][]",name);
01517       outs->int_out(sz);
01518       outs->int_out(N);
01519       for(i=0;i<sz;i++) {
01520         for(j=0;j<N;j++) {
01521           output(cout,outs,&op[i][j]);
01522         }
01523       }
01524       outs->end_object();
01525       return 0;
01526     }
01527     //@}
01528     
01529     /** \name Memory allocation
01530      */
01531     //@{
01532     /** \brief Create memory for an object */
01533     virtual int mem_alloc(object *&op) {
01534       op=new object;
01535       return 0;
01536     }
01537 
01538     /** \brief Create memory for an object */
01539     virtual int mem_alloc_arr(object *&op, int sz) {
01540       op=new object[sz];
01541       return 0;
01542     }
01543 
01544     /** \brief Create memory for an object */
01545     virtual int mem_alloc_2darr(object **&op, int sz, int sz2) {
01546       op=new object *[sz];
01547       for(int i=0;i<sz;i++) {
01548         op[i]=new object[sz2];
01549       }
01550       return 0;
01551     }
01552     //@}
01553     
01554     /** \name Add and get objects from a collection
01555      */
01556     //@{
01557 
01558     /** \brief Add an object(s) to a collection */
01559     int add(collection &coll, std::string name, object *op, int sz=0, 
01560             bool overwrt=true, bool owner=false) {
01561       return coll.add(name,this,op,sz,0,overwrt,owner);
01562     }
01563 
01564     /** \brief Add an object(s) to a collection */
01565     int add_2darray(collection &coll, std::string name, object **op, int sz, 
01566                     int sz2, bool overwrt=true, bool owner=false) {
01567       return coll.add(name,this,op,sz,sz2,overwrt,owner);
01568     }
01569 
01570     /** \brief Get an object(s) from a collection */
01571     int get(collection &coll, std::string tname, object *&op) {
01572       void *vp;
01573       int ret=coll.get(tname,vp);
01574       if (ret==0) {
01575         op=(object *)vp;
01576       } else {
01577         op=NULL;
01578         return ret;
01579       }
01580       return 0;
01581     }
01582     
01583     /** \brief Get an object(s) from a collection */
01584     int get(collection &co, std::string tname, object *&op, int &sz) {
01585       void *vp;
01586       int ret=co.get(tname,vp,sz);
01587       if (ret==0) {
01588         op=(object *)vp;
01589       } else {
01590         op=NULL;
01591         return ret;
01592       }
01593       return 0;
01594     }
01595     
01596     /** \brief Get an object(s) from a collection */
01597     int get(collection &co, std::string tname, object **&op, int &sz,
01598             int &sz2) {
01599       void *vp;
01600       int ret=co.get(tname,vp,sz,sz2);
01601       if (ret==0) {
01602         op=(object **)vp;
01603       } else {
01604         op=NULL;
01605         return ret; 
01606       }
01607       return 0;
01608     }
01609     //@}
01610 
01611     /** \name Other functions
01612      */
01613     //@{
01614 
01615     /// Free the memory associated with an object 
01616     virtual int mem_free(object *op) { return remove((void *)op); }  
01617     
01618     /// Free the memory associated with an array of objects
01619     virtual int mem_free_arr(object *op) { return remove_arr((void *)op); }  
01620     
01621     /// Free the memory associated with a 2-d array of objects
01622     virtual int mem_free_2darr(object **op, int sz) 
01623       { return remove_2darr((void *)op,sz); }  
01624     
01625     //@}
01626 
01627   }; 
01628 
01629 
01630   template<> int io_tlate<bool>::input
01631     (cinput *co, in_file_format *ins, bool *dp);
01632   template<> int io_tlate<bool>::output
01633     (coutput *co, out_file_format *outs, bool *dp);
01634   template<> const char *io_tlate<bool>::type();
01635   
01636   /** 
01637       \brief I/O object for bool variables
01638 
01639 
01640   */
01641 #ifdef DOXYGENP
01642   class bool_io_type : public io_tlate<object>
01643 #else
01644     class bool_io_type : public io_tlate<bool>
01645 #endif
01646     {
01647     public:
01648 
01649       /// Desc
01650       bool_io_type(const char *t) : io_tlate<bool>(t) {};
01651 
01652       bool_io_type() : io_tlate<bool>() {};
01653 
01654       /// Add a bool to a collection
01655       int addb(collection &co, std::string name, bool x, bool overwrt=true);
01656       /// Get a bool from a collection
01657       bool getb(collection &co, std::string tname);
01658       /// Get a bool from a collection
01659       int get_def(collection &co, std::string tname, bool &op, bool def=false);
01660     };
01661 
01662   template<> int io_tlate<char>::input
01663     (cinput *co, in_file_format *ins, char *dp);
01664   template<> int io_tlate<char>::output
01665     (coutput *co, out_file_format *outs, char *dp);
01666   template<> const char *io_tlate<char>::type();
01667   
01668   /** 
01669       \brief I/O object for char variables
01670 
01671 
01672   */
01673 #ifdef DOXYGENP
01674   class char_io_type : public io_tlate<object>
01675 #else
01676     class char_io_type : public io_tlate<char> 
01677 #endif
01678     {
01679     public:
01680       /// Desc
01681       char_io_type(const char *t) : io_tlate<char>(t) {};
01682 
01683       char_io_type() : io_tlate<char>() {};
01684 
01685       /// Add a char to a collection
01686       int addc(collection &co, std::string name, char x, bool overwrt=true);
01687       /** 
01688           \brief Get a char from a collection
01689           
01690           Some older systems have trouble with functions named \c getc,
01691           so this is named \c getcc instead.
01692        */
01693       char getcc(collection &co, std::string tname);
01694       /// Get a char from a collection
01695       int get_def(collection &co, std::string tname, char &op, char def='x');
01696     };
01697 
01698   template<> int io_tlate<double>::input
01699     (cinput *co, in_file_format *ins, double *dp);
01700   template<> int io_tlate<double>::output
01701     (coutput *co, out_file_format *outs, double *dp);
01702   template<> const char *io_tlate<double>::type();
01703   
01704   /** 
01705       \brief I/O object for double variables
01706 
01707 
01708   */
01709 #ifdef DOXYGENP
01710   class double_io_type : public io_tlate<object>
01711 #else
01712     class double_io_type : public io_tlate<double>
01713 #endif
01714     {
01715     public:
01716       /// Desc
01717       double_io_type(const char *t) : io_tlate<double>(t) {};
01718 
01719       double_io_type() : io_tlate<double>() {};
01720 
01721       /// Add a double to a collection
01722       int addd(collection &co, std::string name, double x, bool overwrt=true);
01723       /// Get a double from a collection
01724       double getd(collection &co, std::string tname);
01725       /// Get a double from a collection
01726       int get_def(collection &co, std::string tname, double &op, 
01727                   double def=0.0);
01728     };
01729   
01730   template<> int io_tlate<int>::input
01731     (cinput *co, in_file_format *ins, int *dp);
01732   template<> int io_tlate<int>::output
01733     (coutput *co, out_file_format *outs, int *dp);
01734   template<> const char *io_tlate<int>::type();
01735   
01736   /** 
01737       \brief I/O object for int variables
01738 
01739 
01740   */
01741 #ifdef DOXYGENP
01742   class int_io_type : public io_tlate<object> 
01743 #else
01744     class int_io_type : public io_tlate<int>
01745 #endif
01746     {
01747     public:
01748       /// Desc
01749       int_io_type(const char *t) : io_tlate<int>(t) {};
01750 
01751       int_io_type() : io_tlate<int>() {};
01752 
01753       /// Add a int to a collection
01754       int addi(collection &co, std::string name, int x, bool overwrt=true);
01755       /// Get a int from a collection
01756       int geti(collection &co, std::string tname);
01757       /// Get a int from a collection
01758       int get_def(collection &co, std::string tname, int &op, 
01759                   int def=0);
01760     };
01761 
01762   template<> int io_tlate<unsigned long int>::input
01763     (cinput *co, in_file_format *ins, unsigned long int *dp);
01764   template<> int io_tlate<unsigned long int>::output
01765     (coutput *co, out_file_format *outs, unsigned long int *dp);
01766   template<> const char *io_tlate<unsigned long int>::type();
01767   
01768   /** 
01769       \brief I/O object for long variables
01770 
01771 
01772   */
01773 #ifdef DOXYGENP
01774   class long_io_type : public io_tlate<object> 
01775 #else
01776     class long_io_type : public io_tlate<unsigned long int>
01777 #endif
01778     {
01779     public:
01780       /// Desc
01781       long_io_type(const char *t) : io_tlate<unsigned long int>(t) {};
01782 
01783       long_io_type() : io_tlate<unsigned long int>() {};
01784 
01785       /// Add a long to a collection
01786       int addl(collection &co, std::string name, unsigned long int x, 
01787                bool overwrt=true);
01788       /// Get a long from a collection
01789       int getl(collection &co, std::string tname);
01790       /// Get a long from a collection
01791       int get_def(collection &co, std::string tname, unsigned long int &op, 
01792                   unsigned long int def=0);
01793     };
01794   
01795   template<> int io_tlate<std::string>::input
01796     (cinput *co, in_file_format *ins, std::string *dp);
01797   template<> int io_tlate<std::string>::output
01798     (coutput *co, out_file_format *outs, std::string *dp);
01799   template<> const char *io_tlate<std::string>::type();
01800   
01801   /** 
01802       \brief I/O object for string variables
01803 
01804 
01805   */
01806 #ifdef DOXYGENP
01807   class string_io_type : public io_tlate<object> 
01808 #else
01809     class string_io_type : public io_tlate<std::string>
01810 #endif
01811     {
01812     public:
01813       /// Desc
01814       string_io_type(const char *t) : io_tlate<std::string>(t) {};
01815 
01816       string_io_type() : io_tlate<std::string>() {};
01817 
01818       /// Add a string to a collection
01819       int adds(collection &co, std::string name, std::string s, 
01820                bool overwrt=true);
01821       /// Get a string from a collection
01822       std::string gets(collection &co, std::string tname);
01823       /// Get a string from a collection
01824       int get_def(collection &co, std::string tname, std::string &op, 
01825                   std::string def="");
01826     };
01827   
01828   /** 
01829       \brief I/O object for words
01830 
01831 
01832   */
01833 #ifdef DOXYGENP
01834   class word_io_type : public io_tlate<object>
01835 #else
01836     class word_io_type : public io_tlate<std::string>
01837 #endif
01838     {
01839     public:
01840       /// Desc
01841       word_io_type(const char *t) : io_tlate<std::string>(t) {};
01842 
01843       word_io_type() : io_tlate<std::string>() {};
01844 
01845       /// Desc
01846       int input(cinput *co, in_file_format *ins, std::string *dp);
01847       /// Desc
01848       int output(coutput *co, out_file_format *outs, std::string *dp);
01849       /// Add a string to a collection
01850       int addw(collection &co, std::string name, std::string w, 
01851                bool overwrt=true);
01852       /// Get a word from a collection
01853       std::string getw(collection &co, std::string tname);
01854       /// Get a word from a collection
01855       int get_def(collection &co, std::string tname, std::string &op, 
01856                   std::string def="");
01857       /// Desc
01858       const char *type() { return "word"; }
01859     };
01860 
01861 #ifdef NEVER_DEFINED
01862   /** 
01863       \brief I/O for ovector
01864 
01865 
01866   */
01867   template<> int io_tlate<ovector>::input
01868     (cinput *co, in_file_format *ins, ovector *dp);
01869   template<> int io_tlate<ovector>::output
01870     (coutput *co, out_file_format *outs, ovector *dp);
01871   template<> const char *io_tlate<ovector>::type();
01872 
01873   /** 
01874       \brief I/O for omatrix
01875 
01876 
01877   */
01878   template<> int io_tlate<omatrix>::input
01879     (cinput *co, in_file_format *ins, omatrix *dp);
01880   template<> int io_tlate<omatrix>::output
01881     (coutput *co, out_file_format *outs, omatrix *dp);
01882   template<> const char *io_tlate<omatrix>::type();
01883 
01884   /** 
01885       \brief I/O for ovector_int
01886 
01887 
01888   */
01889   template<> int io_tlate<ovector_int>::input
01890     (cinput *co, in_file_format *ins, ovector_int *dp);
01891   template<> int io_tlate<ovector_int>::output
01892     (coutput *co, out_file_format *outs, ovector_int *dp);
01893   template<> const char *io_tlate<ovector_int>::type();
01894 
01895   /** 
01896       \brief I/O for omatrix_int
01897 
01898 
01899   */
01900   template<> int io_tlate<omatrix_int>::input
01901     (cinput *co, in_file_format *ins, omatrix_int *dp);
01902   template<> int io_tlate<omatrix_int>::output
01903     (coutput *co, out_file_format *outs, omatrix_int *dp);
01904   template<> const char *io_tlate<omatrix_int>::type();
01905 
01906   /** 
01907       \brief I/O for ovector_cx
01908 
01909 
01910   */
01911   template<> int io_tlate<ovector_cx>::input
01912     (cinput *co, in_file_format *ins, ovector_cx *dp);
01913   template<> int io_tlate<ovector_cx>::output
01914     (coutput *co, out_file_format *outs, ovector_cx *dp);
01915   template<> const char *io_tlate<ovector_cx>::type();
01916 
01917   /** 
01918       \brief I/O for omatrix_cx
01919 
01920 
01921   */
01922   template<> int io_tlate<omatrix_cx>::input
01923     (cinput *co, in_file_format *ins, omatrix_cx *dp);
01924   template<> int io_tlate<omatrix_cx>::output
01925     (coutput *co, out_file_format *outs, omatrix_cx *dp);
01926   template<> const char *io_tlate<omatrix_cx>::type();
01927 
01928   typedef io_tlate<ovector> ovector_io_type;
01929   typedef io_tlate<omatrix> omatrix_io_type;
01930   typedef io_tlate<ovector_int> ovector_int_io_type;
01931   typedef io_tlate<omatrix_int> omatrix_int_io_type;
01932   typedef io_tlate<ovector_cx> ovector_cx_io_type;
01933   typedef io_tlate<omatrix_cx> omatrix_cx_io_type;
01934 
01935 #endif
01936 
01937 #ifndef DOXYGENP  
01938 }
01939 #endif
01940 
01941 #endif

Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.

Project hosting provided by SourceForge.net Logo, O2scl Sourceforge Project Page