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, Base::IsStreamable());
79 
80  Base::m_ValueCacheValid = false;
81 
82  GCLOGINFOPUSH( Base::m_pValueLog, "SetValue( %f )...", Value );
83 
84  if (!Base::CanBeWritten( Verify ))
85  {
86  throw ACCESS_EXCEPTION_NODE( "Node is not writable." );
87  }
88 
89  if (Verify || !Base::m_pNodeMap->EntryIsStremable())
90  {
91  CHECK_RANGE_FLT_NODE(Value, Base::InternalGetMin(), Base::InternalGetMax());
92  }
93 
94  {
95  typename Base::PostSetValueFinalizer PostSetValueCaller(this, CallbacksToFire); // dtor calls Base::PostSetValue
96 
97  // invalidates all nodes if this is the first call in a chain of SetValue calls
98  Base::PreSetValue();
99 
100  // sets the value
101  Base::InternalSetValue(Value, Verify);
102 
103  #if ! defined( DISABLE_VALUE_CACHING ) || (DISABLE_VALUE_CACHING == 0)
104  // Fill cache
105  if( WriteThrough == static_cast<INode *>(this)->GetCachingMode() )
106  {
107  m_ValueCache = Value;
108  Base::m_ValueCacheValid = true;
109  Base::m_DontDeleteThisCache = true;
110  }
111  #endif
112 
113  }
114  if (Verify)
115  Base::InternalCheckError();
116 
117  GCLOGINFOPOP( Base::m_pValueLog, "...SetValue" );
118 
119  // fire callbacks inside the lock
120  std::list<CNodeCallback*>::iterator ptrCallback;
121  for( ptrCallback = CallbacksToFire.begin(); ptrCallback != CallbacksToFire.end(); ptrCallback++ )
122  {
123  (*ptrCallback)->operator ()(cbPostInsideLock);
124  }
125  }
126 
127  // fire callbacks outside the lock
128  std::list<CNodeCallback*>::iterator ptrCallback;
129  for( ptrCallback = CallbacksToFire.begin(); ptrCallback != CallbacksToFire.end(); ptrCallback++ )
130  {
131  (*ptrCallback)->operator ()(cbPostOutsideLock);
132  }
133  }
134 
136  virtual IFloat& operator=(double Value)
137  {
138  SetValue(Value);
139 
140  return *this;
141  }
142 
143  /* This is a helper function used in the method ToString (see below)
144  It parses a floating point number given in a buffer s and creates a correction value used for correct rounding
145 
146  If the number in s is given in fixed point notation like
147  123.4567
148  the correction is
149  0.00005
150  that is it has zeros for all trailing digits of the number followed by a '5'
151 
152  In case of scientific notation like
153  1.1234e-12
154  the correction number is
155  0.00005e-12
156  that is it has zeros for all trailing digits of the number followed by a '5' plus it has
157  the same exponent as the original number.
158 
159  The use of the correction number is explained below in the method ToString
160 
161  The code is inspired from from http://www.hackchina.com/en/r/185703/ATOF.C__html
162  */
163  double Correction( const char *s )
164  {
165  // note that while parsing the parsed value is composed even if that is not necessary
166  // nevertheless the code is left as is for clarification and verification purposes
167  bool sign;
168  char c;
169 
170  // eat white space
171  while( isspace(c = *s) )
172  s++;
173 
174  // handle sign
175  if ((sign = (c == '-')))
176  s++;
177  else if (c == '+')
178  s++;
179 
180  // read digits before decimal point
181  double v = 0.0;
182  while( isdigit(*s) )
183  v = 10.0 * v + (*s++ - '0');
184 
185  double Cor = 0.5;
186  if( *s == '.' )
187  {
188  s++;
189 
190  // eat digits after decimal point
191  double fr = 10.0;
192  while( isdigit(*s) )
193  {
194  v += (*s++ - '0') / fr;
195  Cor *= 0.1;
196  fr *= 10.0;
197  }
198  }
199 
200  // handle exponent
201  double exp = 1.0;
202  if (tolower(*s) == 'e')
203  {
204  int i = atoi(s);
205  exp = pow(10.0, i);
206  }
207 
208  //v *= exp;
209  //v = sign ? -v : v;
210 
211  Cor *= exp;
212 
213  return Cor;
214  }
215 
217  virtual GENICAM_NAMESPACE::gcstring InternalToString(bool Verify = false, bool IgnoreCache = false)
218  {
219  AutoLock l(Base::GetLock());
220 
221  std::stringstream Buffer;
222  std::ostringstream CorrectedBuffer;
223 
224  // set DisplayNotation
225  switch( Base::InternalGetDisplayNotation() )
226  {
227  case fnAutomatic:
228  // default
229  break;
230  case fnFixed:
231  Buffer.setf(std::ios::fixed, std::ios::floatfield);
232  CorrectedBuffer.setf(std::ios::fixed, std::ios::floatfield);
233  break;
234  case fnScientific:
235  Buffer.setf(std::ios::scientific, std::ios::floatfield);
236  CorrectedBuffer.setf(std::ios::scientific, std::ios::floatfield);
237  break;
238  #pragma BullseyeCoverage off
239  default:
240  assert(false);
241  #pragma BullseyeCoverage on
242  }
243 
244  // set DisplayPrecision
245  int Precision = (int)GetDisplayPrecision();
246  Buffer.precision( Precision );
247  CorrectedBuffer.precision( Precision );
248 
249  // output
250  double Value = GetValue( Verify, IgnoreCache );
251  Buffer << Value;
252 
253  // Make sure FromString will work with the result
254  // for details see the test code in FloatTestSuite::TestTicket785
255 
256  // read back the created string
257  double VerifyValue;
258  Buffer >> VerifyValue;
259 
260  double CorrectedValue = Value;
261  bool LimitsExceeded = false;
262 
263  // the string may be too large due to rounding issues
264  if( VerifyValue > Base::InternalGetMax() )
265  {
266  CorrectedValue = Value - Correction( Buffer.str().c_str() );
267  LimitsExceeded = true;
268  }
269  else if( VerifyValue < Base::InternalGetMin() )
270  {
271  CorrectedValue = Value + Correction( Buffer.str().c_str() );
272  LimitsExceeded = true;
273  }
274 
275  GENICAM_NAMESPACE::gcstring valueString;
276  if( LimitsExceeded )
277  {
278  CorrectedBuffer << CorrectedValue;
279  valueString = CorrectedBuffer.str().c_str();
280  }
281  else
282  {
283  valueString = Buffer.str().c_str();
284  }
285  return valueString;
286  }
287 
289  virtual double GetValue(bool Verify = false, bool IgnoreCache = false)
290  {
291  AutoLock l(Base::GetLock());
292  typename Base::EntryMethodFinalizer E(this, meGetValue, Base::IsStreamable(), IgnoreCache);
293 
294  // Note that readability is tested regardless of Verify
295  if( !IsReadable( this ) )
296  throw ACCESS_EXCEPTION_NODE("Node is not readable.");
297 
298  #if ! defined( DISABLE_VALUE_CACHING ) || (DISABLE_VALUE_CACHING == 0)
299  // Use cache
300  if (!IgnoreCache && Base::m_ValueCacheValid && !Verify)
301  {
302  GCLOGINFO( Base::m_pValueLog, "GetValue = %f (from cache)", m_ValueCache );
303 
304  return m_ValueCache;
305  }
306  #endif
307 
308  GCLOGINFOPUSH( Base::m_pValueLog, "GetValue...");
309 
310  const double Value( Base::InternalGetValue(Verify, IgnoreCache) );
311 
312  GCLOGINFOPOP( Base::m_pValueLog, "...GetValue = %f", Value );
313 
314  if( Verify )
315  {
316  CHECK_RANGE_FLT_NODE(Value, Base::InternalGetMin(), Base::InternalGetMax());
317  Base::InternalCheckError();
318  }
319 
320  #if ! defined( DISABLE_VALUE_CACHING ) || (DISABLE_VALUE_CACHING == 0)
321  // Fill cache
322  const ECachingMode CachingMode(static_cast<INode *>(this)->GetCachingMode());
323  if( WriteThrough == CachingMode
324  || WriteAround == CachingMode )
325  {
326  m_ValueCache = Value;
327  Base::m_ValueCacheValid = true;
328  }
329  #endif
330 
331  return Value;
332 
333  }
334 
336  virtual double operator()()
337  {
338  return GetValue();
339  }
340 
342  virtual double operator*()
343  {
344  return GetValue();
345  }
346 
348  virtual void InternalFromString(const GENICAM_NAMESPACE::gcstring& ValueStr, bool Verify = true)
349  {
350  double value;
351  if (!String2Value(ValueStr,&value))
352  throw INVALID_ARGUMENT_EXCEPTION_NODE("Node '%s' : cannot convert string '%s' to double.", Base::m_Name.c_str(), ValueStr.c_str() );
353 
354  SetValue(value, Verify);
355  }
356 
357 
359  virtual double GetMin()
360  {
361  AutoLock l(Base::GetLock());
362  typename Base::EntryMethodFinalizer E( this, meGetMin );
363 
364  // only allowed for available nodes
365  if (!IsAvailable(this))
366  throw ACCESS_EXCEPTION_NODE("Node is not available.");
367 
368  GCLOGINFOPUSH( Base::m_pRangeLog, "GetMin..." );
369 
370  double Minimum = Base::InternalGetMin();
371  Minimum = (std::max)(Minimum, m_ImposedMin);
372 
373  GCLOGINFOPOP( Base::m_pRangeLog, "...GetMin = %f", Minimum );
374 
375  return Minimum;
376 
377  }
378 
380  virtual double GetMax()
381  {
382  AutoLock l(Base::GetLock());
383  typename Base::EntryMethodFinalizer E( this, meGetMax );
384 
385  // only allowed for available nodes
386  if (!IsAvailable(this))
387  throw ACCESS_EXCEPTION_NODE("Node is not available.");
388 
389  GCLOGINFOPUSH( Base::m_pRangeLog, "GetMax...");
390 
391  double Maximum(Base::InternalGetMax());
392  Maximum = (std::min)( Maximum, m_ImposedMax );
393 
394  GCLOGINFOPOP( Base::m_pRangeLog, "...GetMax = %f", Maximum );
395 
396  return Maximum;
397 
398  }
399 
401  virtual bool HasInc()
402  {
403  AutoLock l(Base::GetLock());
404 
405  GCLOGINFOPUSH( Base::m_pRangeLog, "HasInc...");
406 
407  bool HasInc( Base::InternalHasInc() );
408 #pragma BullseyeCoverage off
409  GCLOGINFOPOP( Base::m_pRangeLog, "...HasInc = " + (HasInc ? GENICAM_NAMESPACE::gcstring("true") : GENICAM_NAMESPACE::gcstring("false")));
410 #pragma BullseyeCoverage on
411 
412  return HasInc;
413 
414  }
415 
417  {
418  AutoLock l(Base::GetLock());
419  typename Base::EntryMethodFinalizer E( this, meGetIncMode );
420 
421  GCLOGINFOPUSH( Base::m_pRangeLog, "GetIncMode...");
422 
423  if( ! Base::m_ListOfValidValuesCacheValid )
424  {
425  m_CurentValidValueSet = Base::InternalGetListOfValidValues();
426  Base::m_ListOfValidValuesCacheValid = true;
427  }
428 
429  EIncMode incMode( (m_CurentValidValueSet.size())? listIncrement: Base::InternalHasInc()? fixedIncrement : noIncrement );
430 
431  GCLOGINFOPOP( Base::m_pRangeLog, "...GetIncMode" );
432 
433  return incMode;
434  }
435 
437  virtual double GetInc()
438  {
439  AutoLock l(Base::GetLock());
440  typename Base::EntryMethodFinalizer E( this, meGetInc );
441 
442  if( !Base::InternalHasInc() )
443  throw RUNTIME_EXCEPTION_NODE("node does not have an increment." );
444 
445  // only allowed for available nodes
446  if (!IsAvailable(this))
447  throw ACCESS_EXCEPTION_NODE("Node is not available.");
448 
449  GCLOGINFOPUSH( Base::m_pRangeLog, "GetInc...");
450 
451  double Inc( Base::InternalGetInc() );
452 
453  GCLOGINFOPOP( Base::m_pRangeLog, "...GetInc = %f", Inc );
454 
455  return Inc;
456  }
457 
459  virtual double_autovector_t GetListOfValidValues(bool bounded = true)
460  {
461  AutoLock l(Base::GetLock());
462  typename Base::EntryMethodFinalizer E(this, meGetListOfValidValues, Base::IsStreamable());
463 
464  GCLOGINFOPUSH( Base::m_pRangeLog, "GetListOfValidValues...");
465  if( ! Base::m_ListOfValidValuesCacheValid )
466  {
467  m_CurentValidValueSet = Base::InternalGetListOfValidValues();
468  Base::m_ListOfValidValuesCacheValid = true;
469  }
470 
471  double_autovector_t list( ( bounded)? m_CurentValidValueSet.duplicate( Base::InternalGetMin(), Base::InternalGetMax()) : m_CurentValidValueSet);
472 
473 
474  GCLOGINFOPOP( Base::m_pRangeLog, "...GetListOfValidValues" );
475  return list;
476 
477 
478  }
479 
480 
483  {
484  AutoLock l(Base::GetLock());
485  return Base::InternalGetRepresentation();
486  }
487 
490  {
491  AutoLock l(Base::GetLock());
492  return Base::InternalGetUnit();
493  }
494 
497  {
498  AutoLock l(Base::GetLock());
499  return Base::InternalGetDisplayNotation();
500  }
501 
503  virtual int64_t GetDisplayPrecision() const
504  {
505  AutoLock l(Base::GetLock());
506 
507  int64_t Precision = Base::InternalGetDisplayPrecision();
508 
509  if( Precision == -1 )
510  {
511  // determine built in precision
512  std::stringstream Buffer;
513  switch( Base::InternalGetDisplayNotation() )
514  {
515  case fnFixed:
516  Buffer.setf(std::ios::fixed, std::ios::floatfield);
517  break;
518  case fnScientific:
519  Buffer.setf(std::ios::scientific, std::ios::floatfield);
520  break;
521  case fnAutomatic:
522  // default
523  break;
524  #pragma BullseyeCoverage off
525  default:
526  assert(false);
527  #pragma BullseyeCoverage on
528  }
529 
530  Precision = Buffer.precision();
531  }
532 
533  return Precision;
534  }
535 
537  virtual void ImposeMin(double Value)
538  {
539  m_ImposedMin = Value;
541  }
542 
544  virtual void ImposeMax(double Value)
545  {
546  m_ImposedMax = Value;
548  }
549 
550  protected:
552  double m_ValueCache;
553 
555  double m_ImposedMax;
556 
558  double m_ImposedMin;
559 
562  };
563 }
564 
565 #endif // GENAPI_FLOATT_H
Definition of value2string and string2value functions.
virtual bool CanBeWritten(bool Verify)=0
virtual void InternalFromString(const GENICAM_NAMESPACE::gcstring &ValueStr, bool Verify=true)
Set value of the node as string.
Definition: FloatT.h:348
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:380
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:173
virtual EDisplayNotation GetDisplayNotation() const
Get the way the float should be converted to a string.
Definition: FloatT.h:496
virtual const char * c_str(void) const
virtual int64_t GetDisplayPrecision() const
Get the DisplayPrecision to be used when converting the float to a string.
Definition: FloatT.h:503
#define GCLOGINFO(cat,...)
Definition: CLog.h:129
GENICAM_INTERFACE GENAPI_DECL_ABSTRACT bool Verify
Definition: IBoolean.h:61
#define CHECK_RANGE_FLT_NODE(_Value, _Min, _Max)
Range check for float.
Definition: Exception.h:199
Vector of doubles with reference counting.
Definition: Autovector.h:76
__int64 int64_t
Definition: config-win32.h:21
virtual EIncMode GetIncMode()
Definition: FloatT.h:416
double_autovector_impl m_CurentValidValueSet
The cached list of valie value for the integer.
Definition: FloatT.h:561
virtual IFloat & operator=(double Value)
Implementation of IFloat::operator=()
Definition: FloatT.h:136
virtual double GetValue(bool Verify=false, bool IgnoreCache=false)
Implementation of IFloat::GetValue()
Definition: FloatT.h:289
virtual GENICAM_NAMESPACE::gcstring GetUnit() const
Implementation of IFloat::GetUnit()
Definition: FloatT.h:489
std::string str()
bool IsReadable(EAccessMode AccessMode)
Tests if readable.
Definition: INode.h:178
the notation is scientific, e.g. 1.234e2
Definition: Types.h:182
virtual bool HasInc()
True if the float has a constant increment.
Definition: FloatT.h:401
#define INVALID_ARGUMENT_EXCEPTION_NODE
Fires an invalid argument exception, e.g. throw INVALID_ARGUMENT("%ld too large", Value);...
Definition: Exception.h:164
bool IsAvailable(EAccessMode AccessMode)
Tests if available.
Definition: INode.h:232
Write to cache and register.
Definition: Types.h:81
double m_ImposedMin
a Value imposed to the minimum
Definition: FloatT.h:558
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:552
Write to register, write to cache on read.
Definition: Types.h:82
#define ACCESS_EXCEPTION_NODE
Fires a access error exception, e.g. throw ACCESS_ERROR_EXCEPTION("Not everybody") ...
Definition: Exception.h:179
Invalidate the node and all of its dependents.
Definition: INodePrivate.h:94
#define GCLOGINFOPUSH(cat,...)
Definition: CLog.h:130
virtual bool IsStreamable() const =0
True if the node is streamable.
virtual bool EntryIsStremable()=0
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:459
double m_ImposedMax
a Value imposed to the maximum
Definition: FloatT.h:555
virtual double GetMin()
Implementation of IFloat::GetMin()
Definition: FloatT.h:359
A string class which is a clone of std::string.
Definition: GCString.h:52
double Correction(const char *s)
Definition: FloatT.h:163
the notation if either scientific or fixed depending on what is shorter
Definition: Types.h:180
virtual ECachingMode GetCachingMode() const =0
Get Caching Mode.
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
GENICAM_INTERFACE GENAPI_DECL_ABSTRACT IFloat
Interface for float properties.
Definition: IFloat.h:60
Implementation of the IFloat Interface.
Definition: FloatT.h:58
virtual void ImposeMin(double Value)
Restrict minimum value.
Definition: FloatT.h:537
virtual double operator*()
Implementation of IFloat::operator*()
Definition: FloatT.h:342
#define GCLOGINFOPOP(cat,...)
Definition: CLog.h:134
virtual void ImposeMax(double Value)
Restrict maximum value.
Definition: FloatT.h:544
virtual double GetInc()
Get the constant increment if there is any.
Definition: FloatT.h:437
virtual ERepresentation GetRepresentation()
Implementation of IFloat::GetRepresentation()
Definition: FloatT.h:482
virtual double operator()()
Implementation of IFloat::operator()()
Definition: FloatT.h:336
Lexical analyzer for CIntSwissKnife.
Definition: Destructible.h:30
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:181
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:217


rc_genicam_api
Author(s): Heiko Hirschmueller
autogenerated on Sun Jun 18 2023 02:43:55