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


rc_genicam_api
Author(s): Heiko Hirschmueller
autogenerated on Wed Mar 17 2021 02:48:40