number.hpp
Go to the documentation of this file.
00001 
00008 /*****************************************************************************
00009 ** Ifdefs
00010 *****************************************************************************/
00011 
00012 #ifndef ECL_FORMATTERS_NUMBER_HPP_
00013 #define ECL_FORMATTERS_NUMBER_HPP_
00014 
00015 /*****************************************************************************
00016 ** Includes
00017 *****************************************************************************/
00018 
00019 #include "common.hpp"
00020 #include <ecl/exceptions/standard_exception.hpp>
00021 #include <ecl/converters/char_strings.hpp>
00022 
00023 /*****************************************************************************
00024 ** Namespaces
00025 *****************************************************************************/
00026 
00027 namespace ecl {
00028 
00029 /*****************************************************************************
00030 ** Format Tags
00031 *****************************************************************************/
00037 enum IntegralBase
00038 {
00039     Bin, 
00040     Hex, 
00041     Dec, 
00042 };
00043 
00044 namespace interfaces {
00045 
00046 /*****************************************************************************
00047 ** FormatNumber Interface [Integral types]
00048 *****************************************************************************/
00049 
00056 template < typename Number >
00057 class FormatNumber {
00058     public:
00059         /******************************************
00060         ** C&D's
00061         *******************************************/
00068         FormatNumber(int w = -1, ecl::Alignment a = NoAlign, ecl::IntegralBase b = Dec) : prm_width(w),prm_alignment(a),prm_base(b),width_(&prm_width),alignment_(&prm_alignment),base_(&prm_base),ready_to_format(false) {}
00069 
00070         virtual ~FormatNumber() {}
00071 
00072         /******************************************
00073         ** Set
00074         *******************************************/
00080         FormatNumber<Number>& base(ecl::IntegralBase b);
00085         FormatNumber<Number>& width(int w);
00091         FormatNumber<Number>& align(ecl::Alignment a);
00092 
00093         /******************************************
00094          * Set Format Combinations
00095          ******************************************/
00103         FormatNumber<Number>& operator ()(int w, ecl::Alignment a, ecl::IntegralBase b);
00104 
00105         /******************************************
00106         ** Format a value
00107         *******************************************/
00114         FormatNumber<Number>& operator() (Number n);
00115 
00116         /******************************************
00117         ** Common format usages
00118         *******************************************/
00127         FormatNumber<Number>& operator() (Number n, int w, ecl::IntegralBase b);
00137         FormatNumber<Number>& operator() (Number n, int w, ecl::Alignment a, ecl::IntegralBase b);
00138 
00139         /******************************************
00140         ** Insert the formatter into a stream
00141         *******************************************/
00152         template <typename OutputStream, typename N> friend OutputStream& operator << (OutputStream& ostream, FormatNumber<N>& formatter) ecl_assert_throw_decl(StandardException);
00153 
00154     protected:
00155         /******************************************
00156         ** Paramaters
00157         *******************************************/
00158         int prm_width, tmp_width;
00159         ecl::Alignment prm_alignment, tmp_alignment;
00160         ecl::IntegralBase prm_base, tmp_base;
00161         int *width_;
00162         ecl::Alignment *alignment_; IntegralBase *base_;
00163         bool ready_to_format;
00164         Number value_;
00165 
00166         /******************************************
00167         ** Padding
00168         *******************************************/
00169         template <typename OutputStream> void pad(int n, OutputStream &ostream) const;
00170         template <typename OutputStream> void prePad(int n, OutputStream &ostream) const;
00171         template <typename OutputStream> void postPad(int n, OutputStream &ostream) const;
00172 
00173         /******************************************
00174         ** Formatter Functions
00175         *******************************************/
00176         template <typename OutputStream> void formatBin(OutputStream &ostream) const;
00177         template <typename OutputStream> void formatHex(OutputStream &ostream) const;
00178         template <typename OutputStream> void formatDec(OutputStream &ostream) const;
00179 
00180 }; // FormatNumber
00181 
00182 /*****************************************************************************
00183 * FormatNumber Implementation  [configuration]
00184 *****************************************************************************/
00185 template <typename Number>
00186 FormatNumber<Number>& FormatNumber<Number>::base(ecl::IntegralBase b)
00187 {
00188     *base_ = b;
00189     return *this;
00190 }
00191 
00192 template <typename Number>
00193 FormatNumber<Number>& FormatNumber<Number>::width(int w)
00194 {
00195     *width_ = w;
00196     if ( ( *width_ > 0 ) && ( *alignment_ == NoAlign ) ) {
00197         *alignment_ = RightAlign;
00198     }
00199     return *this;
00200 }
00201 
00202 template <typename Number>
00203 FormatNumber<Number>& FormatNumber<Number>::align(ecl::Alignment a)
00204 {
00205     *alignment_ = a;
00206     if ( *alignment_ == NoAlign )
00207     {
00208         *width_ = 0;
00209     }
00210     return *this;
00211 }
00212 template <typename Number>
00213 FormatNumber<Number>& FormatNumber<Number>::operator () (int w, ecl::Alignment a, ecl::IntegralBase b)
00214 {
00215     base(b);
00216     width(w);
00217     align(a);
00218     return *this;
00219 }
00220 
00221 /*****************************************************************************
00222 * FormatNumber Implementation [internal formatting]
00223 *****************************************************************************/
00224 template <typename Number>
00225   template <typename OutputStream>
00226 void FormatNumber<Number>::formatBin(OutputStream &ostream) const
00227 {
00228     int size = 8*sizeof(Number);
00229     prePad(*width_ - (size + 2),ostream);
00230     ostream << "0b";
00231     for (int i = size - 1; i>=0; i--)
00232     {
00233         ostream << "01"[((value_ >> i) & 1)];
00234     }
00235     postPad(*width_ - (size + 2),ostream);
00236 }
00237 
00238 template <typename Number>
00239   template <typename OutputStream>
00240 void FormatNumber<Number>::formatHex(OutputStream &ostream) const
00241 {
00242     static const char hex_string[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
00243 
00244     int size = 2*sizeof(Number);
00245     prePad(*width_ - (size + 2),ostream);
00246     ostream << "0x";
00247     for (int i = size - 1; i>=0; i--)
00248     {
00249 //        ostream << "0123456789abcdef"[((value_ >> i*4) & 0xF)];
00250         ostream << hex_string[((value_ >> i*4) & 0xF)]; // Dont have to recreate this every time
00251     }
00252     postPad(*width_ - (size + 2),ostream);
00253 }
00254 
00255 template <typename Number>
00256   template <typename OutputStream>
00257 void FormatNumber<Number>::formatDec(OutputStream &ostream) const
00258 {
00259     static ecl::Converter<char*> convert;
00260     char *s = convert(value_);
00261     int size = strlen(s);
00262     prePad(*width_ - size,ostream);
00263     ostream << s;
00264     postPad(*width_ - size,ostream);
00265 }
00266 
00267 template <typename Number>
00268   template <typename OutputStream>
00269 void FormatNumber<Number>::prePad(int n, OutputStream &ostream) const
00270 {
00271     if ( n <= 0 ) { return; }
00272     switch ( *alignment_ )
00273     {
00274         case ( NoAlign ) : { break; }
00275         case ( LeftAlign ) : { break; }
00276         case ( RightAlign ) : { pad(n,ostream); break; }
00277         case ( CentreAlign ) : { pad(n/2+ n%2,ostream); break; } // Add the remainder
00278         default : break;
00279     }
00280 }
00281 
00282 template <typename Number>
00283   template <typename OutputStream>
00284 void FormatNumber<Number>::postPad(int n, OutputStream &ostream) const
00285 {
00286     if ( n <= 0 ) { return; }
00287     switch ( *alignment_ )
00288     {
00289         case ( NoAlign ) : { break; }
00290         case ( LeftAlign ) : { pad(n,ostream); break; }
00291         case ( RightAlign ) : { break; }
00292         case ( CentreAlign ) : { pad(n/2,ostream); break; }  // Do not add the remainder
00293         default : break;
00294     }
00295 }
00296 
00297 template <typename Number>
00298   template <typename OutputStream>
00299 void FormatNumber<Number>::pad(int n, OutputStream &ostream) const
00300 {
00301     for (int i = n; i > 0; --i )
00302     {
00303         ostream << ' ';
00304     }
00305 }
00306 /*****************************************************************************
00307 * FormatNumber Implementation [value]
00308 *****************************************************************************/
00312 template <typename Number>
00313 FormatNumber<Number>& FormatNumber<Number>::operator()(Number n)
00314 {
00315     value_ = n;
00316     ready_to_format = true;
00317     return *this;
00318 }
00319 
00320 /*****************************************************************************
00321 * FormatNumber Implementation [temporary formatting]
00322 *****************************************************************************/
00323 
00327 template <typename Number>
00328 FormatNumber<Number>& FormatNumber<Number>::operator() (Number n, int w, ecl::IntegralBase b)
00329 {
00330     width_ = &tmp_width;
00331     alignment_ = &tmp_alignment;
00332     base_ = &tmp_base;
00333     base(b);
00334     width(w);
00335     value_ = n;
00336     ready_to_format = true;
00337     return *this;
00338 }
00342 template <typename Number>
00343 FormatNumber<Number>& FormatNumber<Number>::operator() (Number n, int w, ecl::Alignment a, ecl::IntegralBase b)
00344 {
00345     width_ = &tmp_width;
00346     alignment_ = &tmp_alignment;
00347     base_ = &tmp_base;
00348     base(b);
00349     width(w);
00350     align(a);
00351     value_ = n;
00352     ready_to_format = true;
00353     return *this;
00354 }
00355 
00356 
00357 /*****************************************************************************
00358 * FormatNumber Implementation [streaming]
00359 *****************************************************************************/
00360 template <typename OutputStream, typename N>
00361 OutputStream& operator << (OutputStream &ostream, FormatNumber<N>& formatter ) ecl_assert_throw_decl(StandardException)
00362 {
00363     bool ready = formatter.ready_to_format;
00364 
00365     ecl_assert_throw(ready, StandardException(LOC,UsageError,"The formatter cannot print any data - "
00366             "either there is no data available, or you have tried to use the "
00367             "formatter more than once in a single streaming operation. "
00368             "C++ produces unspecified results when functors are used multiply "
00369             "in the same stream sequence, so this is not permitted here.") );
00370 
00371     if ( ready )
00372     {
00373         switch(*(formatter.base_) )
00374         {
00375             case(Bin) : {
00376                 formatter.formatBin(ostream);
00377                 break;
00378             }
00379             case(Hex) : {
00380                 formatter.formatHex(ostream);
00381                 break;
00382             }
00383             case(Dec) : {
00384                 formatter.formatDec(ostream);
00385                 break;
00386             }
00387         }
00388         if ( formatter.width_ != &(formatter.prm_width) ) {
00389             formatter.width_ = &(formatter.prm_width);
00390             formatter.alignment_ = &(formatter.prm_alignment);
00391             formatter.base_ = &(formatter.prm_base);
00392         }
00393         formatter.ready_to_format = false;
00394     }
00395     return ostream;
00396 }
00397 
00398 } // namespace interfaces
00399 
00400 /*****************************************************************************
00401 * Format Classes
00402 *****************************************************************************/
00407 template <>
00408 class Format<short> : public interfaces::FormatNumber<short>
00409 {
00410     public:
00417         Format(int w = -1, Alignment a = NoAlign, IntegralBase b = Dec) : interfaces::FormatNumber<short>(w, a, b) {}
00418                 virtual ~Format() {}
00419 };
00424 template <>
00425 class Format<int> : public interfaces::FormatNumber<int>
00426 {
00427     public:
00434         Format(int w = -1, Alignment a = NoAlign, IntegralBase b = Dec) : interfaces::FormatNumber<int>(w, a, b) {}
00435                 virtual ~Format() {}
00436 };
00441 template <>
00442 class Format<long> : public interfaces::FormatNumber<long>
00443 {
00444     public:
00451         Format(int w = -1, Alignment a = NoAlign, IntegralBase b = Dec) : interfaces::FormatNumber<long>(w, a, b) {}
00452                 virtual ~Format() {}
00453 };
00454 
00459 template <>
00460 class Format<char> : public interfaces::FormatNumber<char>
00461 {
00462     public:
00469         Format(int w = -1, Alignment a = NoAlign, IntegralBase b = Dec) : interfaces::FormatNumber<char>(w, a, b) {}
00470                 virtual ~Format() {}
00471 };
00472 
00477 template <>
00478 class Format<signed char> : public interfaces::FormatNumber<signed char>
00479 {
00480     public:
00487         Format(int w = -1, Alignment a = NoAlign, IntegralBase b = Dec) : interfaces::FormatNumber<signed char>(w, a, b) {}
00488                 virtual ~Format() {}
00489 };
00490 
00495 template <>
00496 class Format<unsigned short> : public interfaces::FormatNumber<unsigned short>
00497 {
00498     public:
00505         Format(int w = -1, Alignment a = NoAlign, IntegralBase b = Dec) : interfaces::FormatNumber<unsigned short>(w, a, b) {}
00506                 virtual ~Format() {}
00507 };
00508 
00513 template <>
00514 class Format<unsigned int> : public interfaces::FormatNumber<unsigned int>
00515 {
00516     public:
00523         Format(int w = -1, Alignment a = NoAlign, IntegralBase b = Dec) : interfaces::FormatNumber<unsigned int>(w, a, b) {}
00524                 virtual ~Format() {}
00525 };
00530 template <>
00531 class Format<unsigned long> : public interfaces::FormatNumber<unsigned long>
00532 {
00533     public:
00540         Format(int w = -1, Alignment a = NoAlign, IntegralBase b = Dec) : interfaces::FormatNumber<unsigned long>(w, a, b) {}
00541                 virtual ~Format() {}
00542 };
00547 template <>
00548 class Format<unsigned char> : public interfaces::FormatNumber<unsigned char>
00549 {
00550     public:
00551         Format(int w = -1, Alignment a = NoAlign, IntegralBase b = Dec) : interfaces::FormatNumber<unsigned char>(w, a, b) {} 
00552                 virtual ~Format() {}
00553 };
00554 
00555 }; // namespace ecl
00556 
00557 #endif /*ECL_FORMATTERS_NUMBER_HPP_*/


ecl_formatters
Author(s): Daniel Stonier (d.stonier@gmail.com)
autogenerated on Thu Jan 2 2014 11:12:10