number.hpp
Go to the documentation of this file.
1 
8 /*****************************************************************************
9 ** Ifdefs
10 *****************************************************************************/
11 
12 #ifndef ECL_FORMATTERS_NUMBER_HPP_
13 #define ECL_FORMATTERS_NUMBER_HPP_
14 
15 /*****************************************************************************
16 ** Includes
17 *****************************************************************************/
18 
19 #include "common.hpp"
22 
23 /*****************************************************************************
24 ** Namespaces
25 *****************************************************************************/
26 
27 namespace ecl {
28 
29 /*****************************************************************************
30 ** Format Tags
31 *****************************************************************************/
37 enum IntegralBase
38 {
39  Bin,
40  Hex,
41  Dec,
42 };
43 
44 namespace interfaces {
45 
46 /*****************************************************************************
47 ** FormatNumber Interface [Integral types]
48 *****************************************************************************/
49 
56 template < typename Number >
57 class FormatNumber {
58  public:
59  /******************************************
60  ** C&D's
61  *******************************************/
69 
70  virtual ~FormatNumber() {}
71 
72  /******************************************
73  ** Set
74  *******************************************/
80  FormatNumber<Number>& base(ecl::IntegralBase b);
85  FormatNumber<Number>& width(int w);
91  FormatNumber<Number>& align(ecl::Alignment a);
92 
93  /******************************************
94  * Set Format Combinations
95  ******************************************/
103  FormatNumber<Number>& operator ()(int w, ecl::Alignment a, ecl::IntegralBase b);
104 
105  /******************************************
106  ** Format a value
107  *******************************************/
114  FormatNumber<Number>& operator() (Number n);
115 
116  /******************************************
117  ** Common format usages
118  *******************************************/
127  FormatNumber<Number>& operator() (Number n, int w, ecl::IntegralBase b);
137  FormatNumber<Number>& operator() (Number n, int w, ecl::Alignment a, ecl::IntegralBase b);
138 
139  /******************************************
140  ** Insert the formatter into a stream
141  *******************************************/
152  template <typename OutputStream, typename N> friend OutputStream& operator << (OutputStream& ostream, FormatNumber<N>& formatter);
153 
154  protected:
155  /******************************************
156  ** Paramaters
157  *******************************************/
158  int prm_width, tmp_width;
161  int *width_;
163  bool ready_to_format;
164  Number value_;
165 
166  /******************************************
167  ** Padding
168  *******************************************/
169  template <typename OutputStream> void pad(int n, OutputStream &ostream) const;
170  template <typename OutputStream> void prePad(int n, OutputStream &ostream) const;
171  template <typename OutputStream> void postPad(int n, OutputStream &ostream) const;
172 
173  /******************************************
174  ** Formatter Functions
175  *******************************************/
176  template <typename OutputStream> void formatBin(OutputStream &ostream) const;
177  template <typename OutputStream> void formatHex(OutputStream &ostream) const;
178  template <typename OutputStream> void formatDec(OutputStream &ostream) const;
179 
180 }; // FormatNumber
181 
182 /*****************************************************************************
183 * FormatNumber Implementation [configuration]
184 *****************************************************************************/
185 template <typename Number>
187 {
188  *base_ = b;
189  return *this;
190 }
191 
192 template <typename Number>
194 {
195  *width_ = w;
196  if ( ( *width_ > 0 ) && ( *alignment_ == NoAlign ) ) {
197  *alignment_ = RightAlign;
198  }
199  return *this;
200 }
201 
202 template <typename Number>
204 {
205  *alignment_ = a;
206  if ( *alignment_ == NoAlign )
207  {
208  *width_ = 0;
209  }
210  return *this;
211 }
212 template <typename Number>
214 {
215  base(b);
216  width(w);
217  align(a);
218  return *this;
219 }
220 
221 /*****************************************************************************
222 * FormatNumber Implementation [internal formatting]
223 *****************************************************************************/
224 template <typename Number>
225  template <typename OutputStream>
226 void FormatNumber<Number>::formatBin(OutputStream &ostream) const
227 {
228  int size = 8*sizeof(Number);
229  prePad(*width_ - (size + 2),ostream);
230  ostream << "0b";
231  for (int i = size - 1; i>=0; i--)
232  {
233  ostream << "01"[((value_ >> i) & 1)];
234  }
235  postPad(*width_ - (size + 2),ostream);
236 }
237 
238 template <typename Number>
239  template <typename OutputStream>
240 void FormatNumber<Number>::formatHex(OutputStream &ostream) const
241 {
242  static const char hex_string[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
243 
244  int size = 2*sizeof(Number);
245  prePad(*width_ - (size + 2),ostream);
246  ostream << "0x";
247  for (int i = size - 1; i>=0; i--)
248  {
249 // ostream << "0123456789abcdef"[((value_ >> i*4) & 0xF)];
250  ostream << hex_string[((value_ >> i*4) & 0xF)]; // Dont have to recreate this every time
251  }
252  postPad(*width_ - (size + 2),ostream);
253 }
254 
255 template <typename Number>
256  template <typename OutputStream>
257 void FormatNumber<Number>::formatDec(OutputStream &ostream) const
258 {
259  static ecl::Converter<char*> convert;
260  char *s = convert(value_);
261  int size = strlen(s);
262  prePad(*width_ - size,ostream);
263  ostream << s;
264  postPad(*width_ - size,ostream);
265 }
266 
267 template <typename Number>
268  template <typename OutputStream>
269 void FormatNumber<Number>::prePad(int n, OutputStream &ostream) const
270 {
271  if ( n <= 0 ) { return; }
272  switch ( *alignment_ )
273  {
274  case ( NoAlign ) : { break; }
275  case ( LeftAlign ) : { break; }
276  case ( RightAlign ) : { pad(n,ostream); break; }
277  case ( CentreAlign ) : { pad(n/2+ n%2,ostream); break; } // Add the remainder
278  default : break;
279  }
280 }
281 
282 template <typename Number>
283  template <typename OutputStream>
284 void FormatNumber<Number>::postPad(int n, OutputStream &ostream) const
285 {
286  if ( n <= 0 ) { return; }
287  switch ( *alignment_ )
288  {
289  case ( NoAlign ) : { break; }
290  case ( LeftAlign ) : { pad(n,ostream); break; }
291  case ( RightAlign ) : { break; }
292  case ( CentreAlign ) : { pad(n/2,ostream); break; } // Do not add the remainder
293  default : break;
294  }
295 }
296 
297 template <typename Number>
298  template <typename OutputStream>
299 void FormatNumber<Number>::pad(int n, OutputStream &ostream) const
300 {
301  for (int i = n; i > 0; --i )
302  {
303  ostream << ' ';
304  }
305 }
306 /*****************************************************************************
307 * FormatNumber Implementation [value]
308 *****************************************************************************/
312 template <typename Number>
314 {
315  value_ = n;
316  ready_to_format = true;
317  return *this;
318 }
319 
320 /*****************************************************************************
321 * FormatNumber Implementation [temporary formatting]
322 *****************************************************************************/
323 
327 template <typename Number>
329 {
330  width_ = &tmp_width;
331  alignment_ = &tmp_alignment;
332  base_ = &tmp_base;
333  base(b);
334  width(w);
335  value_ = n;
336  ready_to_format = true;
337  return *this;
338 }
342 template <typename Number>
344 {
345  width_ = &tmp_width;
346  alignment_ = &tmp_alignment;
347  base_ = &tmp_base;
348  base(b);
349  width(w);
350  align(a);
351  value_ = n;
352  ready_to_format = true;
353  return *this;
354 }
355 
356 
357 /*****************************************************************************
358 * FormatNumber Implementation [streaming]
359 *****************************************************************************/
360 template <typename OutputStream, typename N>
361 OutputStream& operator << (OutputStream &ostream, FormatNumber<N>& formatter )
362 {
363  bool ready = formatter.ready_to_format;
364 
365  ecl_assert_throw(ready, StandardException(LOC,UsageError,"The formatter cannot print any data - "
366  "either there is no data available, or you have tried to use the "
367  "formatter more than once in a single streaming operation. "
368  "C++ produces unspecified results when functors are used multiply "
369  "in the same stream sequence, so this is not permitted here.") );
370 
371  if ( ready )
372  {
373  switch(*(formatter.base_) )
374  {
375  case(Bin) : {
376  formatter.formatBin(ostream);
377  break;
378  }
379  case(Hex) : {
380  formatter.formatHex(ostream);
381  break;
382  }
383  case(Dec) : {
384  formatter.formatDec(ostream);
385  break;
386  }
387  }
388  if ( formatter.width_ != &(formatter.prm_width) ) {
389  formatter.width_ = &(formatter.prm_width);
390  formatter.alignment_ = &(formatter.prm_alignment);
391  formatter.base_ = &(formatter.prm_base);
392  }
393  formatter.ready_to_format = false;
394  }
395  return ostream;
396 }
397 
398 } // namespace interfaces
399 
400 /*****************************************************************************
401 * Format Classes
402 *****************************************************************************/
407 template <>
408 class Format<short> : public interfaces::FormatNumber<short>
409 {
410  public:
417  Format(int w = -1, Alignment a = NoAlign, IntegralBase b = Dec) : interfaces::FormatNumber<short>(w, a, b) {}
418  virtual ~Format() {}
419 };
424 template <>
425 class Format<int> : public interfaces::FormatNumber<int>
426 {
427  public:
434  Format(int w = -1, Alignment a = NoAlign, IntegralBase b = Dec) : interfaces::FormatNumber<int>(w, a, b) {}
435  virtual ~Format() {}
436 };
441 template <>
442 class Format<long> : public interfaces::FormatNumber<long>
443 {
444  public:
451  Format(int w = -1, Alignment a = NoAlign, IntegralBase b = Dec) : interfaces::FormatNumber<long>(w, a, b) {}
452  virtual ~Format() {}
453 };
454 
459 template <>
460 class Format<char> : public interfaces::FormatNumber<char>
461 {
462  public:
469  Format(int w = -1, Alignment a = NoAlign, IntegralBase b = Dec) : interfaces::FormatNumber<char>(w, a, b) {}
470  virtual ~Format() {}
471 };
472 
477 template <>
478 class Format<signed char> : public interfaces::FormatNumber<signed char>
479 {
480  public:
487  Format(int w = -1, Alignment a = NoAlign, IntegralBase b = Dec) : interfaces::FormatNumber<signed char>(w, a, b) {}
488  virtual ~Format() {}
489 };
490 
495 template <>
496 class Format<unsigned short> : public interfaces::FormatNumber<unsigned short>
497 {
498  public:
505  Format(int w = -1, Alignment a = NoAlign, IntegralBase b = Dec) : interfaces::FormatNumber<unsigned short>(w, a, b) {}
506  virtual ~Format() {}
507 };
508 
513 template <>
514 class Format<unsigned int> : public interfaces::FormatNumber<unsigned int>
515 {
516  public:
523  Format(int w = -1, Alignment a = NoAlign, IntegralBase b = Dec) : interfaces::FormatNumber<unsigned int>(w, a, b) {}
524  virtual ~Format() {}
525 };
530 template <>
531 class Format<unsigned long> : public interfaces::FormatNumber<unsigned long>
532 {
533  public:
541  virtual ~Format() {}
542 };
547 template <>
548 class Format<unsigned char> : public interfaces::FormatNumber<unsigned char>
549 {
550  public:
552  virtual ~Format() {}
553 };
554 
555 }; // namespace ecl
556 
557 #endif /*ECL_FORMATTERS_NUMBER_HPP_*/
ecl::Hex
@ Hex
Hex representation for integral types.
Definition: number.hpp:54
ecl::interfaces::FormatNumber::tmp_base
ecl::IntegralBase tmp_base
Definition: number.hpp:168
ecl::interfaces::FormatNumber::pad
void pad(int n, OutputStream &ostream) const
Definition: number.hpp:305
ecl::NoAlign
@ NoAlign
No alignment used.
Definition: common.hpp:41
ecl::UsageError
UsageError
ecl::interfaces::FormatNumber::alignment_
ecl::Alignment * alignment_
Definition: number.hpp:170
ecl::interfaces::FormatNumber::width_
int * width_
Definition: number.hpp:169
ecl::interfaces::FormatNumber::ready_to_format
bool ready_to_format
Definition: number.hpp:171
common.hpp
Common formatting definitions.
ecl::interfaces::FormatNumber::base_
IntegralBase * base_
Definition: number.hpp:170
ecl::interfaces::FormatNumber::prePad
void prePad(int n, OutputStream &ostream) const
Definition: number.hpp:275
ecl::RightAlign
@ RightAlign
Align to the right.
Definition: common.hpp:43
ecl::interfaces::FormatNumber::formatBin
void formatBin(OutputStream &ostream) const
Definition: number.hpp:232
char_strings.hpp
ecl::IntegralBase
IntegralBase
Base format tags for the integral formatters.
Definition: number.hpp:43
ecl::interfaces::FormatNumber::FormatNumber
FormatNumber(int w=-1, ecl::Alignment a=NoAlign, ecl::IntegralBase b=Dec)
Definition: number.hpp:76
ecl::interfaces::FormatNumber::~FormatNumber
virtual ~FormatNumber()
Definition: number.hpp:78
ecl::interfaces::FormatNumber::prm_width
int prm_width
Definition: number.hpp:166
ecl::interfaces::FormatNumber::width
FormatNumber< Number > & width(int w)
Definition: number.hpp:199
ecl::CentreAlign
@ CentreAlign
Align in the centre.
Definition: common.hpp:44
ecl::Dec
@ Dec
Decimal (i.e. normal) representation for integral types.
Definition: number.hpp:55
ecl::Bin
@ Bin
Binary representation for integral types.
Definition: number.hpp:53
ecl::interfaces::FormatNumber::value_
Number value_
Definition: number.hpp:172
ecl::StandardException
ecl::interfaces::FormatNumber::formatDec
void formatDec(OutputStream &ostream) const
Definition: number.hpp:263
ecl::interfaces::FormatNumber::postPad
void postPad(int n, OutputStream &ostream) const
Definition: number.hpp:290
ecl::LeftAlign
@ LeftAlign
Align to the left.
Definition: common.hpp:42
ecl::Format
Primary template for all formatter classes.
Definition: common.hpp:103
ecl_assert_throw
#define ecl_assert_throw(expression, exception)
ecl::interfaces::FormatNumber::base
FormatNumber< Number > & base(ecl::IntegralBase b)
Definition: number.hpp:192
standard_exception.hpp
ecl::interfaces::FormatNumber
Formatter for integral types.
Definition: number.hpp:63
ecl::interfaces::FormatNumber::operator()
FormatNumber< Number > & operator()(int w, ecl::Alignment a, ecl::IntegralBase b)
Definition: number.hpp:219
ecl::interfaces::FormatNumber::operator<<
friend OutputStream & operator<<(OutputStream &ostream, FormatNumber< N > &formatter)
Definition: number.hpp:367
ecl::Alignment
Alignment
Alignment tags for text formatting.
Definition: common.hpp:33
ecl::interfaces::FormatNumber::align
FormatNumber< Number > & align(ecl::Alignment a)
Definition: number.hpp:209
ecl::interfaces::FormatNumber::prm_alignment
ecl::Alignment prm_alignment
Definition: number.hpp:167
ecl::interfaces::FormatNumber::formatHex
void formatHex(OutputStream &ostream) const
Definition: number.hpp:246
ecl::interfaces::operator<<
OutputStream & operator<<(OutputStream &ostream, FormatFloat< N > &formatter)
Definition: floats.hpp:453
ecl
Embedded control libraries.
ecl::Converter
ecl::interfaces::FormatNumber::tmp_width
int tmp_width
Definition: number.hpp:166
ecl::interfaces::FormatNumber::prm_base
ecl::IntegralBase prm_base
Definition: number.hpp:168
ecl::interfaces::FormatNumber::tmp_alignment
ecl::Alignment tmp_alignment
Definition: number.hpp:167


ecl_formatters
Author(s): Daniel Stonier
autogenerated on Wed Mar 2 2022 00:16:27