MOOCHO (Single Doxygen Collection) Version of the Day
DenseLinAlgPack_IOFormat.hpp
Go to the documentation of this file.
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 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov) 
00038 // 
00039 // ***********************************************************************
00040 // @HEADER
00041 
00042 #ifndef LINALGPACK_IO_FORMAT_H
00043 #define LINALGPACK_IO_FORMAT_H
00044 
00045 #include <ios>
00046 
00047 #include "DenseLinAlgPack_IOBasic.hpp"
00048 
00049 namespace DenseLinAlgPack {
00050 namespace LinAlgPackIO {
00051 
00053 /* * This class is used to encapsulate a set of bit flags.
00054   */
00055 class bit_flags {
00056 public:
00057 
00059   typedef LinAlgPackIO::fmtflags fmtflags;  
00060 
00062   bit_flags() : flags_((fmtflags)(0x0000)) {}
00063 
00065   fmtflags flags() const {
00066     return flags_;
00067   }
00068 
00070   fmtflags flags(fmtflags f) {
00071     fmtflags f_tmp = flags_;
00072     flags_ = f;
00073     return f_tmp;
00074   }
00075 
00077   fmtflags setf(fmtflags f) {
00078     return flags( (fmtflags)(flags() | f) );
00079   }
00080 
00082   fmtflags setf(fmtflags f, fmtflags mask) {
00083     return flags( (fmtflags)(flags() | (f&mask)) );
00084   }
00085 
00087   void unsetf(fmtflags mask) {
00088     flags( (fmtflags)(flags() & ~mask) );
00089   }
00090 
00091 private:
00092   fmtflags flags_;
00093 
00094 };  // end class flags
00095 
00097 /* * Memento class that saves the state of a standard stream.
00098   *
00099   * This is a variation of the "Memento" Pattern in Gama et. al.
00100   *
00101   * Allow default copy constructor and assignment operator.
00102   * The default constuctor is private so the only way to 
00103   * create an object of this class if from another object
00104   * or from save_format().
00105   */
00106 class ios_format_memento {
00107 public:
00109   static ios_format_memento save_format(const std::ios& s);
00110 
00112   void set_format(std::ios& s) const;
00113 
00114 private:
00115   LinAlgPackIO::fmtflags  flags_;
00116   int       prec_;
00117   int       wdt_;
00118   int       fill_;
00119 
00121   ios_format_memento() : flags_((fmtflags)(0)), prec_(6), wdt_(0)
00122     , fill_(' ') {}
00123 
00124 };  // end class ios_format_memento
00125 
00126 template<class T> class bound_format;
00127 template<class T> class const_bound_format;
00128 
00130 /* * This class is used to allow some flexiblility in inputing
00131   * and outputing of DVector, DVectorSlice, DMatrix and DMatrixSlice objects.
00132   * It maintains format information for a #std::ios_base# object and adds
00133   * additional format information.
00134   *
00135   * The idea for this class is based on the user-defined manipulator given in
00136   * Stroustrup 1997, p. 635.  The main difference is that the non-member funciton
00137   * bind(format,object) is used to create a bound format object and not that
00138   * member function operator().  To use operator() would require a template
00139   * member function and they are not supposed to be allowed in MS VC++ 5.0.
00140   *
00141   * Warning: The default constructor sets the formating flags to false but this
00142   * may not be the default value for the actual ios stream.  It is recommended
00143   * that you start with the formating settings of a valid ios stream and then
00144   * change the flags that you want.  You can do this on construction with
00145   *
00146   * #format f(cin);#\\
00147   *
00148   * or after construction using
00149   *
00150   * #format f;#\\
00151   * #f.copy_format(cin);#\\
00152   *
00153   * then set the formating using the manipulator like functions.
00154   *
00155   * The default copy constructor and assignment operator functions are allowed.
00156   */
00157 class format {
00158 public:
00159 
00161   typedef LinAlgPackIO::fmtflags fmtflags;
00162 
00164   format() : prec_(6), wdt_(0), fill_(' ') {}
00165 
00167   format(const std::ios& s) {
00168     copy_format(s);
00169   }
00170 
00171   /* * @name Access format flags objects
00172     */
00173   // @{ 
00174   
00176   bit_flags& ios_base_flags()       { return ios_base_flags_; }
00178   const bit_flags& ios_base_flags() const { return ios_base_flags_; }
00179 
00181   bit_flags& extra_flags()        { return extra_flags_;  }
00183   const bit_flags& extra_flags() const  { return extra_flags_;  }
00184 
00185   // @}
00186 
00187   /* * @name Manipulator like functions for standard floating-point number formating.
00188     *
00189     * These member functions are ment to mirror the standard input/output
00190     * manipulator functions.  Their names are the same and you can set
00191     * a list of options in one statement like:
00192     *
00193     * #format_obj.showpos().setprecision(6).fixed();#\\
00194     *
00195     * The primary difference is that #width# presists over all uses in output
00196     * operations while the standard #width# manipulator only applys to the next
00197     * operation.  See \Ref{bound_format} and \Ref{operator>>} for details
00198     * on how objects of this class are used to specify formating for input/output
00199     * operations.
00200     */
00201   // @{
00202 
00204   format& showpoint()   { ios_base_flags().setf(std::ios_base::showpoint); return *this;  }
00206   format& noshowpoint() { ios_base_flags().unsetf(std::ios_base::showpoint); return *this;  }
00208   format& showpos()   { ios_base_flags().setf(std::ios_base::showpos); return *this;  }
00210   format& noshowpos()   { ios_base_flags().unsetf(std::ios_base::showpos); return *this;  }
00212   format& skipws()    { ios_base_flags().setf(std::ios_base::skipws); return *this; }
00214   format& noskipws()    { ios_base_flags().unsetf(std::ios_base::skipws); return *this; }
00216   format& uppercase()   { ios_base_flags().setf(std::ios_base::uppercase); return *this;  }
00218   format& nouppercase() { ios_base_flags().unsetf(std::ios_base::uppercase); return *this;  }
00220   format& internal()    {
00221     ios_base_flags().setf(std::ios_base::internal, std::ios_base::adjustfield);
00222     return *this;
00223   }
00225   format& left()      {
00226     ios_base_flags().setf(std::ios_base::left, std::ios_base::adjustfield);
00227     return *this;
00228   }
00230   format& right()     {
00231     ios_base_flags().setf(std::ios_base::right, std::ios_base::adjustfield);
00232     return *this;
00233   }
00235   format& general()   {
00236     ios_base_flags().setf((fmtflags)0, std::ios_base::floatfield);
00237     return *this;
00238   }
00240   format& fixed()     {
00241     ios_base_flags().setf(std::ios_base::fixed, std::ios_base::floatfield);
00242     return *this;
00243   }
00245   format& scientific()  {
00246     ios_base_flags().setf(std::ios_base::scientific, std::ios_base::floatfield);
00247     return *this;
00248   }
00250   format& setfill(int c)  { fill_ = c; return *this;  }
00252   format& setprecision(int p) { prec_ = p; return *this;  }
00254   format& setw(int w)   { wdt_ = w; return *this; }
00255 
00256   // @}
00257 
00258   /* * @name Manipulator like functions for extra I/O formatin.
00259     *
00260     * These member functions are ment to mirror the type of standard input/output
00261     * manipulator functions accept they are used to set extra flags for 
00262     * #DenseLinAlgPack::ignore_dim_bit# and #DenseLinAlgPack::no_insert_newlines_bit#.
00263     * This allows them to be set in the same statement that sets a standard
00264     * option.  For example you can write:
00265     *
00266     * #format_obj.showpos().setprecision(6).fixed().ignore_dim().no_insert_newlines();#\\
00267     *
00268     * Like the member functions that simulate the standard manipulators these
00269     * options presist after input/output operations.
00270     */
00271   // @{
00272 
00274   format& ignore_dim()
00275   {
00276     extra_flags().setf((fmtflags)(ignore_dim_bit));
00277     return *this;
00278   }
00280   format& no_ignore_dim()
00281   {
00282     extra_flags().unsetf((fmtflags)(ignore_dim_bit));
00283     return *this;
00284   }
00286   format& insert_newlines()
00287   {
00288     extra_flags().unsetf((fmtflags)(no_insert_newlines_bit));
00289     return *this;
00290   }
00292   format& no_insert_newlines()
00293   {
00294     extra_flags().setf((fmtflags)(no_insert_newlines_bit));
00295     return *this;
00296   }
00297 
00298   // @}
00299 
00300   /* * @name Other access functions
00301     */
00302   // @{
00303 
00305   int precision() const     { return prec_; }
00307   int precision(int p)      { int tmp = prec_; prec_ = p; return tmp; }
00309   int width() const       { return wdt_;  }
00311   int width(int w)        { int tmp = wdt_; wdt_ = w; return tmp; }
00313   int fill() const        { return fill_; }
00315   int fill(int c)         { int tmp = fill_; fill_ = c; return tmp; }
00316 
00317   // @}
00318 
00319   /* * @name Utility functions for saving and replacing a streams format state
00320     */
00321   // @{
00322 
00324   void copy_format(const std::ios& s);
00325 
00327   void set_format(std::ios& s) const;
00328   
00329   // @}
00330 
00331 
00332 // ToDo: Enable these once member templates are supported.  This is much more
00333 // attractive syntasticaly than using bind() and cbind() 
00334 //
00335 //  ///
00336 //  template<class T>
00337 //  bound_format<T> operator()(T& obj);
00338 //
00339 //  ///
00340 //  template<class T>
00341 //  const_bound_format<T> operator()(const T& obj) const;
00342 
00343 private:
00344   bit_flags ios_base_flags_;
00345   bit_flags extra_flags_;
00346   int prec_;
00347   int wdt_;
00348   int fill_;
00349 
00350 };  // end class LinAlgPackIOFormat
00351 
00352 
00353 // ////////////////////////////////////////////////////////////////////////////////
00354 // Format binding classes and functions
00355 
00356 template<class T> class const_bound_format;
00357 
00359 /* * Special I/O manipulator class for non-constant objects.
00360   *
00361   * This class as a special manipulator and is composed of a composition
00362   * of a format object and a templated object that is used in an input
00363   * or output operation.
00364   *
00365   * An object of this class should only be created by using 
00366   * the bind(format,obj) function.  It object can not default constructed
00367   * or assigned.
00368   *
00369   * Objects of this class can be implicitly converted to const_bound_format
00370   * for use in output operations.
00371   */
00372 template<class T>
00373 class bound_format {
00374 public:
00375 
00377   bound_format(const format& f, T& obj) : f_(f), obj_(obj) {}
00378 
00380   const format& f() const { return f_; }
00382   T&  obj()       { return obj_; }
00384   const T& obj() const  { return obj_; }
00385   
00386 private:
00387   const format& f_;
00388   T&        obj_;
00389 
00390   // not defined and not to be called
00391   bound_format();
00392   bound_format& operator=(const bound_format&);
00393 
00394 };  // end class bound_format
00395 
00397 /* * Special I/O manipulator class for constant objects.
00398   *
00399   * This class as a special manipulator and is composed of a composition
00400   * of a format object and a const templated object that is used only in
00401   * an output operation.
00402   *
00403   * An object of this class can only be created by using 
00404   * the bind(f,obj) operation.  It can not be default constructed or assigned.
00405   * It is only to be used in input or output operations.
00406   */
00407 template<class T>
00408 class const_bound_format {
00409 public:
00410 
00412   const_bound_format(const format& f, const T& obj) : f_(f), obj_(obj) {}
00413 
00415   const_bound_format(const bound_format<T>& bf) : f_(bf.f()), obj_(bf.obj()) {}
00416 
00418   const format& f() const { return f_; }
00420   const T& obj() const  { return obj_; }
00421 
00422 private:
00423   const format& f_;
00424   const T&    obj_;
00425 
00426   // not defined and not to be called
00427   const_bound_format();
00428   const_bound_format& operator=(const const_bound_format&);
00429 
00430 };  // end class const_bound_format
00431 
00433 /* * Returns a bound_format<T> object using this format object.
00434   *
00435   * Using templated input/output operator functions this function
00436   * is used to bind a format to a non-const target object for a
00437   * input/output stream operation.  For example, to bind the format 
00438   * for a single output operation using the streams set formating 
00439   * and addition formating use something like:
00440   *
00441   * #DVector v(1.0,5);#\\
00442   * #format f; f.copy_format(cout);#\\
00443   * #f.width(10).fixed().ignore_dim();#\\
00444   * #cout << bind(f,v);#\\1
00445   */
00446 template<class T>
00447 inline bound_format<T> bind(const format& f, T& obj) {
00448   return bound_format<T>(f,obj);
00449 }
00450 
00452 /* * Returns a const_bound_format<T> using this format object.
00453   *
00454   * This function works the same as the previous \Ref{bind}#()# function
00455   * accept it is for a const target object.  It could not use
00456   * the name #bind# due to ambiguity problems.
00457   */
00458 template<class T>
00459 inline const_bound_format<T> cbind(const format& f, const T& obj) {
00460   return const_bound_format<T>(f,obj);
00461 }
00462 
00463 // ///////////////////////////////////////
00464 // Inline functions for members of format
00465 
00466 // Use once member templates are supported.  See class format
00467 //
00468 //template<class T>
00469 //inline bound_format<T> format::operator()(T& obj) {
00470 //  return bind(*this,obj);
00471 //}
00472 
00473 //template<class T>
00474 //inline const_bound_format<T> format::operator()(const T& obj) const {
00475 //  return cbind(*this,obj);
00476 //}
00477 
00478 } // end namespace LinAlgPackIO
00479 } // end namespace DenseLinAlgPack
00480 
00481 #endif // LINALGPACK_IO_FORMAT_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines