00001
00008
00009
00010
00011
00012 #ifndef ECL_FORMATTERS_NUMBER_HPP_
00013 #define ECL_FORMATTERS_NUMBER_HPP_
00014
00015
00016
00017
00018
00019 #include "common.hpp"
00020 #include <ecl/exceptions/standard_exception.hpp>
00021 #include <ecl/converters/char_strings.hpp>
00022
00023
00024
00025
00026
00027 namespace ecl {
00028
00029
00030
00031
00037 enum IntegralBase
00038 {
00039 Bin,
00040 Hex,
00041 Dec,
00042 };
00043
00044 namespace interfaces {
00045
00046
00047
00048
00049
00056 template < typename Number >
00057 class FormatNumber {
00058 public:
00059
00060
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
00074
00080 FormatNumber<Number>& base(ecl::IntegralBase b);
00085 FormatNumber<Number>& width(int w);
00091 FormatNumber<Number>& align(ecl::Alignment a);
00092
00093
00094
00095
00103 FormatNumber<Number>& operator ()(int w, ecl::Alignment a, ecl::IntegralBase b);
00104
00105
00106
00107
00114 FormatNumber<Number>& operator() (Number n);
00115
00116
00117
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
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
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
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
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 };
00181
00182
00183
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
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
00250 ostream << hex_string[((value_ >> i*4) & 0xF)];
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; }
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; }
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
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
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
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 }
00399
00400
00401
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 };
00556
00557 #endif