text_file.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_TEXT_FILE_H
00024 #define O2SCL_TEXT_FILE_H
00025 
00026 #include <iostream>
00027 #include <stack>
00028 #include <o2scl/err_hnd.h>
00029 #include <o2scl/file_format.h>
00030 #include <o2scl/misc.h>
00031 #include <o2scl/lib_settings.h>
00032 
00033 #ifndef DOXYGENP
00034 namespace o2scl {
00035 #endif
00036 
00037   /** \brief An output text file
00038 
00039       A collection file is simply a text file containing a list of
00040       objects specially formatted for input and output. Each entry in
00041       the text file is of the form:
00042     
00043       object_type object_name object_version word_number word1 word2 word3 ...
00044     
00045       The type, name, and version are all strings that contain no
00046       whitespace.  "a_name" is a valid name but, "a name" is not.
00047     
00048       Parts of the object definition may be separated by any amount of
00049       whitespace, with the exception of 'strings'.
00050     
00051       The collection file may contain comments, which are lines that begin
00052       with the '#' character. Comments may last more than one line (so long as 
00053       every line begins with '#'), but they may not occur in the middle of
00054       an object definition.
00055       \verbatim
00056       # comment 1
00057       double a 4.0
00058       double[] c 4 
00059       4.5 3.4 2.3 4.2
00060       # comment 2
00061       double b 5.0
00062       \endverbatim
00063       is acceptable, but
00064       \verbatim
00065       # comment 1
00066       double a 4.0
00067       double[] c 4 
00068       4.5 3.4 2.3 4.2
00069       double b
00070       # comment 2
00071       5.0
00072       \endverbatim
00073       is not, since the second comment occurs in the middle of the definition
00074       for the object named 'b'.
00075     
00076       Normal variable:
00077       type name version word data1 ... data2
00078     
00079       Object containing pointer:
00080       type name version word data1 ... ptr_type ptr_name ... data2
00081     
00082       where ptr_type is the type of the object being pointed to
00083       and ptr_name is the name of the object. If it's not in the
00084       list, then the object is assigned a unique name of the
00085       form ptrX where 'X' is an integer >= 0. 
00086     
00087       Static objects are the same, except they are preceeded by 
00088       the keyword \c static  and do not have a name associated with them.
00089     
00090       This is useful for output to text files and to std::cout, i.e.
00091       text_out_file tf(&cout);
00092 
00093       <b>Note:</b> Text files are not entirely architecture-independent,
00094       For example, a larger integer will not be read correctly on small 
00095       integer systems.
00096    */
00097   class text_out_file : public out_file_format {
00098   public:
00099 
00100     /** \brief Use output stream \c out_file  for text output 
00101 
00102         This constructor assumes that the I/O properties of 
00103         \c out_file  have already been set.
00104 
00105         Note that the stream \c out_file  should not have 
00106         been opened in binary mode, and errors will likely occur
00107         if this is the case.
00108 
00109         \todo Ensure streams are not opened in binary mode
00110         for safety.
00111     */
00112     text_out_file(std::ostream *out_file, int width=80);
00113     
00114     /** \brief Create an output file with name \c file_name  
00115         
00116         If \c prop  is not null, then the I/O properties
00117         (precision, fill, flags, etc) for the newly created file are
00118         taken to be the same as \c prop .
00119         
00120     */
00121     text_out_file(std::string file_name, std::ostream *prop=NULL,
00122                   bool append=false, int width=80);
00123 
00124     virtual ~text_out_file();
00125 
00126     /** \brief Output a bool variable
00127      */
00128     virtual int bool_out(bool dat, std::string name="");
00129 
00130     /** \brief Output a char variable
00131      */
00132     virtual int char_out(char dat, std::string name="");
00133 
00134     /** \brief Output a char variable
00135      */
00136     virtual int char_out_internal(char dat, std::string name="");
00137 
00138     /** \brief Output a double variable
00139      */
00140     virtual int double_out(double dat, std::string name="");
00141 
00142     /** \brief Output a float variable
00143      */
00144     virtual int float_out(float dat, std::string name="");
00145 
00146     /** \brief Output an int variable
00147      */
00148     virtual int int_out(int dat, std::string name="");
00149 
00150     /** \brief Output an long variable
00151      */
00152     virtual int long_out(unsigned long int dat, std::string name="");
00153 
00154     /** \brief Output a string
00155      */
00156     virtual int string_out(std::string dat, std::string name="");
00157 
00158     /** \brief Output a word
00159      */
00160     virtual int word_out(std::string dat, std::string name="");
00161     
00162     /** \brief Start object output
00163      */
00164     virtual int start_object(std::string type, std::string name);
00165 
00166     /** \brief End object output
00167      */
00168     virtual int end_object();
00169 
00170     /** \brief End line
00171      */
00172     virtual int end_line();
00173 
00174     /** \brief Output initialization */
00175     virtual int init_file();
00176 
00177     virtual int clean_up() {
00178       return 0;
00179     }
00180     
00181     /** \brief Output a comment (only for text files) */
00182     int comment_out(std::string comment);
00183 
00184     /// Add brackets and replace carriage returns with spaces
00185     std::string reformat_string(std::string in);
00186 
00187 #ifndef DOXYGEN_INTERNAL
00188 
00189   protected:
00190 
00191     friend class collection;
00192 
00193     /** \brief A list to indicate if the current object and subobjects 
00194         are "hard-coded"
00195     */
00196     std::stack<bool> hcs;
00197 
00198     /// True if the constructor was called with a string, false otherwise
00199     bool from_string;
00200 
00201     /// True if the file is to be compressed
00202     bool compressed;
00203 
00204     /// True if the file is to be compressed with gzip
00205     bool gzip;
00206 
00207     /// The width of the file
00208     int file_width;
00209 
00210     /// The output stream
00211     std::ostream *outs;
00212 
00213     /// A pointer to an output stream to define output properties
00214     std::ostream *props;
00215 
00216     /// The temporary buffer as a stringstream
00217     std::ostringstream *strout;
00218 
00219     /// The user-specified filename
00220     std::string user_filename;
00221 
00222     /// The temporary filename used
00223     std::string temp_filename;
00224 
00225     /// Flush the string buffer
00226     virtual int flush();
00227 
00228     /// If true, then \c type is a "hard-coded" type
00229     bool is_hc_type(std::string type);
00230 
00231 #endif
00232                            
00233   };
00234 
00235   /** 
00236       \brief An input text file
00237 
00238       <b>Note:</b> Text files are not entirely architecture-independent,
00239       For example, a larger integer will not be read correctly on small 
00240       integer systems.
00241    */
00242   class text_in_file : public in_file_format {
00243   public:
00244 
00245     /** \brief Use input stream \c in_file for text input */
00246     text_in_file(std::istream *in_file);
00247 
00248     /** \brief Read an input file with name \c file_name  */
00249     text_in_file(std::string file_name);
00250 
00251     virtual ~text_in_file();
00252   
00253     virtual int bool_in(bool &dat, std::string name="");
00254     virtual int char_in(char &dat, std::string name="");
00255     virtual int double_in(double &dat, std::string name="");
00256     virtual int float_in(float &dat, std::string name="");
00257     virtual int int_in(int &dat, std::string name="");
00258     virtual int long_in(unsigned long int &dat, std::string name="");
00259     virtual int string_in(std::string &dat, std::string name="");
00260     virtual int word_in(std::string &dat, std::string name="");
00261     
00262     virtual int start_object(std::string &type, std::string &name);
00263     virtual int skip_object();
00264     virtual int end_object();
00265 
00266     /** \brief Initialize file input */
00267     virtual int init_file();
00268     
00269     /// Finish file input
00270     virtual int clean_up() {
00271       return 0;
00272     }
00273 
00274     /// Add brackets and replace carriage returns with spaces
00275     std::string reformat_string(std::string in);
00276 
00277 #ifndef DOXYGEN_INTERNAL
00278 
00279   protected:
00280 
00281     /// If true, then \c type is a "hard-coded" type
00282     bool is_hc_type(std::string type);
00283 
00284     /** \brief A list to indicate if the current object and subobjects 
00285         are "hard-coded"
00286     */
00287     std::stack<bool> hcs;
00288 
00289     /// The input stream
00290     std::istream *ins;
00291 
00292     /// True if the string version of the constructor was called
00293     bool from_string;
00294 
00295     /// A version of word_in() which doesn't call the error handler
00296     virtual int word_in_noerr(std::string &dat, std::string name="") {
00297       std::string tmp;
00298       if (name.length()>0) (*ins) >> tmp;
00299       if ((*ins) >> dat) {
00300         return 0;
00301       }
00302       return -1;
00303     }
00304     
00305 #endif
00306 
00307   };
00308 
00309 #ifndef DOXYGENP
00310 }
00311 #endif
00312 
00313 #endif

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