collection.h

Go to the documentation of this file.
00001 /*
00002   -------------------------------------------------------------------
00003   
00004   Copyright (C) 2006, 2007, 2008, 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 
00044 /** \file collection.h
00045     \brief File containing I/O types and the collection class
00046     
00047     New update todos:
00048     - There are a lot of blank functions in the io_base class, 
00049     so this class should be made abstract. This can actually be done
00050     by separating io_base into two classes, so that the parents of
00051     the collection class and the io_tlate class are different.
00052     - Construct new templated add() function
00053     - Fix test_type()
00054     - Fix error handling in get() functions and make a lookup() method
00055     which doesn't necessarily call the error handler
00056     - Fix documentation?
00057     - Columnify summary output
00058     - Ensure all parameters are matched by parameter and name if possible
00059 
00060     \future Figure out what to do with templated matrix and vector output.
00061     What might be ideal is a "vector_io" type which will input or output
00062     a generic vector of any type.
00063 */
00064 
00065 #ifndef DOXYGENP
00066 namespace o2scl {
00067 #endif
00068 
00069   /** An entry in a collection
00070       
00071       Experimental.
00072   */
00073   typedef struct {
00074     /// The pointer to the object
00075     void *data;
00076     /// The first size parameter
00077     int size;
00078     /// The second size parameter
00079     int size2;
00080     /// True if the collection owns this object
00081     bool owner;
00082     /// A pointer to the corresponding \ref io_base object
00083     class io_base *iop;
00084   } collection_entry;
00085 
00086   /** \brief A pointer output structure
00087       
00088       Experimental.
00089   */
00090   typedef struct {
00091     /// The name of the pointer
00092     std::string name;
00093     /// Pointer to the collection entry
00094     collection_entry *ep;
00095     /// True if the pointer has been written to the file
00096     bool output;
00097   } pointer_output;
00098   
00099   /** \brief A pointer input structure
00100 
00101       Experimental.
00102    */
00103   typedef struct {
00104     /// The name of the pointer
00105     std::string name;
00106     /// The pointer
00107     void **ptr;
00108     /// The type of the object pointed to
00109     std::string stype;
00110   } pointer_input;
00111 
00112   // Forward declaration of class cinput
00113   class cinput;
00114   // Forward declaration of class coutput
00115   class coutput;
00116 
00117   /** 
00118       \brief I/O base class
00119 
00120       This class is experimental.
00121 
00122       This class is necessary so that the collection method source code
00123       and the io_base method source code doesn't have to go in header files.
00124       
00125       \todo Should the remove() functions be moved to class collection?
00126   */
00127   class io_base {
00128    
00129 #ifndef DOXYGEN_INTERNAL
00130 
00131   protected:
00132 
00133     /// for io_type_info.add_type().
00134     friend class io_type_info;
00135    
00136     /// for stat_in and stat_out
00137     friend class collection;
00138 
00139     friend class cinput;
00140     friend class coutput;
00141     friend class io_manager;
00142 
00143     /// A pointer to the type manager
00144     static class io_manager *iom;
00145     
00146     /// A count of the number of objects
00147     static int objs_count;
00148 
00149     /// Automatically create an object for stat_in
00150     virtual int stat_in_noobj(cinput *co, in_file_format *ins);
00151   
00152     /// Automatically create an object for stat_out
00153     virtual int stat_out_noobj(coutput *co, out_file_format *outs);
00154   
00155     /** \brief Allocate memory and input an object
00156      */
00157     virtual int in_wrapper(cinput *co, in_file_format *ins, void *&vp);
00158     
00159     /** \brief Allocate memory and input an array of objects
00160      */
00161     virtual int in_wrapper(cinput *co, in_file_format *ins, void *&vp, 
00162                            int &sz);
00163 
00164     /** \brief Allocate memory and input a 2-d array of objects 
00165      */
00166     virtual int in_wrapper(cinput *co, in_file_format *ins, void *&vp, 
00167                            int &sz, int &sz2);
00168     
00169     /** \brief Internal function to output an object (or an array
00170         or 2-d array) 
00171     */
00172     virtual int out_wrapper(coutput *co, out_file_format *outs, 
00173                             void *vp, int sz, int sz2);
00174 
00175     /// Input an object (no memory allocation)
00176     virtual int object_in_void(cinput *cin, in_file_format *ins, void *op,
00177                                std::string &name);
00178     
00179     /// Input an array of objects (no memory allocation)
00180     virtual int object_in_void(cinput *cin, in_file_format *ins, void *op, 
00181                                int sz, std::string &name);
00182     
00183     /// Input a 2-d array of objects (no memory allocation)
00184     virtual int object_in_void(cinput *cin, in_file_format *ins, void *op, 
00185                                int sz, int sz2, std::string &name);
00186     
00187     /// Input an object (no memory allocation)
00188     virtual int object_in_mem_void(cinput *cin, in_file_format *ins, 
00189                                    void *&op, std::string &name);
00190     
00191     /// Input an array of objects (no memory allocation)
00192     virtual int object_in_mem_void(cinput *cin, in_file_format *ins, 
00193                                    void *&op, int &sz, std::string &name);
00194     
00195     /// Input a 2-d array of objects (no memory allocation)
00196     virtual int object_in_mem_void(cinput *cin, in_file_format *ins, 
00197                                    void *&op, int &sz, int &sz2,
00198                                    std::string &name);
00199     
00200     /// Output an object, an array of objects, or a 2-d array of objects
00201     virtual int object_out_void(coutput *cout, out_file_format *outs, 
00202                                 void *op, int sz, int sz2, 
00203                                 std::string name="");
00204 
00205     /** \brief Store the value of \c sw given in the constructor so
00206         that we know if we need to remove the type in the destructor
00207     */
00208     int sw_store;
00209 
00210     /** \name Functions to remove the memory that was allocated for an object
00211      */
00212     //@{
00213     /// Remove the memory for an object
00214     virtual int remove(void *vp) { return 0; }
00215     
00216     /// Remove the memory for an array of objects
00217     virtual int remove_arr(void *vp) { 
00218       return 0; 
00219     }
00220 
00221     /// Remove the memory for a 2-dimensional array of objects
00222     virtual int remove_2darr(void *vp, int sz) { return 0; }
00223     //@}
00224 
00225 #endif
00226   
00227   public:
00228 
00229     /** 
00230         \brief Create a new I/O object 
00231         
00232         If \c sw is different from zero, then the type will not
00233         be added to the io_manager. This is useful if you want
00234         an object to be its own I/O class, in which case you
00235         may want to make sure that the io_manager only tries
00236         to add the type once. There is no need to have an I/O 
00237         object for every instance of a particular type.
00238     */
00239     io_base(int sw=0);
00240 
00241     /** \brief Create a new object only if an I/O object for type \c t
00242         is not yet present
00243     */
00244     io_base(const char *t);
00245 
00246     virtual ~io_base();
00247     
00248     /// \name Functions to be overloaded in descendants of io_base
00249     //@{
00250     /// Return the type of an object
00251     virtual const char *type() { return "io_base"; }
00252     
00253     /// If true, then the object contains static data
00254     virtual bool has_static_data() { return false; }
00255     //@}
00256     
00257     /** \name Functions useful for in in() and out()
00258      */
00259     //@{
00260     /// Input a pointer
00261     virtual int pointer_in(cinput *co, in_file_format *ins, void **pp, 
00262                            std::string &stype);
00263 
00264     /** 
00265         \brief Output an object to \c outs of type \c stype 
00266 
00267         This is useful for to output a pointer to an object in the
00268         out() or stat_out() functions for a class. The data for
00269         the object which is pointed to is separate from the object
00270         and is only referred to once if more than one objects
00271         point to it.
00272     */
00273     virtual int pointer_out(coutput *co, out_file_format *outs, void *ptr, 
00274                             std::string stype);
00275     //@}
00276     
00277   };
00278  
00279   /** 
00280       \brief Manage I/O type information
00281 
00282       This class is experimental.
00283 
00284       This class is automatically created, utilized, and destroyed by
00285       \ref io_base. It's sole constructor is protected, so it cannot
00286       be created by a generic end-user. 
00287   */
00288   class io_manager {
00289 
00290   public:
00291 
00292     /** 
00293         \brief Add a type to the list
00294 
00295         Unfortunately, add_type() cannot ensure that no type is added
00296         more than once, since the type is not specified until the 
00297         entire constructor hierarchy has been executed and add_type()
00298         is called at the top of this hierarchy.
00299     */
00300     int add_type(io_base *iop);
00301 
00302     /// Return 0 if \c iop points to a valid type
00303     int is_type(io_base *iop);
00304 
00305     /// Add type \c iop to the manager assuming the type name \c t
00306     int add_type(io_base *iop, const char *t);
00307 
00308     /// Remove a type from the list
00309     int remove_type(io_base *iop);
00310 
00311 #ifndef DOXYGEN_INTERNAL
00312 
00313   protected:
00314 
00315     /// So that io_base can access add_type().
00316     friend class io_base;
00317 
00318     /// So that collections can access get_ptr
00319     friend class collection;
00320 
00321     /// So that cinputs can access get_ptr()
00322     friend class cinput;
00323 
00324     /// So that coutputs can access get_ptr()
00325     friend class coutput;
00326 
00327     // So that io_type_info can access tlist
00328     friend class io_type_info;
00329 
00330     /// Get a pointer to type \c stype 
00331     io_base *get_ptr(std::string stype);
00332   
00333     /// The list of types in the form of io_base pointers
00334     std::vector<io_base *> tlist;
00335   
00336     /// A useful definition for iterating through types
00337     typedef std::vector<io_base *>::iterator titer;
00338 
00339     /// Empty constructor
00340     io_manager() {};
00341   
00342 #endif
00343 
00344   };
00345 
00346   // ----------------------------------------------------------------
00347   // Start of class io_type_info
00348   // ----------------------------------------------------------------
00349 
00350   /** 
00351       \brief User interface to provide I/O type information
00352 
00353       This class is experimental.
00354   */
00355   class io_type_info : public io_base {
00356 
00357 #ifndef DOXYGEN_INTERNAL
00358 
00359   protected:
00360 
00361     /// So that collection::fout() can access static_fout().
00362     friend class collection;
00363     
00364     /// Output the static information for the I/O types
00365     int static_fout(coutput *co, out_file_format *out);
00366     
00367     /// Output the static information for the I/O types not in the list
00368     int static_fout_restricted(coutput *co, out_file_format *out,
00369                                std::set<std::string,string_comp> list);
00370   
00371     /// A useful definition for iterating through types
00372     typedef std::vector<io_base *>::iterator titer;
00373 
00374 #endif
00375   
00376   public:
00377 
00378     io_type_info();
00379 
00380     virtual ~io_type_info();
00381 
00382     /** \name Type manipulation 
00383      */
00384     //@{
00385 
00386     /// Return 0 if \c stype is a valid I/O type
00387     int is_type(std::string stype);
00388 
00389     /** 
00390         \brief Remove \c stype from the list of valid I/O types
00391 
00392         This method is dangerous, as it can't check to ensure that
00393         no collection has remaining objects of the type to be
00394         removed.
00395     */
00396     int remove_type(std::string stype);
00397 
00398     /** 
00399         \brief Remove all types in the list of valid I/O types
00400 
00401         This method is dangerous as it doesn't ensure that
00402         all collections are empty.
00403     */
00404     virtual int clear_types();
00405 
00406     /// Print a summary of valid types to the \c outs stream
00407     void type_summary(std::ostream *outs, bool pointers=false);
00408 
00409     /// Add an I/O type to the list
00410     int add_type(io_base *iop) { return iom->add_type(iop); }
00411     //@}
00412 
00413   };
00414   
00415   // ----------------------------------------------------------------
00416   // End of class io_type_info
00417   // ----------------------------------------------------------------
00418 
00419   // ----------------------------------------------------------------
00420   // Start of class collection
00421   // ----------------------------------------------------------------
00422 
00423   /** 
00424       \brief Collection of objects 
00425 
00426       This class is experimental.
00427 
00428       By default, the fout() functions alphabetize the objects by name,
00429       but this is not a requirement for files read using fin().
00430     
00431       Important issues:
00432       1. Pointers are not set until after an entire file is read so that
00433       objects that are pointed to may occur anywhere in a file. This
00434       means that the information that is pointed to cannot be used in
00435       the io_tlate_d::input() function.
00436       
00437       \todo
00438       - If pointer_in gets a null pointer it does nothing. Should we
00439       replace this behaviour by two pointer_in() functions. One which
00440       does nothing if it gets a null pointer, and one which will
00441       go ahead and set the pointer to null. This is useful for 
00442       output object which have default values to be used if
00443       they are given a null pointer.
00444       - More testing on rewrite() function.
00445       - Think more about adding arrays of pointers? pointers to arrays?
00446       - Modify static data output so that if no objects of a type
00447       are included, then no static data is output for that type?
00448       (No, it's too hard to go through all objects looking for
00449       an object of a particular type).
00450       
00451       \bug
00452       - Ensure that the user cannot add a object with a name of ptrXXX.
00453       - Test_type does not test handle static data or pointers.
00454       - Check strings and words for characters that we can't handle
00455       - The present version of a text-file requires
00456       strings to contain at least one printable character.
00457       - Ensure that all matching is done by both type and name if 
00458       possible.
00459 
00460       Structure:
00461       collection::fout() does the following:
00462       - create an object of type coutput
00463       - Add all objects in the list to the pointer map \c ptr_map 
00464       (with \c output=true ) so that they can be referred to by
00465       pointers later
00466       - Output all static data using io_type_info::static_fout()
00467       - Output all of the items in the list \c plist  (see
00468       below). Any pointers which are not already in \c ptr_map  are
00469       added at this point (with \c output=false 
00470       - Call coutput::pointer_map_fout() to output all objects that
00471       were referred to but not in the list
00472 
00473       To output individual items, collection::fout() does the following:
00474       - Call either io_base::out_wrapper() or io_base::out_hc_wrapper()
00475       - In turn, these functions call io_base::output(), which the user
00476       has overloaded
00477       - If the function io_base::output() calls io_tlate::object_out() then the
00478       io_base::output() function appropriate for that object is called.
00479       No type or name information is included, but size integers are
00480       included if the object is a 1- or 2-d array.
00481       - If the function io_base::output() calls io_base::pointer_out(), then 
00482       the object is searched for in the \c ptr_map . If it is 
00483       not there, then the object is added and assigned a name. The
00484       type and name are then output. If the pointer is NULL, then
00485       both the type and the name are set to \c null .
00486 
00487   */
00488   class collection : public io_base {
00489 
00490 #ifndef DOXYGEN_INTERNAL
00491   
00492   protected:
00493 
00494     friend class io_base;
00495     friend class cinput;
00496     friend class coutput;
00497   
00498     /// A convenient iterator definition for the collection
00499     typedef std::map<std::string,collection_entry,string_comp>::iterator 
00500       piter;
00501   
00502     /// The actual collection
00503     std::map<std::string,collection_entry,string_comp> plist;
00504 
00505 #endif
00506 
00507   public:
00508     
00509     collection() : io_base(1) {};
00510       
00511 #ifdef O2SCL_NEVER_DEFINED
00512       // This is just to assist emacs tabification
00513   }
00514   {
00515 #endif
00516     
00517     ~collection();
00518     
00519     /** \name Output to file methods */
00520     //@{
00521     
00522     /// Output entire list to \c outs 
00523     int fout(out_file_format *outs);
00524     
00525     /// Output entire list to a text file named \c filename
00526     int fout(std::string filename);
00527     //@}
00528     
00529     /** \name Input from file methods 
00530         If \c overwrt is true, then any objects which
00531         already exist with the same name are overwritten
00532         with the objects in the file. The collection
00533         owns all the objects read. (Since it created them,
00534         the collection assumes it ought to be responsible
00535         to destroy them.)
00536     */
00537     //@{
00538     /// Read a collection from text file named \c file_name
00539     int fin(std::string file_name, bool overwrt=false, int verbose=0);
00540     
00541     /// Read a collection from \c ins
00542     int fin(in_file_format *ins, bool overwrt=false, int verbose=0);
00543     //@}
00544     
00545     /** \name Miscellaneous methods
00546      */
00547     //@{
00548 
00549     /// Test the output for type \c stype.
00550     int test_type(o2scl::test_mgr &t, std::string stype, void *obj,
00551                   void *&newobj, bool scrout=false);
00552 
00553     /** 
00554         \brief Update a file containing a collection
00555  
00556         This method loads the file from "fin" and produces a file at
00557         "fout" containing all of the objects from "fin", updated by
00558         their new values in the present list if possible. Then, it adds
00559         to the end of "fout" any objects in the present list that were
00560         not originally contained in "fin".
00561     */
00562     int rewrite(std::string in_name, std::string out_name);
00563 
00564     /** \brief Force the collection to assume that the ownership
00565         of \c name is external.
00566 
00567         This allows the user to take over ownership of the object
00568         named \c name. This is particularly useful if the object is
00569         read from a file (since then object is owned initially by the
00570         collection), and you want to delete the collection, but retain
00571         the object.  
00572     */
00573     int disown(std::string name);
00574 
00575     /** \brief Summarize contents of collection
00576      */
00577     int summary(std::ostream *out, bool show_addresses=false);
00578 
00579     /** 
00580         \brief Remove an object for the collection
00581 
00582         Free the memory \c name if it is owned by the collection 
00583         and then remove it from the collection.  
00584     */
00585     int remove(std::string name);
00586     
00587     /** \brief Remove all objects from the list
00588      */
00589     void clear();
00590 
00591     /** 
00592         \brief Count number of objects */
00593     int size();
00594 
00595     //@}
00596 
00597     /** \name Generic add methods
00598         
00599     If \c overwrt is true, then any objects which already exist
00600     with the same name as \c name are overwritten. If owner=true,
00601     then the collection will own the memory allocated for the
00602     object and will free that memory with delete when the object
00603     is removed or the collection is deleted.
00604     */
00605     //@{
00606     int add_void(std::string name, io_base *tio, void *vec, int sz=0, 
00607                  int sz2=0, bool overwrt=true, bool owner=false);
00608     
00609     int add_void(std::string name, std::string stype, 
00610             void *vec, int sz=0, int sz2=0,
00611             bool overwrt=true, bool owner=false);
00612     //@}
00613 
00614     /// \name Machine type get methods
00615     //@{
00616     /// Get a boolean value named \c name with default value \c def_value
00617     bool getb_def(std::string name, bool def_value) {
00618       piter pit=plist.find(name);                       
00619       if (pit!=plist.end()) {                           
00620         if (((std::string)pit->second.iop->type())=="bool") {   
00621           if (pit->second.size!=0 || pit->second.size2!=0) {
00622             O2SCL_ERR("Size of object incorrect in collection::getc2().",
00623                     gsl_efailed);
00624             return 0;
00625           }
00626           bool *wp=(bool *)(pit->second.data);                  
00627           return *wp;
00628         }                                                       
00629       }                                                 
00630       return def_value;
00631     }
00632     
00633     /// Get a char named \c name with default value \c def_value
00634     char getc_def(std::string name, char def_value) {
00635       piter pit=plist.find(name);                       
00636       if (pit!=plist.end()) {                           
00637         if (((std::string)pit->second.iop->type())=="char") {   
00638           if (pit->second.size!=0 || pit->second.size2!=0) {
00639             O2SCL_ERR("Size of object incorrect in collection::getc2().",
00640                     gsl_efailed);
00641             return 0;
00642           }
00643           char *wp=(char *)(pit->second.data);                  
00644           return *wp;
00645         }                                                       
00646       }                                                 
00647       return def_value;
00648     }
00649     
00650     /// Get a double named \c name with default value \c def_value
00651     double getd_def(std::string name, double def_value) {
00652       piter pit=plist.find(name);                       
00653       if (pit!=plist.end()) {                           
00654         if (((std::string)pit->second.iop->type())=="double") { 
00655           if (pit->second.size!=0 || pit->second.size2!=0) {
00656             O2SCL_ERR("Size of object incorrect in collection::getd2().",
00657                     gsl_efailed);
00658             return 0.0;
00659           }
00660           double *wp=(double *)(pit->second.data);                      
00661           return *wp;
00662         }                                                       
00663       }                                                 
00664       return def_value;
00665     }
00666     
00667     /// Get an integer named \c name with default value \c def_value
00668     int geti_def(std::string name, int def_value) {
00669       piter pit=plist.find(name);                       
00670       if (pit!=plist.end()) {                           
00671         if (((std::string)pit->second.iop->type())=="int") {    
00672           if (pit->second.size!=0 || pit->second.size2!=0) {
00673             O2SCL_ERR("Size of object incorrect in collection::geti2().",
00674                     gsl_efailed);
00675             return 0;
00676           }
00677           int *wp=(int *)(pit->second.data);                    
00678           return *wp;
00679         }                                                       
00680       }                                                 
00681       return def_value;
00682     }
00683     
00684     /// Get a string named \c name with default value \c def_value
00685     std::string gets_def(std::string name, std::string def_value) {
00686       piter pit=plist.find(name);                       
00687       if (pit!=plist.end()) {                           
00688         if (((std::string)pit->second.iop->type())=="string") { 
00689           if (pit->second.size!=0 || pit->second.size2!=0) {
00690             O2SCL_ERR("Size of object incorrect in collection::gets2().",
00691                     gsl_efailed);
00692             return "";
00693           }
00694           std::string *wp=(std::string *)(pit->second.data);
00695           return *wp;
00696         }                                                       
00697       }
00698       return def_value;
00699     }
00700     
00701     /// Get a boolean value named \c name with default value \c def_value
00702     std::string getw_def(std::string name, std::string def_value) {
00703       piter pit=plist.find(name);                       
00704       if (pit!=plist.end()) {                           
00705         if (((std::string)pit->second.iop->type())=="word") {   
00706           if (pit->second.size!=0 || pit->second.size2!=0) {
00707             O2SCL_ERR("Size of object incorrect in collection::getw2().",
00708                     gsl_efailed);
00709             return "";
00710           }
00711           std::string *wp=(std::string *)(pit->second.data);
00712           return *wp;
00713         }                                                       
00714       }                                                 
00715       return def_value;
00716     }
00717     
00718     /// Desc
00719     bool getb(std::string name) {
00720       piter pit=plist.find(name);                       
00721       if (pit!=plist.end()) {                           
00722         if (((std::string)pit->second.iop->type())=="bool") {   
00723           if (pit->second.size!=0 || pit->second.size2!=0) {
00724             O2SCL_ERR("Size of object incorrect in collection::getc2().",
00725                     gsl_efailed);
00726             return 0;
00727           }
00728           bool *wp=(bool *)(pit->second.data);                  
00729           return *wp;
00730         }                                                       
00731       }                                                 
00732       O2SCL_ERR("Object not found in collection::getc2().",gsl_enotfound);
00733       return false;
00734     }
00735     
00736     /// Desc
00737     char getc(std::string name) {
00738       piter pit=plist.find(name);                       
00739       if (pit!=plist.end()) {                           
00740         if (((std::string)pit->second.iop->type())=="char") {   
00741           if (pit->second.size!=0 || pit->second.size2!=0) {
00742             O2SCL_ERR("Size of object incorrect in collection::getc2().",
00743                     gsl_efailed);
00744             return 0;
00745           }
00746           char *wp=(char *)(pit->second.data);                  
00747           return *wp;
00748         }                                                       
00749       }                                                 
00750       O2SCL_ERR("Object not found in collection::getc2().",gsl_enotfound);
00751       return 0;
00752     }
00753     
00754     /// Desc
00755     double getd(std::string name) {
00756       piter pit=plist.find(name);                       
00757       if (pit!=plist.end()) {                           
00758         if (((std::string)pit->second.iop->type())=="double") { 
00759           if (pit->second.size!=0 || pit->second.size2!=0) {
00760             O2SCL_ERR("Size of object incorrect in collection::getd2().",
00761                     gsl_efailed);
00762             return 0.0;
00763           }
00764           double *wp=(double *)(pit->second.data);                      
00765           return *wp;
00766         }                                                       
00767       }                                                 
00768       O2SCL_ERR("Object not found in collection::getd2().",gsl_enotfound);
00769       return 0.0;
00770     }
00771     
00772     /// Desc
00773     int geti(std::string name) {
00774       piter pit=plist.find(name);                       
00775       if (pit!=plist.end()) {                           
00776         if (((std::string)pit->second.iop->type())=="int") {    
00777           if (pit->second.size!=0 || pit->second.size2!=0) {
00778             O2SCL_ERR("Size of object incorrect in collection::geti2().",
00779                     gsl_efailed);
00780             return 0;
00781           }
00782           int *wp=(int *)(pit->second.data);                    
00783           return *wp;
00784         }                                                       
00785       }                                                 
00786       O2SCL_ERR("Object not found in collection::geti2().",gsl_enotfound);
00787       return 0;
00788     }
00789     
00790     /// Desc
00791     std::string gets(std::string name) {
00792       piter pit=plist.find(name);                       
00793       if (pit!=plist.end()) {                           
00794         if (((std::string)pit->second.iop->type())=="string") { 
00795           if (pit->second.size!=0 || pit->second.size2!=0) {
00796             O2SCL_ERR("Size of object incorrect in collection::gets2().",
00797                     gsl_efailed);
00798             return "";
00799           }
00800           std::string *wp=(std::string *)(pit->second.data);
00801           return *wp;
00802         }                                                       
00803       }
00804       O2SCL_ERR("Object not found in collection::gets2().",gsl_enotfound);
00805       return "";
00806     }
00807     
00808     /// Desc
00809     std::string getw(std::string name) {
00810       piter pit=plist.find(name);                       
00811       if (pit!=plist.end()) {                           
00812         if (((std::string)pit->second.iop->type())=="word") {   
00813           if (pit->second.size!=0 || pit->second.size2!=0) {
00814             O2SCL_ERR("Size of object incorrect in collection::getw2().",
00815                     gsl_efailed);
00816             return "";
00817           }
00818           std::string *wp=(std::string *)(pit->second.data);
00819           return *wp;
00820         }                                                       
00821       }                                                 
00822       O2SCL_ERR("Object not found in collection::getw2().",gsl_enotfound);
00823       return "";
00824     }
00825     
00826 
00827     /// Desc
00828     int getb(std::string name, bool *&op, size_t &sz) {
00829       op=0;
00830       piter pit=plist.find(name);
00831       if (pit!=plist.end()) {
00832         if (((std::string)pit->second.iop->type())=="bool") {
00833           if (pit->second.size==0 || pit->second.size2!=0) {
00834             O2SCL_ERR_RET("Size of object incorrect in collection::get2().",
00835                         gsl_efailed);
00836           }
00837           op=(bool *)(pit->second.data);
00838           sz=pit->second.size;
00839           return gsl_success;
00840         }
00841       }
00842       // 1/9/05 We choose not to set an error here in case
00843       // the user is legitimately looking for something 
00844       // that they don't expect to find.
00845       //  O2SCL_ERR(tname+" not found in get().",not_found);
00846       return gsl_enotfound;
00847     }
00848     
00849     /// Desc
00850     int getb(std::string name, bool **&op, size_t &sz,
00851              size_t &sz2) {
00852       op=0;
00853       piter pit=plist.find(name);
00854       if (pit!=plist.end()) {
00855         if (((std::string)pit->second.iop->type())=="bool") {
00856           if (pit->second.size==0 || pit->second.size2==0) {
00857             O2SCL_ERR_RET("Size of object incorrect in collection::get2().",
00858                         gsl_efailed);
00859           }
00860           op=(bool **)(pit->second.data);
00861           sz=pit->second.size;
00862           sz2=pit->second.size2;
00863           return gsl_success;
00864         }
00865       }
00866       // 1/9/05 We choose not to set an error here in case
00867       // the user is legitimately looking for something 
00868       // that they don't expect to find.
00869       //  O2SCL_ERR(tname+" not found in get().",not_found);
00870       return gsl_enotfound;
00871     }
00872 
00873     /// Desc
00874     int getc(std::string name, char *&op, size_t &sz) {
00875       op=0;
00876       piter pit=plist.find(name);
00877       if (pit!=plist.end()) {
00878         if (((std::string)pit->second.iop->type())=="char") {
00879           if (pit->second.size==0 || pit->second.size2!=0) {
00880             O2SCL_ERR_RET("Size of object incorrect in collection::get2().",
00881                         gsl_efailed);
00882           }
00883           op=(char *)(pit->second.data);
00884           sz=pit->second.size;
00885           return gsl_success;
00886         }
00887       }
00888       // 1/9/05 We choose not to set an error here in case
00889       // the user is legitimately looking for something 
00890       // that they don't expect to find.
00891       //  O2SCL_ERR(tname+" not found in get().",not_found);
00892       return gsl_enotfound;
00893     }
00894     
00895     /// Desc
00896     int getc(std::string name, char **&op, size_t &sz,
00897             size_t &sz2) {
00898       op=0;
00899       piter pit=plist.find(name);
00900       if (pit!=plist.end()) {
00901         if (((std::string)pit->second.iop->type())=="char") {
00902           if (pit->second.size==0 || pit->second.size2==0) {
00903             O2SCL_ERR_RET("Size of object incorrect in collection::get2().",
00904                         gsl_efailed);
00905           }
00906           op=(char **)(pit->second.data);
00907           sz=pit->second.size;
00908           sz2=pit->second.size2;
00909           return gsl_success;
00910         }
00911       }
00912       // 1/9/05 We choose not to set an error here in case
00913       // the user is legitimately looking for something 
00914       // that they don't expect to find.
00915       //  O2SCL_ERR(tname+" not found in get().",not_found);
00916       return gsl_enotfound;
00917     }
00918 
00919     /// Desc
00920     int getd(std::string name, double *&op, size_t &sz) {
00921       op=0;
00922       piter pit=plist.find(name);
00923       if (pit!=plist.end()) {
00924         if (((std::string)pit->second.iop->type())=="double") {
00925           if (pit->second.size==0 || pit->second.size2!=0) {
00926             O2SCL_ERR_RET("Size of object incorrect in collection::get2().",
00927                         gsl_efailed);
00928           }
00929           op=(double *)(pit->second.data);
00930           sz=pit->second.size;
00931           return gsl_success;
00932         }
00933       }
00934       // 1/9/05 We choose not to set an error here in case
00935       // the user is legitimately looking for something 
00936       // that they don't expect to find.
00937       //  O2SCL_ERR(tname+" not found in get().",not_found);
00938       return gsl_enotfound;
00939     }
00940     
00941     /// Desc
00942     int getd(std::string name, double **&op, size_t &sz,
00943              size_t &sz2) {
00944       op=0;
00945       piter pit=plist.find(name);
00946       if (pit!=plist.end()) {
00947         if (((std::string)pit->second.iop->type())=="double") {
00948           if (pit->second.size==0 || pit->second.size2==0) {
00949             O2SCL_ERR_RET("Size of object incorrect in collection::get2().",
00950                         gsl_efailed);
00951           }
00952           op=(double **)(pit->second.data);
00953           sz=pit->second.size;
00954           sz2=pit->second.size2;
00955           return gsl_success;
00956         }
00957       }
00958       // 1/9/05 We choose not to set an error here in case
00959       // the user is legitimately looking for something 
00960       // that they don't expect to find.
00961       //  O2SCL_ERR(tname+" not found in get().",not_found);
00962       return gsl_enotfound;
00963     }
00964 
00965     /// Desc
00966     int geti(std::string name, int *&op, size_t &sz) {
00967       op=0;
00968       piter pit=plist.find(name);
00969       if (pit!=plist.end()) {
00970         if (((std::string)pit->second.iop->type())=="int") {
00971           if (pit->second.size==0 || pit->second.size2!=0) {
00972             O2SCL_ERR_RET("Size of object incorrect in collection::get2().",
00973                         gsl_efailed);
00974           }
00975           op=(int *)(pit->second.data);
00976           sz=pit->second.size;
00977           return gsl_success;
00978         }
00979       }
00980       // 1/9/05 We choose not to set an error here in case
00981       // the user is legitimately looking for something 
00982       // that they don't expect to find.
00983       //  O2SCL_ERR(tname+" not found in get().",not_found);
00984       return gsl_enotfound;
00985     }
00986     
00987     /// Desc
00988     int geti(std::string name, int **&op, size_t &sz,
00989              size_t &sz2) {
00990       op=0;
00991       piter pit=plist.find(name);
00992       if (pit!=plist.end()) {
00993         if (((std::string)pit->second.iop->type())=="int") {
00994           if (pit->second.size==0 || pit->second.size2==0) {
00995             O2SCL_ERR_RET("Size of object incorrect in collection::get2().",
00996                         gsl_efailed);
00997           }
00998           op=(int **)(pit->second.data);
00999           sz=pit->second.size;
01000           sz2=pit->second.size2;
01001           return gsl_success;
01002         }
01003       }
01004       // 1/9/05 We choose not to set an error here in case
01005       // the user is legitimately looking for something 
01006       // that they don't expect to find.
01007       //  O2SCL_ERR(tname+" not found in get().",not_found);
01008       return gsl_enotfound;
01009     }
01010 
01011     /// Desc
01012     int gets(std::string name, std::string *&op, size_t &sz) {
01013       op=0;
01014       piter pit=plist.find(name);
01015       if (pit!=plist.end()) {
01016         if (((std::string)pit->second.iop->type())=="string") {
01017           if (pit->second.size==0 || pit->second.size2!=0) {
01018             O2SCL_ERR_RET("Size of object incorrect in collection::get2().",
01019                         gsl_efailed);
01020           }
01021           op=(std::string *)(pit->second.data);
01022           sz=pit->second.size;
01023           return gsl_success;
01024         }
01025       }
01026       // 1/9/05 We choose not to set an error here in case
01027       // the user is legitimately looking for something 
01028       // that they don't expect to find.
01029       //  O2SCL_ERR(tname+" not found in get().",not_found);
01030       return gsl_enotfound;
01031     }
01032     
01033     /// Desc
01034     int gets(std::string name, std::string **&op, size_t &sz,
01035              size_t &sz2) {
01036       op=0;
01037       piter pit=plist.find(name);
01038       if (pit!=plist.end()) {
01039         if (((std::string)pit->second.iop->type())=="string") {
01040           if (pit->second.size==0 || pit->second.size2==0) {
01041             O2SCL_ERR_RET("Size of object incorrect in collection::get2().",
01042                         gsl_efailed);
01043           }
01044           op=(std::string **)(pit->second.data);
01045           sz=pit->second.size;
01046           sz2=pit->second.size2;
01047           return gsl_success;
01048         }
01049       }
01050       // 1/9/05 We choose not to set an error here in case
01051       // the user is legitimately looking for something 
01052       // that they don't expect to find.
01053       //  O2SCL_ERR(tname+" not found in get().",not_found);
01054       return gsl_enotfound;
01055     }
01056 
01057     /// Desc
01058     int getw(std::string name, std::string *&op, size_t &sz) {
01059       op=0;
01060       piter pit=plist.find(name);
01061       if (pit!=plist.end()) {
01062         if (((std::string)pit->second.iop->type())=="word") {
01063           if (pit->second.size==0 || pit->second.size2!=0) {
01064             O2SCL_ERR_RET("Size of object incorrect in collection::get2().",
01065                         gsl_efailed);
01066           }
01067           op=(std::string *)(pit->second.data);
01068           sz=pit->second.size;
01069           return gsl_success;
01070         }
01071       }
01072       // 1/9/05 We choose not to set an error here in case
01073       // the user is legitimately looking for something 
01074       // that they don't expect to find.
01075       //  O2SCL_ERR(tname+" not found in get().",not_found);
01076       return gsl_enotfound;
01077     }
01078     
01079     /// Desc
01080     int getw(std::string name, std::string **&op, size_t &sz,
01081              size_t &sz2) {
01082       op=0;
01083       piter pit=plist.find(name);
01084       if (pit!=plist.end()) {
01085         if (((std::string)pit->second.iop->type())=="word") {
01086           if (pit->second.size==0 || pit->second.size2==0) {
01087             O2SCL_ERR_RET("Size of object incorrect in collection::get2().",
01088                         gsl_efailed);
01089           }
01090           op=(std::string **)(pit->second.data);
01091           sz=pit->second.size;
01092           sz2=pit->second.size2;
01093           return gsl_success;
01094         }
01095       }
01096       // 1/9/05 We choose not to set an error here in case
01097       // the user is legitimately looking for something 
01098       // that they don't expect to find.
01099       //  O2SCL_ERR(tname+" not found in get().",not_found);
01100       return gsl_enotfound;
01101     }
01102 
01103     //@}
01104     
01105     /// \name Generic type get methods
01106     //@{
01107 
01108     /// Desc
01109     template<class obj_t>
01110       int get(std::string name, obj_t *&op) {
01111       obj_t od;
01112       op=0;
01113       piter pit=plist.find(name);
01114       if (pit!=plist.end()) {
01115         if (((std::string)pit->second.iop->type())==od.type()) {
01116           if (pit->second.size!=0 || pit->second.size2!=0) {
01117             O2SCL_ERR_RET("Size of object incorrect in collection::get2().",
01118                         gsl_efailed);
01119           }
01120           op=(obj_t *)(pit->second.data);
01121           return gsl_success;
01122         }
01123       }
01124       // 1/9/05 We choose not to set an error here in case
01125       // the user is legitimately looking for something