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 *****************************************************************************/
43 {
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),
81  base_(&prm_base),
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);
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  *******************************************/
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>
259 {
260  *width_ = w;
261  if ( ( *width_ > 0 ) && ( *alignment_ == NoAlign ) )
262  {
264  }
265  return *this;
266 }
267 
273 template <typename Number>
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 
326  precision(p);
327 
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 
346  precision(p);
347 
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_*/
void prePad(int n, OutputStream &ostream) const
Definition: floats.hpp:405
ecl::FloatBase prm_base
Definition: floats.hpp:218
void formatSci(OutputStream &ostream) const
Definition: floats.hpp:397
Embedded control libraries.
FormatFloat< Number > & base(const ecl::FloatBase b)
Sets the base notation to use.
Definition: floats.hpp:248
Formatter for float types.
Definition: floats.hpp:61
virtual ~Format()
Definition: floats.hpp:509
Align to the left.
Definition: common.hpp:32
#define LOC
void postPad(int n, OutputStream &ostream) const
Definition: floats.hpp:420
ecl::Alignment * alignment_
Definition: floats.hpp:220
FormatFloat(const int w=-1, const unsigned int p=4, const ecl::Alignment a=NoAlign, const ecl::FloatBase b=Fixed)
Definition: floats.hpp:73
Common formatting definitions.
Primary template for all formatter classes.
Definition: common.hpp:99
#define ecl_assert_throw(expression, exception)
Scientific formatting for floats (i.e. exponential representation).
Definition: floats.hpp:45
int width()
Returns the current precision setting.
Definition: floats.hpp:140
ecl::Alignment tmp_alignment
Definition: floats.hpp:217
Format(int w=-1, int p=4, Alignment a=NoAlign, FloatBase b=Fixed)
Definition: floats.hpp:506
FormatFloat< Number > & operator()(unsigned int p, const int w)
Definition: floats.hpp:289
ecl::Alignment prm_alignment
Definition: floats.hpp:217
void pad(int n, OutputStream &ostream) const
Definition: floats.hpp:435
Format(int w=-1, int p=4, Alignment a=NoAlign, FloatBase b=Fixed)
Definition: floats.hpp:529
FormatFloat< Number > & align(const ecl::Alignment a)
Sets the alignment format parameter.
Definition: floats.hpp:274
void formatFixed(OutputStream &ostream) const
Definition: floats.hpp:365
No alignment used.
Definition: common.hpp:31
UsageError
FormatFloat< Number > & precision(const unsigned int p)
Sets the precision format parameter.
Definition: floats.hpp:97
Fixed formatting for floats (i.e. normal decimal representation).
Definition: floats.hpp:44
ecl::FloatBase * base_
Definition: floats.hpp:221
FloatBase
Base format tags for the float formatters.
Definition: floats.hpp:42
Align to the right.
Definition: common.hpp:33
Alignment
Alignment tags for text formatting.
Definition: common.hpp:29
int precision()
Returns the current precision setting.
Definition: floats.hpp:133
ecl::FloatBase tmp_base
Definition: floats.hpp:218
Align in the centre.
Definition: common.hpp:34


ecl_formatters
Author(s): Daniel Stonier
autogenerated on Mon Feb 28 2022 22:18:36