00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00031 #ifndef GENAPI_FLOATT_H
00032 #define GENAPI_FLOATT_H
00033
00034
00035 #include "../NodeCallback.h"
00036 #include "INodePrivate.h"
00037 #include "../Synch.h"
00038 #include "../Counter.h"
00039 #include "Value2String.h"
00040 #include "GenApi/impl/Log.h"
00041 #include <limits>
00042 #include <cmath>
00043 #include <cstdlib>
00044 #include <algorithm>
00045 #include "Exception.h"
00046 #include "AutovectorImpl.h"
00047
00048 #pragma warning( disable : 4706 ) // assignment within conditional expression
00049
00050 namespace GENAPI_NAMESPACE
00051 {
00055 template<class Base>
00056 class FloatT : public Base
00057 {
00058 public:
00059
00061 FloatT< Base >() :
00062 Base(),
00063 m_ImposedMax( (std::numeric_limits<double>::max)() ),
00064 m_ImposedMin( -(std::numeric_limits<double>::max)() )
00065 {
00066 }
00067
00069 virtual void SetValue(double Value, bool Verify = true)
00070 {
00071
00072
00073 std::list<CNodeCallback*> CallbacksToFire;
00074 {
00075 AutoLock l(Base::GetLock());
00076 typename Base::EntryMethodFinalizer E( this, meSetValue );
00077
00078 GCLOGINFOPUSH( Base::m_pValueLog, "SetValue( %f )...", Value );
00079
00080 if( Verify )
00081 {
00082 if( !IsWritable( this ) )
00083 throw ACCESS_EXCEPTION_NODE("Node is not writable.");
00084
00085 CHECK_RANGE_FLT_NODE(Value, Base::InternalGetMin(), Base::InternalGetMax());
00086 }
00087
00088 {
00089 typename Base::PostSetValueFinalizer PostSetValueCaller(this, CallbacksToFire);
00090
00091
00092 Base::PreSetValue();
00093
00094
00095 Base::InternalSetValue(Value, Verify);
00096
00097 if( Verify )
00098 Base::InternalCheckError();
00099
00100 #if ! defined( DISABLE_VALUE_CACHING ) || (DISABLE_VALUE_CACHING == 0)
00101
00102 if( WriteThrough == static_cast<INode *>(this)->GetCachingMode() )
00103 {
00104 m_ValueCache = Value;
00105 Base::m_ValueCacheValid = true;
00106 Base::m_DontDeleteThisCache = true;
00107 }
00108 #endif
00109
00110 }
00111
00112 GCLOGINFOPOP( Base::m_pValueLog, "...SetValue" );
00113
00114
00115 std::list<CNodeCallback*>::iterator ptrCallback;
00116 for( ptrCallback = CallbacksToFire.begin(); ptrCallback != CallbacksToFire.end(); ptrCallback++ )
00117 {
00118 (*ptrCallback)->operator ()(cbPostInsideLock);
00119 }
00120 }
00121
00122
00123 std::list<CNodeCallback*>::iterator ptrCallback;
00124 for( ptrCallback = CallbacksToFire.begin(); ptrCallback != CallbacksToFire.end(); ptrCallback++ )
00125 {
00126 (*ptrCallback)->operator ()(cbPostOutsideLock);
00127 }
00128 }
00129
00131 virtual IFloat& operator=(double Value)
00132 {
00133 SetValue(Value);
00134
00135 return *this;
00136 }
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 double Correction( const char *s )
00159 {
00160
00161
00162 bool sign;
00163 char c;
00164
00165
00166 while( isspace(c = *s) )
00167 s++;
00168
00169
00170 if ((sign = (c == '-')))
00171 s++;
00172 else if (c == '+')
00173 s++;
00174
00175
00176 double v = 0.0;
00177 while( isdigit(*s) )
00178 v = 10.0 * v + (*s++ - '0');
00179
00180 double Cor = 0.5;
00181 if( *s == '.' )
00182 {
00183 s++;
00184
00185
00186 double fr = 10.0;
00187 while( isdigit(*s) )
00188 {
00189 v += (*s++ - '0') / fr;
00190 Cor *= 0.1;
00191 fr *= 10.0;
00192 }
00193 }
00194
00195
00196 double exp = 1.0;
00197 if (tolower(*s) == 'e')
00198 {
00199 int i = atoi(s);
00200 exp = pow(10.0, i);
00201 }
00202
00203
00204
00205
00206 Cor *= exp;
00207
00208 return Cor;
00209 }
00210
00212 virtual GENICAM_NAMESPACE::gcstring InternalToString(bool Verify = false, bool IgnoreCache = false)
00213 {
00214 AutoLock l(Base::GetLock());
00215
00216 std::stringstream Buffer;
00217 std::ostringstream CorrectedBuffer;
00218
00219
00220 switch( Base::InternalGetDisplayNotation() )
00221 {
00222 case fnAutomatic:
00223
00224 break;
00225 case fnFixed:
00226 Buffer.setf(std::ios::fixed, std::ios::floatfield);
00227 CorrectedBuffer.setf(std::ios::fixed, std::ios::floatfield);
00228 break;
00229 case fnScientific:
00230 Buffer.setf(std::ios::scientific, std::ios::floatfield);
00231 CorrectedBuffer.setf(std::ios::scientific, std::ios::floatfield);
00232 break;
00233 #pragma BullseyeCoverage off
00234 default:
00235 assert(false);
00236 #pragma BullseyeCoverage on
00237 }
00238
00239
00240 int Precision = (int)GetDisplayPrecision();
00241 Buffer.precision( Precision );
00242 CorrectedBuffer.precision( Precision );
00243
00244
00245 double Value = GetValue( Verify, IgnoreCache );
00246 Buffer << Value;
00247
00248
00249
00250
00251
00252 double VerifyValue;
00253 Buffer >> VerifyValue;
00254
00255 double CorrectedValue = Value;
00256 bool LimitsExceeded = false;
00257
00258
00259 if( VerifyValue > Base::InternalGetMax() )
00260 {
00261 CorrectedValue = Value - Correction( Buffer.str().c_str() );
00262 LimitsExceeded = true;
00263 }
00264 else if( VerifyValue < Base::InternalGetMin() )
00265 {
00266 CorrectedValue = Value + Correction( Buffer.str().c_str() );
00267 LimitsExceeded = true;
00268 }
00269
00270 GENICAM_NAMESPACE::gcstring valueString;
00271 if( LimitsExceeded )
00272 {
00273 CorrectedBuffer << CorrectedValue;
00274 valueString = CorrectedBuffer.str().c_str();
00275 }
00276 else
00277 {
00278 valueString = Buffer.str().c_str();
00279 }
00280 return valueString;
00281 }
00282
00284 virtual double GetValue(bool Verify = false, bool IgnoreCache = false)
00285 {
00286 AutoLock l(Base::GetLock());
00287 typename Base::EntryMethodFinalizer E( this, meGetValue, IgnoreCache );
00288
00289
00290 if( !IsReadable( this ) )
00291 throw ACCESS_EXCEPTION_NODE("Node is not readable.");
00292
00293 #if ! defined( DISABLE_VALUE_CACHING ) || (DISABLE_VALUE_CACHING == 0)
00294
00295 if (!IgnoreCache && Base::m_ValueCacheValid && !Verify)
00296 {
00297 GCLOGINFO( Base::m_pValueLog, "GetValue = %f (from cache)", m_ValueCache );
00298
00299 return m_ValueCache;
00300 }
00301 #endif
00302
00303 GCLOGINFOPUSH( Base::m_pValueLog, "GetValue...");
00304
00305 const double Value( Base::InternalGetValue(Verify, IgnoreCache) );
00306
00307 GCLOGINFOPOP( Base::m_pValueLog, "...GetValue = %f", Value );
00308
00309 if( Verify )
00310 {
00311 CHECK_RANGE_FLT_NODE(Value, Base::InternalGetMin(), Base::InternalGetMax());
00312 Base::InternalCheckError();
00313 }
00314
00315 #if ! defined( DISABLE_VALUE_CACHING ) || (DISABLE_VALUE_CACHING == 0)
00316
00317 const ECachingMode CachingMode(static_cast<INode *>(this)->GetCachingMode());
00318 if( WriteThrough == CachingMode
00319 || WriteAround == CachingMode )
00320 {
00321 m_ValueCache = Value;
00322 Base::m_ValueCacheValid = true;
00323 }
00324 #endif
00325
00326 return Value;
00327
00328 }
00329
00331 virtual double operator()()
00332 {
00333 return GetValue();
00334 }
00335
00337 virtual double operator*()
00338 {
00339 return GetValue();
00340 }
00341
00343 virtual void InternalFromString(const GENICAM_NAMESPACE::gcstring& ValueStr, bool Verify = true)
00344 {
00345 double value;
00346 if (!String2Value(ValueStr,&value))
00347 throw INVALID_ARGUMENT_EXCEPTION_NODE("Node '%s' : cannot convert string '%s' to double.", Base::m_Name.c_str(), ValueStr.c_str() );
00348
00349 SetValue(value, Verify);
00350 }
00351
00352
00354 virtual double GetMin()
00355 {
00356 AutoLock l(Base::GetLock());
00357 typename Base::EntryMethodFinalizer E( this, meGetMin );
00358
00359 GCLOGINFOPUSH( Base::m_pRangeLog, "GetMin..." );
00360
00361 double Minimum = Base::InternalGetMin();
00362 Minimum = (std::max)(Minimum, m_ImposedMin);
00363
00364 GCLOGINFOPOP( Base::m_pRangeLog, "...GetMin = %f", Minimum );
00365
00366 return Minimum;
00367
00368 }
00369
00371 virtual double GetMax()
00372 {
00373 AutoLock l(Base::GetLock());
00374 typename Base::EntryMethodFinalizer E( this, meGetMax );
00375
00376 GCLOGINFOPUSH( Base::m_pRangeLog, "GetMax...");
00377
00378 double Maximum(Base::InternalGetMax());
00379 Maximum = (std::min)( Maximum, m_ImposedMax );
00380
00381 GCLOGINFOPOP( Base::m_pRangeLog, "...GetMax = %f", Maximum );
00382
00383 return Maximum;
00384
00385 }
00386
00388 virtual bool HasInc()
00389 {
00390 AutoLock l(Base::GetLock());
00391
00392 GCLOGINFOPUSH( Base::m_pRangeLog, "HasInc...");
00393
00394 bool HasInc( Base::InternalHasInc() );
00395 #pragma BullseyeCoverage off
00396 GCLOGINFOPOP( Base::m_pRangeLog, "...HasInc = " + (HasInc ? GENICAM_NAMESPACE::gcstring("true") : GENICAM_NAMESPACE::gcstring("false")));
00397 #pragma BullseyeCoverage on
00398
00399 return HasInc;
00400
00401 }
00402
00403 virtual EIncMode GetIncMode()
00404 {
00405 AutoLock l(Base::GetLock());
00406 typename Base::EntryMethodFinalizer E( this, meGetIncMode );
00407
00408 GCLOGINFOPUSH( Base::m_pRangeLog, "GetIncMode...");
00409
00410 if( ! Base::m_ListOfValidValuesCacheValid )
00411 {
00412 m_CurentValidValueSet = Base::InternalGetListOfValidValues();
00413 Base::m_ListOfValidValuesCacheValid = true;
00414 }
00415
00416 EIncMode incMode( (m_CurentValidValueSet.size())? listIncrement: Base::InternalHasInc()? fixedIncrement : noIncrement );
00417
00418 GCLOGINFOPOP( Base::m_pRangeLog, "...GetIncMode" );
00419
00420 return incMode;
00421 }
00422
00424 virtual double GetInc()
00425 {
00426 AutoLock l(Base::GetLock());
00427 typename Base::EntryMethodFinalizer E( this, meGetInc );
00428
00429 if( !Base::InternalHasInc() )
00430 throw RUNTIME_EXCEPTION_NODE("node does not have an increment." );
00431
00432 GCLOGINFOPUSH( Base::m_pRangeLog, "GetInc...");
00433
00434 double Inc( Base::InternalGetInc() );
00435
00436 GCLOGINFOPOP( Base::m_pRangeLog, "...GetInc = %f", Inc );
00437
00438 return Inc;
00439 }
00440
00442 virtual double_autovector_t GetListOfValidValues(bool bounded = true)
00443 {
00444 AutoLock l(Base::GetLock());
00445 typename Base::EntryMethodFinalizer E( this, meGetListOfValidValues );
00446
00447 GCLOGINFOPUSH( Base::m_pRangeLog, "GetListOfValidValues...");
00448 if( ! Base::m_ListOfValidValuesCacheValid )
00449 {
00450 m_CurentValidValueSet = Base::InternalGetListOfValidValues();
00451 Base::m_ListOfValidValuesCacheValid = true;
00452 }
00453
00454 double_autovector_t list( ( bounded)? m_CurentValidValueSet.duplicate( Base::InternalGetMin(), Base::InternalGetMax()) : m_CurentValidValueSet);
00455
00456
00457 GCLOGINFOPOP( Base::m_pRangeLog, "...GetListOfValidValues" );
00458 return list;
00459
00460
00461 }
00462
00463
00465 virtual ERepresentation GetRepresentation()
00466 {
00467 AutoLock l(Base::GetLock());
00468 return Base::InternalGetRepresentation();
00469 }
00470
00472 virtual GENICAM_NAMESPACE::gcstring GetUnit() const
00473 {
00474 AutoLock l(Base::GetLock());
00475 return Base::InternalGetUnit();
00476 }
00477
00479 virtual EDisplayNotation GetDisplayNotation() const
00480 {
00481 AutoLock l(Base::GetLock());
00482 return Base::InternalGetDisplayNotation();
00483 }
00484
00486 virtual int64_t GetDisplayPrecision() const
00487 {
00488 AutoLock l(Base::GetLock());
00489
00490 int64_t Precision = Base::InternalGetDisplayPrecision();
00491
00492 if( Precision == -1 )
00493 {
00494
00495 std::stringstream Buffer;
00496 switch( Base::InternalGetDisplayNotation() )
00497 {
00498 case fnFixed:
00499 Buffer.setf(std::ios::fixed, std::ios::floatfield);
00500 break;
00501 case fnScientific:
00502 Buffer.setf(std::ios::scientific, std::ios::floatfield);
00503 break;
00504 case fnAutomatic:
00505
00506 break;
00507 #pragma BullseyeCoverage off
00508 default:
00509 assert(false);
00510 #pragma BullseyeCoverage on
00511 }
00512
00513 Precision = Buffer.precision();
00514 }
00515
00516 return Precision;
00517 }
00518
00520 virtual void ImposeMin(double Value)
00521 {
00522 m_ImposedMin = Value;
00523 Base::SetInvalid(INodePrivate::simAll);
00524 }
00525
00527 virtual void ImposeMax(double Value)
00528 {
00529 m_ImposedMax = Value;
00530 Base::SetInvalid(INodePrivate::simAll);
00531 }
00532
00533 protected:
00535 double m_ValueCache;
00536
00538 double m_ImposedMax;
00539
00541 double m_ImposedMin;
00542
00544 double_autovector_impl m_CurentValidValueSet;
00545 };
00546 }
00547
00548 #endif // GENAPI_FLOATT_H