FloatT.h
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 // (c) 2006 by Basler Vision Technologies
3 // Section: Vision Components
4 // Project: GenApi
5 // Author: Alexander Happe
6 // $Header$
7 //
8 // License: This file is published under the license of the EMVA GenICam Standard Group.
9 // A text file describing the legal terms is included in your installation as 'GenICam_license.pdf'.
10 // If for some reason you are missing this file please contact the EMVA or visit the website
11 // (http://www.genicam.org) for a full copy.
12 //
13 // THIS SOFTWARE IS PROVIDED BY THE EMVA GENICAM STANDARD GROUP "AS IS"
14 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE EMVA GENICAM STANDARD GROUP
17 // OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
23 // POSSIBILITY OF SUCH DAMAGE.
24 //-----------------------------------------------------------------------------
31 #ifndef GENAPI_FLOATT_H
32 #define GENAPI_FLOATT_H
33 
34 
35 #include "../NodeCallback.h"
36 #include "INodePrivate.h"
37 #include "../Synch.h"
38 #include "../Counter.h"
39 #include "Value2String.h"
40 #include "GenApi/impl/Log.h"
41 #include <limits>
42 #include <cmath>
43 #include <cstdlib>
44 #include <algorithm>
45 #include "Exception.h"
46 #include "AutovectorImpl.h"
47 
48 #ifdef _MSC_VER
49 # pragma warning( disable : 4706 ) // assignment within conditional expression
50 #endif
51 
52 namespace GENAPI_NAMESPACE
53 {
57  template<class Base>
58  class FloatT : public Base
59  {
60  public:
61 
64  Base(),
65  m_ImposedMax( (std::numeric_limits<double>::max)() ),
66  m_ImposedMin( -(std::numeric_limits<double>::max)() )
67  {
68  }
69 
71  virtual void SetValue(double Value, bool Verify = true)
72  {
73 
74  // a list of callbacks to fire held outside(!) the autolock on the stack(!)
75  std::list<CNodeCallback*> CallbacksToFire;
76  {
78  typename Base::EntryMethodFinalizer E( this, meSetValue );
79 
80  GCLOGINFOPUSH( Base::m_pValueLog, "SetValue( %f )...", Value );
81 
82  if( Verify )
83  {
84  if( !IsWritable( this ) )
85  throw ACCESS_EXCEPTION_NODE("Node is not writable.");
86 
87  CHECK_RANGE_FLT_NODE(Value, Base::InternalGetMin(), Base::InternalGetMax());
88  }
89 
90  {
91  typename Base::PostSetValueFinalizer PostSetValueCaller(this, CallbacksToFire); // dtor calls Base::PostSetValue
92 
93  // invalidates all nodes if this is the first call in a chain of SetValue calls
94  Base::PreSetValue();
95 
96  // sets the value
97  Base::InternalSetValue(Value, Verify);
98 
99  if( Verify )
100  Base::InternalCheckError();
101 
102  #if ! defined( DISABLE_VALUE_CACHING ) || (DISABLE_VALUE_CACHING == 0)
103  // Fill cache
104  if( WriteThrough == static_cast<INode *>(this)->GetCachingMode() )
105  {
106  m_ValueCache = Value;
107  Base::m_ValueCacheValid = true;
108  Base::m_DontDeleteThisCache = true;
109  }
110  #endif
111 
112  }
113 
114  GCLOGINFOPOP( Base::m_pValueLog, "...SetValue" );
115 
116  // fire callbacks inside the lock
117  std::list<CNodeCallback*>::iterator ptrCallback;
118  for( ptrCallback = CallbacksToFire.begin(); ptrCallback != CallbacksToFire.end(); ptrCallback++ )
119  {
120  (*ptrCallback)->operator ()(cbPostInsideLock);
121  }
122  }
123 
124  // fire callbacks outside the lock
125  std::list<CNodeCallback*>::iterator ptrCallback;
126  for( ptrCallback = CallbacksToFire.begin(); ptrCallback != CallbacksToFire.end(); ptrCallback++ )
127  {
128  (*ptrCallback)->operator ()(cbPostOutsideLock);
129  }
130  }
131 
133  virtual IFloat& operator=(double Value)
134  {
135  SetValue(Value);
136 
137  return *this;
138  }
139 
140  /* This is a helper function used in the method ToString (see below)
141  It parses a floating point number given in a buffer s and creates a correction value used for correct rounding
142 
143  If the number in s is given in fixed point notation like
144  123.4567
145  the correction is
146  0.00005
147  that is it has zeros for all trailing digits of the number followed by a '5'
148 
149  In case of scientific notation like
150  1.1234e-12
151  the correction number is
152  0.00005e-12
153  that is it has zeros for all trailing digits of the number followed by a '5' plus it has
154  the same exponent as the original number.
155 
156  The use of the correction number is explained below in the method ToString
157 
158  The code is inspired from from http://www.hackchina.com/en/r/185703/ATOF.C__html
159  */
160  double Correction( const char *s )
161  {
162  // note that while parsing the parsed value is composed even if that is not necessary
163  // nevertheless the code is left as is for clarification and verification purposes
164  bool sign;
165  char c;
166 
167  // eat white space
168  while( isspace(c = *s) )
169  s++;
170 
171  // handle sign
172  if ((sign = (c == '-')))
173  s++;
174  else if (c == '+')
175  s++;
176 
177  // read digits before decimal point
178  double v = 0.0;
179  while( isdigit(*s) )
180  v = 10.0 * v + (*s++ - '0');
181 
182  double Cor = 0.5;
183  if( *s == '.' )
184  {
185  s++;
186 
187  // eat digits after decimal point
188  double fr = 10.0;
189  while( isdigit(*s) )
190  {
191  v += (*s++ - '0') / fr;
192  Cor *= 0.1;
193  fr *= 10.0;
194  }
195  }
196 
197  // handle exponent
198  double exp = 1.0;
199  if (tolower(*s) == 'e')
200  {
201  int i = atoi(s);
202  exp = pow(10.0, i);
203  }
204 
205  //v *= exp;
206  //v = sign ? -v : v;
207 
208  Cor *= exp;
209 
210  return Cor;
211  }
212 
214  virtual GENICAM_NAMESPACE::gcstring InternalToString(bool Verify = false, bool IgnoreCache = false)
215  {
216  AutoLock l(Base::GetLock());
217 
218  std::stringstream Buffer;
219  std::ostringstream CorrectedBuffer;
220 
221  // set DisplayNotation
222  switch( Base::InternalGetDisplayNotation() )
223  {
224  case fnAutomatic:
225  // default
226  break;
227  case fnFixed:
228  Buffer.setf(std::ios::fixed, std::ios::floatfield);
229  CorrectedBuffer.setf(std::ios::fixed, std::ios::floatfield);
230  break;
231  case fnScientific:
232  Buffer.setf(std::ios::scientific, std::ios::floatfield);
233  CorrectedBuffer.setf(std::ios::scientific, std::ios::floatfield);
234  break;
235  #pragma BullseyeCoverage off
236  default:
237  assert(false);
238  #pragma BullseyeCoverage on
239  }
240 
241  // set DisplayPrecision
242  int Precision = (int)GetDisplayPrecision();
243  Buffer.precision( Precision );
244  CorrectedBuffer.precision( Precision );
245 
246  // output
247  double Value = GetValue( Verify, IgnoreCache );
248  Buffer << Value;
249 
250  // Make sure FromString will work with the result
251  // for details see the test code in FloatTestSuite::TestTicket785
252 
253  // read back the created string
254  double VerifyValue;
255  Buffer >> VerifyValue;
256 
257  double CorrectedValue = Value;
258  bool LimitsExceeded = false;
259 
260  // the string may be too large due to rounding issues
261  if( VerifyValue > Base::InternalGetMax() )
262  {
263  CorrectedValue = Value - Correction( Buffer.str().c_str() );
264  LimitsExceeded = true;
265  }
266  else if( VerifyValue < Base::InternalGetMin() )
267  {
268  CorrectedValue = Value + Correction( Buffer.str().c_str() );
269  LimitsExceeded = true;
270  }
271 
272  GENICAM_NAMESPACE::gcstring valueString;
273  if( LimitsExceeded )
274  {
275  CorrectedBuffer << CorrectedValue;
276  valueString = CorrectedBuffer.str().c_str();
277  }
278  else
279  {
280  valueString = Buffer.str().c_str();
281  }
282  return valueString;
283  }
284 
286  virtual double GetValue(bool Verify = false, bool IgnoreCache = false)
287  {
288  AutoLock l(Base::GetLock());
289  typename Base::EntryMethodFinalizer E( this, meGetValue, IgnoreCache );
290 
291  // Note that readability is tested regardless of Verify
292  if( !IsReadable( this ) )
293  throw ACCESS_EXCEPTION_NODE("Node is not readable.");
294 
295  #if ! defined( DISABLE_VALUE_CACHING ) || (DISABLE_VALUE_CACHING == 0)
296  // Use cache
297  if (!IgnoreCache && Base::m_ValueCacheValid && !Verify)
298  {
299  GCLOGINFO( Base::m_pValueLog, "GetValue = %f (from cache)", m_ValueCache );
300 
301  return m_ValueCache;
302  }
303  #endif
304 
305  GCLOGINFOPUSH( Base::m_pValueLog, "GetValue...");
306 
307  const double Value( Base::InternalGetValue(Verify, IgnoreCache) );
308 
309  GCLOGINFOPOP( Base::m_pValueLog, "...GetValue = %f", Value );
310 
311  if( Verify )
312  {
313  CHECK_RANGE_FLT_NODE(Value, Base::InternalGetMin(), Base::InternalGetMax());
314  Base::InternalCheckError();
315  }
316 
317  #if ! defined( DISABLE_VALUE_CACHING ) || (DISABLE_VALUE_CACHING == 0)
318  // Fill cache
319  const ECachingMode CachingMode(static_cast<INode *>(this)->GetCachingMode());
320  if( WriteThrough == CachingMode
321  || WriteAround == CachingMode )
322  {
323  m_ValueCache = Value;
324  Base::m_ValueCacheValid = true;
325  }
326  #endif
327 
328  return Value;
329 
330  }
331 
333  virtual double operator()()
334  {
335  return GetValue();
336  }
337 
339  virtual double operator*()
340  {
341  return GetValue();
342  }
343 
345  virtual void InternalFromString(const GENICAM_NAMESPACE::gcstring& ValueStr, bool Verify = true)
346  {
347  double value;
348  if (!String2Value(ValueStr,&value))
349  throw INVALID_ARGUMENT_EXCEPTION_NODE("Node '%s' : cannot convert string '%s' to double.", Base::m_Name.c_str(), ValueStr.c_str() );
350 
351  SetValue(value, Verify);
352  }
353 
354 
356  virtual double GetMin()
357  {
358  AutoLock l(Base::GetLock());
359  typename Base::EntryMethodFinalizer E( this, meGetMin );
360 
361  // only allowed for available nodes
362  if (!IsAvailable(this))
363  throw ACCESS_EXCEPTION_NODE("Node is not available.");
364 
365  GCLOGINFOPUSH( Base::m_pRangeLog, "GetMin..." );
366 
367  double Minimum = Base::InternalGetMin();
368  Minimum = (std::max)(Minimum, m_ImposedMin);
369 
370  GCLOGINFOPOP( Base::m_pRangeLog, "...GetMin = %f", Minimum );
371 
372  return Minimum;
373 
374  }
375 
377  virtual double GetMax()
378  {
379  AutoLock l(Base::GetLock());
380  typename Base::EntryMethodFinalizer E( this, meGetMax );
381 
382  // only allowed for available nodes
383  if (!IsAvailable(this))
384  throw ACCESS_EXCEPTION_NODE("Node is not available.");
385 
386  GCLOGINFOPUSH( Base::m_pRangeLog, "GetMax...");
387 
388  double Maximum(Base::InternalGetMax());
389  Maximum = (std::min)( Maximum, m_ImposedMax );
390 
391  GCLOGINFOPOP( Base::m_pRangeLog, "...GetMax = %f", Maximum );
392 
393  return Maximum;
394 
395  }
396 
398  virtual bool HasInc()
399  {
400  AutoLock l(Base::GetLock());
401 
402  GCLOGINFOPUSH( Base::m_pRangeLog, "HasInc...");
403 
404  bool HasInc( Base::InternalHasInc() );
405 #pragma BullseyeCoverage off
406  GCLOGINFOPOP( Base::m_pRangeLog, "...HasInc = " + (HasInc ? GENICAM_NAMESPACE::gcstring("true") : GENICAM_NAMESPACE::gcstring("false")));
407 #pragma BullseyeCoverage on
408 
409  return HasInc;
410 
411  }
412 
414  {
415  AutoLock l(Base::GetLock());
416  typename Base::EntryMethodFinalizer E( this, meGetIncMode );
417 
418  GCLOGINFOPUSH( Base::m_pRangeLog, "GetIncMode...");
419 
420  if( ! Base::m_ListOfValidValuesCacheValid )
421  {
422  m_CurentValidValueSet = Base::InternalGetListOfValidValues();
423  Base::m_ListOfValidValuesCacheValid = true;
424  }
425 
426  EIncMode incMode( (m_CurentValidValueSet.size())? listIncrement: Base::InternalHasInc()? fixedIncrement : noIncrement );
427 
428  GCLOGINFOPOP( Base::m_pRangeLog, "...GetIncMode" );
429 
430  return incMode;
431  }
432 
434  virtual double GetInc()
435  {
436  AutoLock l(Base::GetLock());
437  typename Base::EntryMethodFinalizer E( this, meGetInc );
438 
439  if( !Base::InternalHasInc() )
440  throw RUNTIME_EXCEPTION_NODE("node does not have an increment." );
441 
442  // only allowed for available nodes
443  if (!IsAvailable(this))
444  throw ACCESS_EXCEPTION_NODE("Node is not available.");
445 
446  GCLOGINFOPUSH( Base::m_pRangeLog, "GetInc...");
447 
448  double Inc( Base::InternalGetInc() );
449 
450  GCLOGINFOPOP( Base::m_pRangeLog, "...GetInc = %f", Inc );
451 
452  return Inc;
453  }
454 
456  virtual double_autovector_t GetListOfValidValues(bool bounded = true)
457  {
458  AutoLock l(Base::GetLock());
459  typename Base::EntryMethodFinalizer E( this, meGetListOfValidValues );
460 
461  GCLOGINFOPUSH( Base::m_pRangeLog, "GetListOfValidValues...");
462  if( ! Base::m_ListOfValidValuesCacheValid )
463  {
464  m_CurentValidValueSet = Base::InternalGetListOfValidValues();
465  Base::m_ListOfValidValuesCacheValid = true;
466  }
467 
468  double_autovector_t list( ( bounded)? m_CurentValidValueSet.duplicate( Base::InternalGetMin(), Base::InternalGetMax()) : m_CurentValidValueSet);
469 
470 
471  GCLOGINFOPOP( Base::m_pRangeLog, "...GetListOfValidValues" );
472  return list;
473 
474 
475  }
476 
477 
480  {
481  AutoLock l(Base::GetLock());
482  return Base::InternalGetRepresentation();
483  }
484 
487  {
488  AutoLock l(Base::GetLock());
489  return Base::InternalGetUnit();
490  }
491 
494  {
495  AutoLock l(Base::GetLock());
496  return Base::InternalGetDisplayNotation();
497  }
498 
500  virtual int64_t GetDisplayPrecision() const
501  {
502  AutoLock l(Base::GetLock());
503 
504  int64_t Precision = Base::InternalGetDisplayPrecision();
505 
506  if( Precision == -1 )
507  {
508  // determine built in precision
509  std::stringstream Buffer;
510  switch( Base::InternalGetDisplayNotation() )
511  {
512  case fnFixed:
513  Buffer.setf(std::ios::fixed, std::ios::floatfield);
514  break;
515  case fnScientific:
516  Buffer.setf(std::ios::scientific, std::ios::floatfield);
517  break;
518  case fnAutomatic:
519  // default
520  break;
521  #pragma BullseyeCoverage off
522  default:
523  assert(false);
524  #pragma BullseyeCoverage on
525  }
526 
527  Precision = Buffer.precision();
528  }
529 
530  return Precision;
531  }
532 
534  virtual void ImposeMin(double Value)
535  {
536  m_ImposedMin = Value;
538  }
539 
541  virtual void ImposeMax(double Value)
542  {
543  m_ImposedMax = Value;
545  }
546 
547  protected:
549  double m_ValueCache;
550 
552  double m_ImposedMax;
553 
555  double m_ImposedMin;
556 
559  };
560 }
561 
562 #endif // GENAPI_FLOATT_H
Definition of value2string and string2value functions.
virtual void InternalFromString(const GENICAM_NAMESPACE::gcstring &ValueStr, bool Verify=true)
Set value of the node as string.
Definition: FloatT.h:345
virtual void SetValue(double Value, bool Verify=true)
Implementation of IFloat::SetValue()
Definition: FloatT.h:71
virtual double GetMax()
Implementation of IFloat::GetMax()
Definition: FloatT.h:377
const _autovector_impl duplicate(T min, T max)
#define RUNTIME_EXCEPTION_NODE
Fires a runtime exception, e.g. throw RUNTIME_EXCEPTION("buh!")
Definition: Exception.h:166
virtual int64_t GetDisplayPrecision() const
Get the DisplayPrecision to be used when converting the float to a string.
Definition: FloatT.h:500
virtual GENICAM_NAMESPACE::gcstring GetUnit() const
Implementation of IFloat::GetUnit()
Definition: FloatT.h:486
#define GCLOGINFO(cat,...)
Definition: CLog.h:162
#define CHECK_RANGE_FLT_NODE(_Value, _Min, _Max)
Range check for float.
Definition: Exception.h:192
Vector of doubles with reference counting.
Definition: Autovector.h:76
__int64 int64_t
Definition: config-win32.h:21
virtual EIncMode GetIncMode()
Definition: FloatT.h:413
double_autovector_impl m_CurentValidValueSet
The cached list of valie value for the integer.
Definition: FloatT.h:558
virtual IFloat & operator=(double Value)
Implementation of IFloat::operator=()
Definition: FloatT.h:133
virtual double GetValue(bool Verify=false, bool IgnoreCache=false)
Implementation of IFloat::GetValue()
Definition: FloatT.h:286
std::string str()
bool IsReadable(EAccessMode AccessMode)
Tests if readable.
Definition: INode.h:178
interface GENAPI_DECL_ABSTRACT IFloat
Interface for float properties.
Definition: IFloat.h:60
the notation is scientific, e.g. 1.234e2
Definition: Types.h:183
virtual bool HasInc()
True if the float has a constant increment.
Definition: FloatT.h:398
#define INVALID_ARGUMENT_EXCEPTION_NODE
Fires an invalid argument exception, e.g. throw INVALID_ARGUMENT("%ld too large", Value);...
Definition: Exception.h:157
bool IsAvailable(EAccessMode AccessMode)
Tests if available.
Definition: INode.h:232
Write to cache and register.
Definition: Types.h:82
double m_ImposedMin
a Value imposed to the minimum
Definition: FloatT.h:555
enum GENAPI_NAMESPACE::_ERepresentation ERepresentation
recommended representation of a node value
enum GENAPI_NAMESPACE::_ECachingMode ECachingMode
caching mode of a register
enum GENAPI_NAMESPACE::_EDisplayNotation EDisplayNotation
typedef for float notation
double m_ValueCache
The cache for the float value.
Definition: FloatT.h:549
Write to register, write to cache on read.
Definition: Types.h:83
#define ACCESS_EXCEPTION_NODE
Fires a access error exception, e.g. throw ACCESS_ERROR_EXCEPTION("Not everybody") ...
Definition: Exception.h:172
Invalidate the node and all of its dependents.
Definition: INodePrivate.h:94
interface GENAPI_DECL_ABSTRACT bool Verify
Definition: IBoolean.h:61
virtual EDisplayNotation GetDisplayNotation() const
Get the way the float should be converted to a string.
Definition: FloatT.h:493
#define GCLOGINFOPUSH(cat,...)
Definition: CLog.h:163
This file contains the internal implementation of the autovector.
virtual double_autovector_t GetListOfValidValues(bool bounded=true)
Get list of valid value.
Definition: FloatT.h:456
double m_ImposedMax
a Value imposed to the maximum
Definition: FloatT.h:552
virtual double GetMin()
Implementation of IFloat::GetMin()
Definition: FloatT.h:356
A string class which is a clone of std::string.
Definition: GCString.h:52
double Correction(const char *s)
Definition: FloatT.h:160
the notation if either scientific or fixed depending on what is shorter
Definition: Types.h:181
virtual ECachingMode GetCachingMode() const =0
Get Caching Mode.
bool IsWritable(EAccessMode AccessMode)
Tests if writable.
Definition: INode.h:196
virtual void SetInvalid(ESetInvalidMode simMode)=0
Invalidate the node resp. the node and all of its dependents.
enum GENAPI_NAMESPACE::_EIncMode EIncMode
typedef for increment mode
Implementation of the IFloat Interface.
Definition: FloatT.h:58
virtual void ImposeMin(double Value)
Restrict minimum value.
Definition: FloatT.h:534
virtual double operator*()
Implementation of IFloat::operator*()
Definition: FloatT.h:339
#define GCLOGINFOPOP(cat,...)
Definition: CLog.h:164
virtual void ImposeMax(double Value)
Restrict maximum value.
Definition: FloatT.h:541
virtual double GetInc()
Get the constant increment if there is any.
Definition: FloatT.h:434
virtual ERepresentation GetRepresentation()
Implementation of IFloat::GetRepresentation()
Definition: FloatT.h:479
virtual const char * c_str(void) const
virtual double operator()()
Implementation of IFloat::operator()()
Definition: FloatT.h:333
Part of the generic device API.
Definition: Autovector.h:48
Definition of interface INodePrivate.
callback is fired on leaving the tree inside the lock-guarded area
Definition: NodeCallback.h:48
the notation is fixed, e.g. 123.4
Definition: Types.h:182
virtual CLock & GetLock() const =0
Returns the lock which guards the node map.
bool String2Value(const GENICAM_NAMESPACE::gcstring &ValueStr, T *Value)
Converts a string to an T property.
Definition: Value2String.h:72
virtual GENICAM_NAMESPACE::gcstring InternalToString(bool Verify=false, bool IgnoreCache=false)
Get value of the node as string.
Definition: FloatT.h:214


rc_genicam_api
Author(s): Heiko Hirschmueller
autogenerated on Thu Jun 6 2019 19:10:54