floats.hpp
Go to the documentation of this file.
00001 
00008 /*****************************************************************************
00009 ** Ifdefs
00010 *****************************************************************************/
00011 
00012 #ifndef ECL_FORMATTERS_FLOATS_HPP_
00013 #define ECL_FORMATTERS_FLOATS_HPP_
00014 
00015 /*****************************************************************************
00016 ** Includes
00017 *****************************************************************************/
00018 
00019 #include <cstdio>   // snprintf
00020 #include <cstring>  // strlen
00021 #include "common.hpp"
00022 #include <ecl/exceptions/standard_exception.hpp>
00023 
00024 #if _MSC_VER
00025 #define snprintf _snprintf
00026 #endif
00027 
00028 /*****************************************************************************
00029 ** Namespaces
00030 *****************************************************************************/
00031 
00032 namespace ecl {
00033 
00034 /*****************************************************************************
00035 ** Format Tags
00036 *****************************************************************************/
00042 enum FloatBase
00043 {
00044     Fixed,  
00045     Sci,    
00046 };
00047 
00048 namespace interfaces {
00049 
00050 /*****************************************************************************
00051 ** FormatFloat
00052 *****************************************************************************/
00053 
00060 template <typename Number>
00061 class FormatFloat {
00062 public:
00063         /******************************************
00064         ** C&D's
00065         *******************************************/
00073         FormatFloat(const int w = -1, const unsigned int p = 4, const ecl::Alignment a = NoAlign, const ecl::FloatBase b = Fixed) :
00074                 prm_width(w),
00075                 prm_precision(p),
00076                 prm_alignment(a),
00077                 prm_base(b),
00078                 width_(&prm_width),
00079                 precision_(&prm_precision),
00080                 alignment_(&prm_alignment),
00081                 base_(&prm_base),
00082                 ready_to_format(false) {}
00083 
00084         virtual ~FormatFloat() {}
00085 
00086         /******************************************
00087         ** Set Format Parameters
00088         *******************************************/
00097         FormatFloat<Number>& precision(const unsigned int p) { *precision_ = p; return *this; }
00106         FormatFloat<Number>& width(const int w);
00115         FormatFloat<Number>& align(const ecl::Alignment a);
00124         FormatFloat<Number>& base(const ecl::FloatBase b);
00125 
00126         /******************************************
00127         ** Get Format Parameters
00128         *******************************************/
00133         int precision() { return *precision_; }
00134 
00140         int width() { return *width_; }
00141 
00142         /******************************************
00143          * Set Format Combinations
00144          ******************************************/
00151         FormatFloat<Number>& operator()(unsigned int p, const int w);
00160         FormatFloat<Number>& operator()(const unsigned int p, const int w, const ecl::Alignment align, const ecl::FloatBase b);
00161 
00162         /******************************************
00163         ** Format a value
00164         *******************************************/
00175         FormatFloat<Number>& operator() (const Number n);
00176 
00177         /******************************************
00178         ** Format for streaming
00179         *******************************************/
00186         FormatFloat<Number>& operator() (const Number n, const unsigned int p, const int w);
00195         FormatFloat<Number>& operator() (const Number n, const unsigned int p, const int w, const ecl::Alignment align, const ecl::FloatBase b);
00196 
00197         /******************************************
00198         ** Insert the formatter into a stream
00199         *******************************************/
00208 template <typename OutputStream, typename N>
00209 friend OutputStream& operator << (OutputStream& ostream, FormatFloat<N>& formatter) ecl_assert_throw_decl(StandardException);
00210 
00211 protected:
00212         /******************************************
00213         ** Parameters
00214         *******************************************/
00215         int prm_width,tmp_width;
00216         int prm_precision,tmp_precision;
00217         ecl::Alignment prm_alignment,tmp_alignment;
00218         ecl::FloatBase prm_base,tmp_base;
00219         int *width_, *precision_;
00220         ecl::Alignment *alignment_;
00221         ecl::FloatBase *base_;
00222         bool ready_to_format;
00223         Number value_;
00224 
00225         /******************************************
00226         ** Padding
00227         *******************************************/
00228         template <typename OutputStream> void pad(int n, OutputStream &ostream) const;
00229         template <typename OutputStream> void prePad(int n, OutputStream &ostream) const;
00230         template <typename OutputStream> void postPad(int n, OutputStream &ostream) const;
00231 
00232         /******************************************
00233         ** Formatter Functions
00234         *******************************************/
00235         template <typename OutputStream> void formatFixed(OutputStream &ostream) const;
00236         template <typename OutputStream> void formatSci(OutputStream &ostream) const;
00237 };
00238 
00239 /*****************************************************************************
00240 * FormatFloat Implementation  [single parameter configuration]
00241 *****************************************************************************/
00247 template <typename Number>
00248 FormatFloat<Number>& FormatFloat<Number>::base(const ecl::FloatBase b)
00249 {
00250     *base_ = b;
00251     return *this;
00252 }
00257 template <typename Number>
00258 FormatFloat<Number>& FormatFloat<Number>::width(const int w)
00259 {
00260     *width_ = w;
00261     if ( ( *width_ > 0 ) && ( *alignment_ == NoAlign ) )
00262     {
00263         *alignment_ = RightAlign;
00264     }
00265     return *this;
00266 }
00267 
00273 template <typename Number>
00274 FormatFloat<Number>& FormatFloat<Number>::align(const ecl::Alignment a)
00275 {
00276     *alignment_ = a;
00277     if ( *alignment_ == NoAlign )
00278     {
00279         *width_ = 0;
00280     }
00281     return *this;
00282 }
00283 
00284 /*****************************************************************************
00285 * FormatFloat Implementation [format combination configuration]
00286 *****************************************************************************/
00287 
00288 template <typename Number>
00289 FormatFloat<Number>& FormatFloat<Number>::operator () (const unsigned int p, const int w)
00290 {
00291     width(w);
00292     precision(p);
00293     return *this;
00294 }
00295 
00296 template <typename Number>
00297 FormatFloat<Number>& FormatFloat<Number>::operator () (const unsigned int p, const int w, const ecl::Alignment a, const ecl::FloatBase b)
00298 {
00299     width(w);
00300     precision(p);
00301     align(a);
00302     base(b);
00303   return *this;
00304 }
00305 
00306 /*****************************************************************************
00307 * FormatFloat Implementation [value]
00308 *****************************************************************************/
00309 template <typename Number>
00310 FormatFloat<Number>& FormatFloat<Number>::operator()(const Number n)
00311 {
00312     value_ = n;
00313     ready_to_format = true;
00314   return *this;
00315 }
00316 /*****************************************************************************
00317 * FormatFloat Implementation [temporary formatting]
00318 *****************************************************************************/
00319 template <typename Number>
00320 FormatFloat<Number>& FormatFloat<Number>::operator() (const Number n, unsigned int p, const int w)
00321 {
00322     width_ = &tmp_width;
00323     width(w);
00324 
00325     precision_ = &tmp_precision;
00326     precision(p);
00327 
00328     alignment_ = &tmp_alignment;
00329     align(prm_alignment);
00330 
00331     base_ = &tmp_base;
00332     base(prm_base);
00333 
00334     value_ = n;
00335     ready_to_format = true;
00336     return *this;
00337 }
00338 
00339 template <typename Number>
00340 FormatFloat<Number>& FormatFloat<Number>::operator() (const Number n, const unsigned int p, const int w, const ecl::Alignment a, const ecl::FloatBase b)
00341 {
00342     width_ = &tmp_width;
00343     width(w);
00344 
00345     precision_ = &tmp_precision;
00346     precision(p);
00347 
00348     alignment_ = &tmp_alignment;
00349     align(a);
00350 
00351     base_ = &tmp_base;
00352     base(b);
00353 
00354     value_ = n;
00355     ready_to_format = true;
00356     return *this;
00357 }
00358 
00359 
00360 /*****************************************************************************
00361 * FormatFloat Implementation [internal formatting]
00362 *****************************************************************************/
00363 template <typename Number>
00364   template <typename OutputStream>
00365 void FormatFloat<Number>::formatFixed(OutputStream &ostream) const
00366 {
00367     static char format_specifier[6] = "%.xff";
00368     if ( *precision_ < 10 ) {
00369         format_specifier[2] = '0'+*precision_;
00370         format_specifier[3] = 'f';
00371         format_specifier[4] = '\0';
00372     } else if ( *precision_ < 20 )  {
00373         format_specifier[2] = '1';
00374         format_specifier[3] = '0'+(*precision_ - 10);
00375         format_specifier[4] = 'f';
00376     } else {
00377         format_specifier[2] = '2';
00378         format_specifier[3] = '0';
00379         format_specifier[4] = 'f';
00380     }
00381     static const int buffer_size = 30;
00382     static char buffer[buffer_size];
00383 
00384     snprintf(buffer, buffer_size, format_specifier, value_);
00385 
00386     /******************************************
00387     ** Streaming out
00388     *******************************************/
00389     int length = strlen(buffer);
00390     prePad(*width_ - length,ostream);
00391     ostream << buffer;
00392     postPad(*width_ - length,ostream);
00393 }
00394 
00395 template <typename Number>
00396   template <typename OutputStream>
00397 void FormatFloat<Number>::formatSci(OutputStream &ostream) const
00398 {
00399     ostream << "Scientific format is not yet supported." << "\n";
00400     ostream.flush();
00401 }
00402 
00403 template <typename Number>
00404   template <typename OutputStream>
00405 void FormatFloat<Number>::prePad(int n, OutputStream &ostream) const
00406 {
00407     if ( n <= 0 ) { return; }
00408     switch ( *alignment_ )
00409     {
00410         case ( NoAlign ) : { break; }
00411         case ( LeftAlign ) : { break; }
00412         case ( RightAlign ) : { pad(n,ostream); break; }
00413         case ( CentreAlign ) : { pad(n/2+ n%2,ostream); break; } // Add the remainder
00414         default : break;
00415     }
00416 }
00417 
00418 template <typename Number>
00419   template <typename OutputStream>
00420 void FormatFloat<Number>::postPad(int n, OutputStream &ostream) const
00421 {
00422     if ( n <= 0 ) { return; }
00423     switch ( *alignment_ )
00424     {
00425         case ( NoAlign ) : { break; }
00426         case ( LeftAlign ) : { pad(n,ostream); break; }
00427         case ( RightAlign ) : { break; }
00428         case ( CentreAlign ) : { pad(n/2,ostream); break; }  // Do not add the remainder
00429         default : break;
00430     }
00431 }
00432 
00433 template <typename Number>
00434   template <typename OutputStream>
00435 void FormatFloat<Number>::pad(int n, OutputStream &ostream) const
00436 {
00437     for (int i = n; i > 0; --i )
00438     {
00439         ostream << ' ';
00440     }
00441 }
00442 
00443 /*****************************************************************************
00444 * FormatFloat Implementation [streaming]
00445 *****************************************************************************/
00446 template <typename OutputStream, typename N>
00447 OutputStream& operator << (OutputStream &ostream, FormatFloat<N>& formatter ) ecl_assert_throw_decl(StandardException)
00448 {
00449     bool ready = formatter.ready_to_format;
00450 
00451     ecl_assert_throw(ready, StandardException(LOC,UsageError,"The formatter cannot print any data - "
00452             "either there is no data available, or you have tried to use the "
00453             "formatter more than once in a single streaming operation. "
00454             "C++ produces unspecified results when functors are used multiply "
00455             "in the same stream sequence, so this is not permitted here.") );
00456 
00457     if ( ready )
00458     {
00459         switch(*(formatter.base_) )
00460         {
00461             case(Fixed) : {
00462                 formatter.formatFixed(ostream);
00463                 break;
00464             }
00465             case(Sci) : {
00466                 formatter.formatSci(ostream);
00467                 break;
00468             }
00469         }
00470 
00471         // Switch pointers back to prms if not already there.
00472         if ( formatter.width_ != &(formatter.prm_width) ) {
00473             formatter.width_ = &(formatter.prm_width);
00474             formatter.precision_ = &(formatter.prm_precision);
00475             formatter.alignment_ = &(formatter.prm_alignment);
00476             formatter.base_ = &(formatter.prm_base);
00477         }
00478         formatter.ready_to_format = false;
00479     }
00480     return ostream;
00481 }
00482 
00483 } // namespace interfaces
00484 
00485 /*****************************************************************************
00486 * Format Classes
00487 *****************************************************************************/
00495 template <>
00496 class Format<float> : public interfaces::FormatFloat<float>
00497 {
00498     public:
00506         Format(int w = -1, int p = 4, Alignment a = NoAlign, FloatBase b = Fixed) :
00507             interfaces::FormatFloat<float>(w, p, a, b) {}
00508 
00509         virtual ~Format() {}
00510 };
00518 template <>
00519 class Format<double> : public interfaces::FormatFloat<double>
00520 {
00521     public:
00529         Format(int w = -1, int p = 4, Alignment a = NoAlign, FloatBase b = Fixed) :
00530             interfaces::FormatFloat<double>(w, p, a, b) {
00531             }
00532 
00533         virtual ~Format() {}
00534 };
00535 
00536 }; // namespace ecl
00537 
00538 #endif /*ECL_FORMATTERS_FLOATS_HPP_*/


ecl_formatters
Author(s): Daniel Stonier
autogenerated on Wed Aug 26 2015 11:27:13