floats.hpp
Go to the documentation of this file.
1 
8 /*****************************************************************************
9 ** Ifdefs
10 *****************************************************************************/
11 
12 #ifndef ECL_FORMATTERS_FLOATS_HPP_
13 #define ECL_FORMATTERS_FLOATS_HPP_
14 
15 /*****************************************************************************
16 ** Includes
17 *****************************************************************************/
18 
19 #include <cstdio> // snprintf
20 #include <cstring> // strlen
21 #include "common.hpp"
23 
24 #if _MSC_VER
25 #define snprintf _snprintf
26 #endif
27 
28 /*****************************************************************************
29 ** Namespaces
30 *****************************************************************************/
31 
32 namespace ecl {
33 
34 /*****************************************************************************
35 ** Format Tags
36 *****************************************************************************/
42 enum FloatBase
43 {
44  Fixed,
45  Sci,
46 };
47 
48 namespace interfaces {
49 
50 /*****************************************************************************
51 ** FormatFloat
52 *****************************************************************************/
53 
60 template <typename Number>
61 class FormatFloat {
62 public:
63  /******************************************
64  ** C&D's
65  *******************************************/
73  FormatFloat(const int w = -1, const unsigned int p = 4, const ecl::Alignment a = NoAlign, const ecl::FloatBase b = Fixed) :
74  prm_width(w),
75  prm_precision(p),
76  prm_alignment(a),
77  prm_base(b),
78  width_(&prm_width),
82  ready_to_format(false) {}
83 
84  virtual ~FormatFloat() {}
85 
86  /******************************************
87  ** Set Format Parameters
88  *******************************************/
97  FormatFloat<Number>& precision(const unsigned int p) { *precision_ = p; return *this; }
106  FormatFloat<Number>& width(const int w);
115  FormatFloat<Number>& align(const ecl::Alignment a);
124  FormatFloat<Number>& base(const ecl::FloatBase b);
125 
126  /******************************************
127  ** Get Format Parameters
128  *******************************************/
133  int precision() { return *precision_; }
134 
140  int width() { return *width_; }
141 
142  /******************************************
143  * Set Format Combinations
144  ******************************************/
151  FormatFloat<Number>& operator()(unsigned int p, const int w);
160  FormatFloat<Number>& operator()(const unsigned int p, const int w, const ecl::Alignment align, const ecl::FloatBase b);
161 
162  /******************************************
163  ** Format a value
164  *******************************************/
175  FormatFloat<Number>& operator() (const Number n);
176 
177  /******************************************
178  ** Format for streaming
179  *******************************************/
186  FormatFloat<Number>& operator() (const Number n, const unsigned int p, const int w);
195  FormatFloat<Number>& operator() (const Number n, const unsigned int p, const int w, const ecl::Alignment align, const ecl::FloatBase b);
196 
197  /******************************************
198  ** Insert the formatter into a stream
199  *******************************************/
208 template <typename OutputStream, typename N>
209 friend OutputStream& operator << (OutputStream& ostream, FormatFloat<N>& formatter);
210 
211 protected:
212  /******************************************
213  ** Parameters
214  *******************************************/
215  int prm_width,tmp_width;
219  int *width_, *precision_;
222  bool ready_to_format;
223  Number value_;
224 
225  /******************************************
226  ** Padding
227  *******************************************/
228  template <typename OutputStream> void pad(int n, OutputStream &ostream) const;
229  template <typename OutputStream> void prePad(int n, OutputStream &ostream) const;
230  template <typename OutputStream> void postPad(int n, OutputStream &ostream) const;
231 
232  /******************************************
233  ** Formatter Functions
234  *******************************************/
235  template <typename OutputStream> void formatFixed(OutputStream &ostream) const;
236  template <typename OutputStream> void formatSci(OutputStream &ostream) const;
237 };
238 
239 /*****************************************************************************
240 * FormatFloat Implementation [single parameter configuration]
241 *****************************************************************************/
247 template <typename Number>
249 {
250  *base_ = b;
251  return *this;
252 }
257 template <typename Number>
258 FormatFloat<Number>& FormatFloat<Number>::width(const int w)
259 {
260  *width_ = w;
261  if ( ( *width_ > 0 ) && ( *alignment_ == NoAlign ) )
262  {
263  *alignment_ = RightAlign;
264  }
265  return *this;
266 }
267 
273 template <typename Number>
274 FormatFloat<Number>& FormatFloat<Number>::align(const ecl::Alignment a)
275 {
276  *alignment_ = a;
277  if ( *alignment_ == NoAlign )
278  {
279  *width_ = 0;
280  }
281  return *this;
282 }
283 
284 /*****************************************************************************
285 * FormatFloat Implementation [format combination configuration]
286 *****************************************************************************/
287 
288 template <typename Number>
289 FormatFloat<Number>& FormatFloat<Number>::operator () (const unsigned int p, const int w)
290 {
291  width(w);
292  precision(p);
293  return *this;
294 }
295 
296 template <typename Number>
297 FormatFloat<Number>& FormatFloat<Number>::operator () (const unsigned int p, const int w, const ecl::Alignment a, const ecl::FloatBase b)
298 {
299  width(w);
300  precision(p);
301  align(a);
302  base(b);
303  return *this;
304 }
305 
306 /*****************************************************************************
307 * FormatFloat Implementation [value]
308 *****************************************************************************/
309 template <typename Number>
311 {
312  value_ = n;
313  ready_to_format = true;
314  return *this;
315 }
316 /*****************************************************************************
317 * FormatFloat Implementation [temporary formatting]
318 *****************************************************************************/
319 template <typename Number>
320 FormatFloat<Number>& FormatFloat<Number>::operator() (const Number n, unsigned int p, const int w)
321 {
322  width_ = &tmp_width;
323  width(w);
324 
325  precision_ = &tmp_precision;
326  precision(p);
327 
328  alignment_ = &tmp_alignment;
329  align(prm_alignment);
330 
331  base_ = &tmp_base;
332  base(prm_base);
333 
334  value_ = n;
335  ready_to_format = true;
336  return *this;
337 }
338 
339 template <typename Number>
340 FormatFloat<Number>& FormatFloat<Number>::operator() (const Number n, const unsigned int p, const int w, const ecl::Alignment a, const ecl::FloatBase b)
341 {
342  width_ = &tmp_width;
343  width(w);
344 
345  precision_ = &tmp_precision;
346  precision(p);
347 
348  alignment_ = &tmp_alignment;
349  align(a);
350 
351  base_ = &tmp_base;
352  base(b);
353 
354  value_ = n;
355  ready_to_format = true;
356  return *this;
357 }
358 
359 
360 /*****************************************************************************
361 * FormatFloat Implementation [internal formatting]
362 *****************************************************************************/
363 template <typename Number>
364  template <typename OutputStream>
365 void FormatFloat<Number>::formatFixed(OutputStream &ostream) const
366 {
367  static char format_specifier[6] = "%.xff";
368  if ( *precision_ < 10 ) {
369  format_specifier[2] = '0'+*precision_;
370  format_specifier[3] = 'f';
371  format_specifier[4] = '\0';
372  } else if ( *precision_ < 20 ) {
373  format_specifier[2] = '1';
374  format_specifier[3] = '0'+(*precision_ - 10);
375  format_specifier[4] = 'f';
376  } else {
377  format_specifier[2] = '2';
378  format_specifier[3] = '0';
379  format_specifier[4] = 'f';
380  }
381  static const int buffer_size = 30;
382  static char buffer[buffer_size];
383 
384  snprintf(buffer, buffer_size, format_specifier, value_);
385 
386  /******************************************
387  ** Streaming out
388  *******************************************/
389  int length = strlen(buffer);
390  prePad(*width_ - length,ostream);
391  ostream << buffer;
392  postPad(*width_ - length,ostream);
393 }
394 
395 template <typename Number>
396  template <typename OutputStream>
397 void FormatFloat<Number>::formatSci(OutputStream &ostream) const
398 {
399  ostream << "Scientific format is not yet supported." << "\n";
400  ostream.flush();
401 }
402 
403 template <typename Number>
404  template <typename OutputStream>
405 void FormatFloat<Number>::prePad(int n, OutputStream &ostream) const
406 {
407  if ( n <= 0 ) { return; }
408  switch ( *alignment_ )
409  {
410  case ( NoAlign ) : { break; }
411  case ( LeftAlign ) : { break; }
412  case ( RightAlign ) : { pad(n,ostream); break; }
413  case ( CentreAlign ) : { pad(n/2+ n%2,ostream); break; } // Add the remainder
414  default : break;
415  }
416 }
417 
418 template <typename Number>
419  template <typename OutputStream>
420 void FormatFloat<Number>::postPad(int n, OutputStream &ostream) const
421 {
422  if ( n <= 0 ) { return; }
423  switch ( *alignment_ )
424  {
425  case ( NoAlign ) : { break; }
426  case ( LeftAlign ) : { pad(n,ostream); break; }
427  case ( RightAlign ) : { break; }
428  case ( CentreAlign ) : { pad(n/2,ostream); break; } // Do not add the remainder
429  default : break;
430  }
431 }
432 
433 template <typename Number>
434  template <typename OutputStream>
435 void FormatFloat<Number>::pad(int n, OutputStream &ostream) const
436 {
437  for (int i = n; i > 0; --i )
438  {
439  ostream << ' ';
440  }
441 }
442 
443 /*****************************************************************************
444 * FormatFloat Implementation [streaming]
445 *****************************************************************************/
446 template <typename OutputStream, typename N>
447 OutputStream& operator << (OutputStream &ostream, FormatFloat<N>& formatter )
448 {
449  bool ready = formatter.ready_to_format;
450 
451  ecl_assert_throw(ready, StandardException(LOC,UsageError,"The formatter cannot print any data - "
452  "either there is no data available, or you have tried to use the "
453  "formatter more than once in a single streaming operation. "
454  "C++ produces unspecified results when functors are used multiply "
455  "in the same stream sequence, so this is not permitted here.") );
456 
457  if ( ready )
458  {
459  switch(*(formatter.base_) )
460  {
461  case(Fixed) : {
462  formatter.formatFixed(ostream);
463  break;
464  }
465  case(Sci) : {
466  formatter.formatSci(ostream);
467  break;
468  }
469  }
470 
471  // Switch pointers back to prms if not already there.
472  if ( formatter.width_ != &(formatter.prm_width) ) {
473  formatter.width_ = &(formatter.prm_width);
474  formatter.precision_ = &(formatter.prm_precision);
475  formatter.alignment_ = &(formatter.prm_alignment);
476  formatter.base_ = &(formatter.prm_base);
477  }
478  formatter.ready_to_format = false;
479  }
480  return ostream;
481 }
482 
483 } // namespace interfaces
484 
485 /*****************************************************************************
486 * Format Classes
487 *****************************************************************************/
495 template <>
496 class Format<float> : public interfaces::FormatFloat<float>
497 {
498  public:
506  Format(int w = -1, int p = 4, Alignment a = NoAlign, FloatBase b = Fixed) :
507  interfaces::FormatFloat<float>(w, p, a, b) {}
508 
509  virtual ~Format() {}
510 };
518 template <>
519 class Format<double> : public interfaces::FormatFloat<double>
520 {
521  public:
529  Format(int w = -1, int p = 4, Alignment a = NoAlign, FloatBase b = Fixed) :
530  interfaces::FormatFloat<double>(w, p, a, b) {
531  }
532 
533  virtual ~Format() {}
534 };
535 
536 }; // namespace ecl
537 
538 #endif /*ECL_FORMATTERS_FLOATS_HPP_*/
ecl::interfaces::FormatFloat::tmp_base
ecl::FloatBase tmp_base
Definition: floats.hpp:226
ecl::NoAlign
@ NoAlign
No alignment used.
Definition: common.hpp:41
ecl::interfaces::FormatFloat::prm_precision
int prm_precision
Definition: floats.hpp:224
ecl::UsageError
UsageError
ecl::interfaces::FormatFloat::tmp_alignment
ecl::Alignment tmp_alignment
Definition: floats.hpp:225
common.hpp
Common formatting definitions.
ecl::interfaces::FormatFloat::prm_alignment
ecl::Alignment prm_alignment
Definition: floats.hpp:225
ecl::interfaces::FormatFloat::width
int width()
Returns the current precision setting.
Definition: floats.hpp:148
ecl::Fixed
@ Fixed
Fixed formatting for floats (i.e. normal decimal representation).
Definition: floats.hpp:58
ecl::RightAlign
@ RightAlign
Align to the right.
Definition: common.hpp:43
ecl::interfaces::FormatFloat
Formatter for float types.
Definition: floats.hpp:67
ecl::interfaces::FormatFloat::tmp_width
int tmp_width
Definition: floats.hpp:223
ecl::interfaces::FormatFloat::base_
ecl::FloatBase * base_
Definition: floats.hpp:229
ecl::interfaces::FormatFloat::alignment_
ecl::Alignment * alignment_
Definition: floats.hpp:228
ecl::interfaces::FormatFloat::prm_base
ecl::FloatBase prm_base
Definition: floats.hpp:226
ecl::interfaces::FormatFloat::prePad
void prePad(int n, OutputStream &ostream) const
Definition: floats.hpp:411
ecl::interfaces::FormatFloat::operator()
FormatFloat< Number > & operator()(unsigned int p, const int w)
Definition: floats.hpp:295
ecl::CentreAlign
@ CentreAlign
Align in the centre.
Definition: common.hpp:44
ecl::interfaces::FormatFloat::postPad
void postPad(int n, OutputStream &ostream) const
Definition: floats.hpp:426
LOC
#define LOC
ecl::StandardException
ecl::LeftAlign
@ LeftAlign
Align to the left.
Definition: common.hpp:42
ecl::interfaces::FormatFloat::precision
int precision()
Returns the current precision setting.
Definition: floats.hpp:141
ecl_assert_throw
#define ecl_assert_throw(expression, exception)
ecl::FloatBase
FloatBase
Base format tags for the float formatters.
Definition: floats.hpp:48
ecl::interfaces::FormatFloat::precision_
int * precision_
Definition: floats.hpp:227
ecl::interfaces::FormatFloat::align
FormatFloat< Number > & align(const ecl::Alignment a)
Sets the alignment format parameter.
Definition: floats.hpp:280
standard_exception.hpp
ecl::interfaces::FormatFloat::ready_to_format
bool ready_to_format
Definition: floats.hpp:230
ecl::interfaces::FormatFloat::width_
int * width_
Definition: floats.hpp:227
ecl::interfaces::FormatFloat::value_
Number value_
Definition: floats.hpp:231
ecl::interfaces::FormatFloat::base
FormatFloat< Number > & base(const ecl::FloatBase b)
Sets the base notation to use.
Definition: floats.hpp:254
ecl::Alignment
Alignment
Alignment tags for text formatting.
Definition: common.hpp:33
ecl::Sci
@ Sci
Scientific formatting for floats (i.e. exponential representation).
Definition: floats.hpp:59
ecl::interfaces::FormatFloat::tmp_precision
int tmp_precision
Definition: floats.hpp:224
ecl::interfaces::FormatFloat::pad
void pad(int n, OutputStream &ostream) const
Definition: floats.hpp:441
ecl::interfaces::FormatFloat::operator<<
friend OutputStream & operator<<(OutputStream &ostream, FormatFloat< N > &formatter)
Definition: floats.hpp:453
ecl::interfaces::FormatFloat::prm_width
int prm_width
Definition: floats.hpp:223
ecl::interfaces::operator<<
OutputStream & operator<<(OutputStream &ostream, FormatFloat< N > &formatter)
Definition: floats.hpp:453
ecl::interfaces::FormatFloat::~FormatFloat
virtual ~FormatFloat()
Definition: floats.hpp:92
ecl::interfaces::FormatFloat::formatSci
void formatSci(OutputStream &ostream) const
Definition: floats.hpp:403
ecl
Embedded control libraries.
ecl::interfaces::FormatFloat::FormatFloat
FormatFloat(const int w=-1, const unsigned int p=4, const ecl::Alignment a=NoAlign, const ecl::FloatBase b=Fixed)
Definition: floats.hpp:81
ecl::interfaces::FormatFloat::formatFixed
void formatFixed(OutputStream &ostream) const
Definition: floats.hpp:371


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