DenseLinAlgPack_IOFormat.hpp

00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 // Moocho: Multi-functional Object-Oriented arCHitecture for Optimization
00005 //                  Copyright (2003) Sandia Corporation
00006 // 
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 // 
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov) 
00025 // 
00026 // ***********************************************************************
00027 // @HEADER
00028 
00029 #ifndef LINALGPACK_IO_FORMAT_H
00030 #define LINALGPACK_IO_FORMAT_H
00031 
00032 #include <ios>
00033 
00034 #include "DenseLinAlgPack_IOBasic.hpp"
00035 
00036 namespace DenseLinAlgPack {
00037 namespace LinAlgPackIO {
00038 
00040 /* * This class is used to encapsulate a set of bit flags.
00041   */
00042 class bit_flags {
00043 public:
00044 
00046   typedef LinAlgPackIO::fmtflags fmtflags;  
00047 
00049   bit_flags() : flags_((fmtflags)(0x0000)) {}
00050 
00052   fmtflags flags() const {
00053     return flags_;
00054   }
00055 
00057   fmtflags flags(fmtflags f) {
00058     fmtflags f_tmp = flags_;
00059     flags_ = f;
00060     return f_tmp;
00061   }
00062 
00064   fmtflags setf(fmtflags f) {
00065     return flags( (fmtflags)(flags() | f) );
00066   }
00067 
00069   fmtflags setf(fmtflags f, fmtflags mask) {
00070     return flags( (fmtflags)(flags() | (f&mask)) );
00071   }
00072 
00074   void unsetf(fmtflags mask) {
00075     flags( (fmtflags)(flags() & ~mask) );
00076   }
00077 
00078 private:
00079   fmtflags flags_;
00080 
00081 };  // end class flags
00082 
00084 /* * Memento class that saves the state of a standard stream.
00085   *
00086   * This is a variation of the "Memento" Pattern in Gama et. al.
00087   *
00088   * Allow default copy constructor and assignment operator.
00089   * The default constuctor is private so the only way to 
00090   * create an object of this class if from another object
00091   * or from save_format().
00092   */
00093 class ios_format_memento {
00094 public:
00096   static ios_format_memento save_format(const std::ios& s);
00097 
00099   void set_format(std::ios& s) const;
00100 
00101 private:
00102   LinAlgPackIO::fmtflags  flags_;
00103   int       prec_;
00104   int       wdt_;
00105   int       fill_;
00106 
00108   ios_format_memento() : flags_((fmtflags)(0)), prec_(6), wdt_(0)
00109     , fill_(' ') {}
00110 
00111 };  // end class ios_format_memento
00112 
00113 template<class T> class bound_format;
00114 template<class T> class const_bound_format;
00115 
00117 /* * This class is used to allow some flexiblility in inputing
00118   * and outputing of DVector, DVectorSlice, DMatrix and DMatrixSlice objects.
00119   * It maintains format information for a #std::ios_base# object and adds
00120   * additional format information.
00121   *
00122   * The idea for this class is based on the user-defined manipulator given in
00123   * Stroustrup 1997, p. 635.  The main difference is that the non-member funciton
00124   * bind(format,object) is used to create a bound format object and not that
00125   * member function operator().  To use operator() would require a template
00126   * member function and they are not supposed to be allowed in MS VC++ 5.0.
00127   *
00128   * Warning: The default constructor sets the formating flags to false but this
00129   * may not be the default value for the actual ios stream.  It is recommended
00130   * that you start with the formating settings of a valid ios stream and then
00131   * change the flags that you want.  You can do this on construction with
00132   *
00133   * #format f(cin);#\\
00134   *
00135   * or after construction using
00136   *
00137   * #format f;#\\
00138   * #f.copy_format(cin);#\\
00139   *
00140   * then set the formating using the manipulator like functions.
00141   *
00142   * The default copy constructor and assignment operator functions are allowed.
00143   */
00144 class format {
00145 public:
00146 
00148   typedef LinAlgPackIO::fmtflags fmtflags;
00149 
00151   format() : prec_(6), wdt_(0), fill_(' ') {}
00152 
00154   format(const std::ios& s) {
00155     copy_format(s);
00156   }
00157 
00158   /* * @name Access format flags objects
00159     */
00160   // @{ 
00161   
00163   bit_flags& ios_base_flags()       { return ios_base_flags_; }
00165   const bit_flags& ios_base_flags() const { return ios_base_flags_; }
00166 
00168   bit_flags& extra_flags()        { return extra_flags_;  }
00170   const bit_flags& extra_flags() const  { return extra_flags_;  }
00171 
00172   // @}
00173 
00174   /* * @name Manipulator like functions for standard floating-point number formating.
00175     *
00176     * These member functions are ment to mirror the standard input/output
00177     * manipulator functions.  Their names are the same and you can set
00178     * a list of options in one statement like:
00179     *
00180     * #format_obj.showpos().setprecision(6).fixed();#\\
00181     *
00182     * The primary difference is that #width# presists over all uses in output
00183     * operations while the standard #width# manipulator only applys to the next
00184     * operation.  See \Ref{bound_format} and \Ref{operator>>} for details
00185     * on how objects of this class are used to specify formating for input/output
00186     * operations.
00187     */
00188   // @{
00189 
00191   format& showpoint()   { ios_base_flags().setf(std::ios_base::showpoint); return *this;  }
00193   format& noshowpoint() { ios_base_flags().unsetf(std::ios_base::showpoint); return *this;  }
00195   format& showpos()   { ios_base_flags().setf(std::ios_base::showpos); return *this;  }
00197   format& noshowpos()   { ios_base_flags().unsetf(std::ios_base::showpos); return *this;  }
00199   format& skipws()    { ios_base_flags().setf(std::ios_base::skipws); return *this; }
00201   format& noskipws()    { ios_base_flags().unsetf(std::ios_base::skipws); return *this; }
00203   format& uppercase()   { ios_base_flags().setf(std::ios_base::uppercase); return *this;  }
00205   format& nouppercase() { ios_base_flags().unsetf(std::ios_base::uppercase); return *this;  }
00207   format& internal()    {
00208     ios_base_flags().setf(std::ios_base::internal, std::ios_base::adjustfield);
00209     return *this;
00210   }
00212   format& left()      {
00213     ios_base_flags().setf(std::ios_base::left, std::ios_base::adjustfield);
00214     return *this;
00215   }
00217   format& right()     {
00218     ios_base_flags().setf(std::ios_base::right, std::ios_base::adjustfield);
00219     return *this;
00220   }
00222   format& general()   {
00223     ios_base_flags().setf((fmtflags)0, std::ios_base::floatfield);
00224     return *this;
00225   }
00227   format& fixed()     {
00228     ios_base_flags().setf(std::ios_base::fixed, std::ios_base::floatfield);
00229     return *this;
00230   }
00232   format& scientific()  {
00233     ios_base_flags().setf(std::ios_base::scientific, std::ios_base::floatfield);
00234     return *this;
00235   }
00237   format& setfill(int c)  { fill_ = c; return *this;  }
00239   format& setprecision(int p) { prec_ = p; return *this;  }
00241   format& setw(int w)   { wdt_ = w; return *this; }
00242 
00243   // @}
00244 
00245   /* * @name Manipulator like functions for extra I/O formatin.
00246     *
00247     * These member functions are ment to mirror the type of standard input/output
00248     * manipulator functions accept they are used to set extra flags for 
00249     * #DenseLinAlgPack::ignore_dim_bit# and #DenseLinAlgPack::no_insert_newlines_bit#.
00250     * This allows them to be set in the same statement that sets a standard
00251     * option.  For example you can write:
00252     *
00253     * #format_obj.showpos().setprecision(6).fixed().ignore_dim().no_insert_newlines();#\\
00254     *
00255     * Like the member functions that simulate the standard manipulators these
00256     * options presist after input/output operations.
00257     */
00258   // @{
00259 
00261   format& ignore_dim()
00262   {
00263     extra_flags().setf((fmtflags)(ignore_dim_bit));
00264     return *this;
00265   }
00267   format& no_ignore_dim()
00268   {
00269     extra_flags().unsetf((fmtflags)(ignore_dim_bit));
00270     return *this;
00271   }
00273   format& insert_newlines()
00274   {
00275     extra_flags().unsetf((fmtflags)(no_insert_newlines_bit));
00276     return *this;
00277   }
00279   format& no_insert_newlines()
00280   {
00281     extra_flags().setf((fmtflags)(no_insert_newlines_bit));
00282     return *this;
00283   }
00284 
00285   // @}
00286 
00287   /* * @name Other access functions
00288     */
00289   // @{
00290 
00292   int precision() const     { return prec_; }
00294   int precision(int p)      { int tmp = prec_; prec_ = p; return tmp; }
00296   int width() const       { return wdt_;  }
00298   int width(int w)        { int tmp = wdt_; wdt_ = w; return tmp; }
00300   int fill() const        { return fill_; }
00302   int fill(int c)         { int tmp = fill_; fill_ = c; return tmp; }
00303 
00304   // @}
00305 
00306   /* * @name Utility functions for saving and replacing a streams format state
00307     */
00308   // @{
00309 
00311   void copy_format(const std::ios& s);
00312 
00314   void set_format(std::ios& s) const;
00315   
00316   // @}
00317 
00318 
00319 // ToDo: Enable these once member templates are supported.  This is much more
00320 // attractive syntasticaly than using bind() and cbind() 
00321 //
00322 //  ///
00323 //  template<class T>
00324 //  bound_format<T> operator()(T& obj);
00325 //
00326 //  ///
00327 //  template<class T>
00328 //  const_bound_format<T> operator()(const T& obj) const;
00329 
00330 private:
00331   bit_flags ios_base_flags_;
00332   bit_flags extra_flags_;
00333   int prec_;
00334   int wdt_;
00335   int fill_;
00336 
00337 };  // end class LinAlgPackIOFormat
00338 
00339 
00340 // ////////////////////////////////////////////////////////////////////////////////
00341 // Format binding classes and functions
00342 
00343 template<class T> class const_bound_format;
00344 
00346 /* * Special I/O manipulator class for non-constant objects.
00347   *
00348   * This class as a special manipulator and is composed of a composition
00349   * of a format object and a templated object that is used in an input
00350   * or output operation.
00351   *
00352   * An object of this class should only be created by using 
00353   * the bind(format,obj) function.  It object can not default constructed
00354   * or assigned.
00355   *
00356   * Objects of this class can be implicitly converted to const_bound_format
00357   * for use in output operations.
00358   */
00359 template<class T>
00360 class bound_format {
00361 public:
00362 
00364   bound_format(const format& f, T& obj) : f_(f), obj_(obj) {}
00365 
00367   const format& f() const { return f_; }
00369   T&  obj()       { return obj_; }
00371   const T& obj() const  { return obj_; }
00372   
00373 private:
00374   const format& f_;
00375   T&        obj_;
00376 
00377   // not defined and not to be called
00378   bound_format();
00379   bound_format& operator=(const bound_format&);
00380 
00381 };  // end class bound_format
00382 
00384 /* * Special I/O manipulator class for constant objects.
00385   *
00386   * This class as a special manipulator and is composed of a composition
00387   * of a format object and a const templated object that is used only in
00388   * an output operation.
00389   *
00390   * An object of this class can only be created by using 
00391   * the bind(f,obj) operation.  It can not be default constructed or assigned.
00392   * It is only to be used in input or output operations.
00393   */
00394 template<class T>
00395 class const_bound_format {
00396 public:
00397 
00399   const_bound_format(const format& f, const T& obj) : f_(f), obj_(obj) {}
00400 
00402   const_bound_format(const bound_format<T>& bf) : f_(bf.f()), obj_(bf.obj()) {}
00403 
00405   const format& f() const { return f_; }
00407   const T& obj() const  { return obj_; }
00408 
00409 private:
00410   const format& f_;
00411   const T&    obj_;
00412 
00413   // not defined and not to be called
00414   const_bound_format();
00415   const_bound_format& operator=(const const_bound_format&);
00416 
00417 };  // end class const_bound_format
00418 
00420 /* * Returns a bound_format<T> object using this format object.
00421   *
00422   * Using templated input/output operator functions this function
00423   * is used to bind a format to a non-const target object for a
00424   * input/output stream operation.  For example, to bind the format 
00425   * for a single output operation using the streams set formating 
00426   * and addition formating use something like:
00427   *
00428   * #DVector v(1.0,5);#\\
00429   * #format f; f.copy_format(cout);#\\
00430   * #f.width(10).fixed().ignore_dim();#\\
00431   * #cout << bind(f,v);#\\1
00432   */
00433 template<class T>
00434 inline bound_format<T> bind(const format& f, T& obj) {
00435   return bound_format<T>(f,obj);
00436 }
00437 
00439 /* * Returns a const_bound_format<T> using this format object.
00440   *
00441   * This function works the same as the previous \Ref{bind}#()# function
00442   * accept it is for a const target object.  It could not use
00443   * the name #bind# due to ambiguity problems.
00444   */
00445 template<class T>
00446 inline const_bound_format<T> cbind(const format& f, const T& obj) {
00447   return const_bound_format<T>(f,obj);
00448 }
00449 
00450 // ///////////////////////////////////////
00451 // Inline functions for members of format
00452 
00453 // Use once member templates are supported.  See class format
00454 //
00455 //template<class T>
00456 //inline bound_format<T> format::operator()(T& obj) {
00457 //  return bind(*this,obj);
00458 //}
00459 
00460 //template<class T>
00461 //inline const_bound_format<T> format::operator()(const T& obj) const {
00462 //  return cbind(*this,obj);
00463 //}
00464 
00465 } // end namespace LinAlgPackIO
00466 } // end namespace DenseLinAlgPack
00467 
00468 #endif // LINALGPACK_IO_FORMAT_H

Generated on Wed May 12 21:50:38 2010 for DenseLinAlgPack: Concreate C++ Classes for Dense Blas-Compatible Linear Algebra by  doxygen 1.4.7