GenApi 3.5.1
Persistence.h
Go to the documentation of this file.
1//-----------------------------------------------------------------------------
2// (c) 2007 by National Instruments
3// Author: Eric Gross
4//
5// License: This file is published under the license of the EMVA GenICam Standard Group.
6// A text file describing the legal terms is included in your installation as 'GenICam_license.pdf'.
7// If for some reason you are missing this file please contact the EMVA or visit the website
8// (http://www.genicam.org) for a full copy.
9//
10// THIS SOFTWARE IS PROVIDED BY THE EMVA GENICAM STANDARD GROUP "AS IS"
11// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
12// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
13// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE EMVA GENICAM STANDARD GROUP
14// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
15// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
16// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
17// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
18// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
19// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
20// POSSIBILITY OF SUCH DAMAGE.
21//
22//-----------------------------------------------------------------------------
29#ifndef _GENICAM_PERSISTENCE_H
30#define _GENICAM_PERSISTENCE_H
31
32#include <GenApi/Types.h>
33#include <GenApi/Pointer.h>
34#include <GenApi/GenApiDll.h>
35#include <GenApi/SelectorSet.h>
36#include <list>
37#include <iostream>
38#include <cstring>
39#include <locale>
40
41namespace GENAPI_NAMESPACE
42{
43
45 GENICAM_INTERFACE GENAPI_DECL_ABSTRACT IPersistScript
46 {
48 virtual void SetInfo(const GENICAM_NAMESPACE::gcstring &Info) = 0;
49
51 virtual void PersistFeature(IValue& item, CSelectorSet *selectorSet = NULL) = 0;
52 };
53
55 class GENAPI_DECL CFeatureBag : public IPersistScript
56 {
57 public:
59 virtual void SetInfo(const GENICAM_NAMESPACE::gcstring &Info);
60
62 virtual void PersistFeature(IValue& item, CSelectorSet *selectorSet = NULL);
63
68
72 bool LoadFromBag(INodeMap *pNodeMap, bool Verify = true, GENICAM_NAMESPACE::gcstring_vector *pErrorList = NULL);
73
80 int64_t StoreToBag(INodeMap *pNodeMap, const int MaxNumPersistSkriptEntries = -1, GENICAM_NAMESPACE::gcstring_vector *pFeatureFilter = NULL);
81
83 bool operator==(const CFeatureBag &FeatureBag) const;
84
86
87 virtual void Destroy();
88
89 virtual const GENICAM_NAMESPACE::gcstring& GetBagName( void ) const;
90 virtual void SetBagName(const GENICAM_NAMESPACE::gcstring& bagName);
91
93 friend std::istream& operator >>(std::istream &is, CFeatureBag &FeatureBag);
94
96 friend std::ostream& operator <<(std::ostream &os, const CFeatureBag &FeatureBag);
97
98
100 CFeatureBag(const CFeatureBag&);
102 virtual ~CFeatureBag();
103 private:
104
105 CSelectorState* AllocateSelector();
106 void DeleteSelector(CSelectorState*& p);
107
108 void Clear();
109 void Push(const char *name, const char *value, CSelectorState *ps);
110
111 const GENICAM_NAMESPACE::gcstring& GetInfo() const;
112
113 struct Triplet
114 {
117 CSelectorState* pState;
118 };
119
120 class GENAPI_DECL const_iterator
121 {
122 // Ctor / Dtor
123 // -------------------------------------------------------------------------
124 public:
125 const_iterator(Triplet *pTriplet = NULL);
126 const_iterator(const const_iterator&);
127 const_iterator& operator=(const const_iterator&);
128 // Operators
129 // -------------------------------------------------------------------------
130 public:
131 const Triplet & operator * (void) const;
132 const Triplet * operator -> (void) const;
133 const_iterator & operator ++ (void);
134 const_iterator operator ++ (int);
135 const_iterator & operator += (intptr_t iInc);
136 const_iterator operator + (intptr_t iInc) const;
137 intptr_t operator - (const const_iterator &iter) const;
138 bool operator == (const const_iterator &iter) const;
139 bool operator != (const const_iterator &iter) const;
140
141 // Member
142 // -------------------------------------------------------------------------
143 protected:
144 Triplet *m_pTriplet;
145
146 };
147 const_iterator GetBegin();
148 const_iterator GetBegin() const;
149 const_iterator GetEnd();
150 const_iterator GetEnd() const;
151 private:
152 struct FeatureBagImpl;
153 FeatureBagImpl *m_pImpl;
154
155
156 bool LoadFromBagInternal(INodeMap *pNodeMap, bool Verify /* = true */, GENICAM_NAMESPACE::gcstring_vector *pErrorList = NULL);
157 int64_t StoreToBagInternal(INodeMap *pNodeMap, const int MaxNumPersistSkriptEntries = -1, GENICAM_NAMESPACE::gcstring_vector *pFeatureFilter = NULL);
158
159 friend class CFeatureBagger;
160 };
161
163 #define GENAPI_PERSISTENCE_MAGIC "{05D8C294-F295-4dfb-9D01-096BD04049F4}"
164
166 #define GENAPI_PERSISTENCE_MAGIC_FEATUREBAGGER "{4709CB3C-7322-4460-84C3-DA11DDA09939}"
167
169 // note: this method must be inlined because it uses istream in the parameter list
170 inline std::istream& EatComments(std::istream &is)
171 {
172 if( is.eof() )
173 {
174 return is;
175 }
176
177 char FirstCharacter = static_cast<char>(is.peek());
178 while( FirstCharacter == '#' )
179 {
180 is.ignore(1024, '\n');
181 FirstCharacter = static_cast<char>(is.peek());
182 }
183 return is;
184 }
185
186#ifndef GENAPI_DONT_USE_DEFAULT_PERSISTENCE_FILE_FORMAT
188 inline char* TrimSpace( char* Name, std::istream& is )
189 {
190 char* pend = Name + strlen( Name );
191 char* pc = Name;
192 for (; pc < pend && std::isspace( *pc, is.getloc() ); ++pc);
193 for (--pend; pc < pend && std::isspace( *pend, is.getloc() ); --pend);
194 pend[1] = '\0';
195
196 return pc;
197 }
198 inline GENICAM_NAMESPACE::gcstring& TrimSpace( GENICAM_NAMESPACE::gcstring& s, std::istream& is )
199 {
200 size_t iend =s.length();
201 size_t ibegin = 0;
202 for (; ibegin < iend && std::isspace( s[ibegin], is.getloc() ); ++ibegin);
203 for (--iend; ibegin < iend; --iend)
204 {
205 if (!std::isspace( s[iend], is.getloc() ))
206 break;
207 }
208 if (iend < s.length())
209 {
210 s.erase(iend + 1);
211 }
212 s.erase( 0, ibegin );
213
214 return s;
215 }
216
217 template <class ForwardIterator, class T>
218 inline ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& val)
219 {
220 ForwardIterator result = first;
221 while (first!=last) {
222 if (!(*first == val)) {
223 if (result!=first)
224 *result = *first;
225 ++result;
226 }
227 ++first;
228 }
229 return result;
230 }
231
233 // note: this method must be inlined because it uses istream in the parameter list
234 // note: May not be used as inline if called against a library where it is already compiled.
235 inline std::istream& operator >>(std::istream &is, CFeatureBag &FeatureBag)
236 {
237 if( is.eof() )
238 {
239 throw RUNTIME_EXCEPTION("The stream is eof");
240 }
241
242 FeatureBag.Clear();
243
244 std::ostringstream originalContent;
245 originalContent << is.rdbuf();
246 is.seekg(std::ios::beg);
247 std::string toBeNormalized(originalContent.str());
248 // Remove CRs from the source
249 toBeNormalized.erase(
250 GENAPI_NAMESPACE::remove(toBeNormalized.begin(),
251 toBeNormalized.end(), 13), toBeNormalized.end());
252 std::stringbuf normalizedBuffer(toBeNormalized.c_str());
253 std::istream normalizedStream(&normalizedBuffer);
254
256 FirstLine.reserve( 128 );
257 GENICAM_NAMESPACE::getline( normalizedStream, FirstLine, '\n' );
258 // Check the magic
260 if( GENICAM_NAMESPACE::gcstring::_npos() == FirstLine.find(MagicGUID) )
261 {
263 if( GENICAM_NAMESPACE::gcstring::_npos() == FirstLine.find(MagicGUID) )
264 {
265 throw RUNTIME_EXCEPTION("The stream is not a GenApi feature stream since it is missing the magic GUID in the first line");
266 }
267 throw RUNTIME_EXCEPTION("The stream has been created using the CFeatureBagger class thus must be restored using the CFeatureBagger class as well");
268 }
269
270 EatComments( normalizedStream );
271
272 GENICAM_NAMESPACE::gcstring Name, Value;
273 Name.reserve( 128 );
274 Value.reserve( 128 );
275 while (!normalizedStream.eof())
276 {
277 GENICAM_NAMESPACE::getline( normalizedStream, Name, '\t' );
278 if (normalizedStream.fail()) // if reading from stream failed -> stop reading!
279 {
280 throw RUNTIME_EXCEPTION( "The stream holds excess data" );
281 break;
282 }
283
284 Name = TrimSpace( Name, normalizedStream );
285 if (Name.empty())
286 {
287 continue;
288 }
289
290 CSelectorState *pSelectorState = FeatureBag.AllocateSelector();
291 if (!pSelectorState)
292 {
293 throw RUNTIME_EXCEPTION( "Unable to allocate SelectorState" );
294 }
295
296
297 if (normalizedStream.peek() == '{')
298 {
299 GENICAM_NAMESPACE::getline( normalizedStream, Value, '\t' );
300 if (normalizedStream.fail()) // if reading from stream failed -> stop reading!
301 {
302 break;
303 }
304 for (size_t iassign = Value.find_last_of( '=' ); iassign != GENICAM_NAMESPACE::gcstring::_npos(); iassign = Value.find_last_of( '=' ))
305 {
306 const size_t iend = Value.find_last_of( '}');
307 const size_t ibeg = (Value[0] == '{') ? 1 : 0;
308 const size_t rhs_len = iend == GENICAM_NAMESPACE::gcstring::_npos() ? iend : iend - iassign - 1;
309 const size_t lhs_len = iassign - ibeg;
310 GENICAM_NAMESPACE::gcstring selectorName = Value.substr( ibeg, lhs_len );
311 GENICAM_NAMESPACE::gcstring selectorValue = Value.substr( iassign + 1, rhs_len );
312 pSelectorState->AddSelector( selectorName, selectorValue );
313 if (iend != GENICAM_NAMESPACE::gcstring::_npos())
314 {
315 break;
316 }
317
318 GENICAM_NAMESPACE::getline( normalizedStream, Value, '\t' );
319 if (normalizedStream.fail())
320 {
321 break;
322 }
323 }
324 }
325 GENICAM_NAMESPACE::getline( normalizedStream, Value, '\n' );
326 if (Value.empty())
327 {
328 FeatureBag.DeleteSelector(pSelectorState);
329 throw RUNTIME_EXCEPTION( "The stream holds incomplete key - value - set" );
330 }
331
332 FeatureBag.Push( Name.c_str(), Value.c_str(), pSelectorState );
333
334 EatComments( normalizedStream );
335 }
336 return is;
337 }
338
340 // note: this method must be inlined because it uses ostream in the parameter list
341 // note: May not be used as inline if called against a library where it is already compiled.
342 inline std::ostream& operator <<(std::ostream &os, const CFeatureBag &FeatureBag)
343 {
344 os << "# " GENAPI_PERSISTENCE_MAGIC "\n";
345 if( !FeatureBag.GetInfo().empty() )
346 {
347 os << "# GenApi persistence file (version " << GENAPI_VERSION_MAJOR << "." << GENAPI_VERSION_MINOR << "." << GENAPI_VERSION_SUBMINOR << ")\n";
348 os << "# " << FeatureBag.GetInfo() << "\n";
349 }
350 for (
351 CFeatureBag::const_iterator it = FeatureBag.GetBegin(), end = FeatureBag.GetEnd();
352 it != end;
353 ++it
354 )
355 {
356 const GENICAM_NAMESPACE::gcstring Name(it->name);
357 const GENICAM_NAMESPACE::gcstring Value(it->value);
358 if ((it->pState)->IsEmpty())
359 {
360 os << Name << "\t" << Value << "\n";
361 }
362 else
363 {
364 bool isFirst = true;
365 os << Name << "\t{";
366 (it->pState)->SetFirst();
367 do
368 {
369 if (!isFirst)
370 os << "\t";
371 else
372 isFirst = false;
373 os << (it->pState)->GetNodeName() << "=" << (it->pState)->GetNodeValue();
374 } while ((it->pState)->SetNext());
375 os << "}\t" << Value << "\n";
376 }
377 }
378
379 return os;
380 }
381#endif // #ifndef GENAPI_DONT_USE_DEFAULT_PERSISTENCE_FILE_FORMAT
382
384 class GENAPI_DECL CFeatureBagger
385 {
386 public:
387 class GENAPI_DECL const_iterator
388 {
389 // Ctor / Dtor
390 // -------------------------------------------------------------------------
391 public:
392 const_iterator(CFeatureBag **ppBag = NULL);
393
394 // Operators
395 // -------------------------------------------------------------------------
396 public:
397 const CFeatureBag & operator * (void) const;
398 const CFeatureBag * operator -> (void) const;
399 const_iterator & operator ++ (void);
400 const_iterator operator ++ (int);
401 const_iterator & operator += (intptr_t iInc);
402 const_iterator operator + (intptr_t iInc) const;
403 intptr_t operator - (const const_iterator &iter) const;
404 bool operator == (const const_iterator &iter) const;
405 bool operator != (const const_iterator &iter) const;
406
407 // Member
408 // -------------------------------------------------------------------------
409 protected:
410 CFeatureBag **_ppb;
411 };
412 explicit CFeatureBagger();
413 virtual ~CFeatureBagger();
414
423 size_t Bag(INodeMap *pNodeMap, bool handleDefaultNodeMap = true, bool handleUserSets = false, bool handleSequencerSets = false, const int MaxNumPersistSkriptEntries = -1);
424
428
432 bool UnBag(INodeMap *pNodeMap, bool Verify = true, GENICAM_NAMESPACE::gcstring_vector *pErrorList = NULL);
433
435 virtual void SetInfo(const GENICAM_NAMESPACE::gcstring &Info);
436
437 // Element access
438 // ---------------------------------------------------------------------------
439 virtual const_iterator begin(void) const;
440 virtual const_iterator end(void) const;
441 virtual const CFeatureBag& at(size_t uiIndex) const;
442 virtual size_t size(void) const;
443
445 friend std::ostream& operator <<(std::ostream &os, const CFeatureBagger &featureBagger);
446
448 friend std::istream& operator >>(std::istream &is, CFeatureBagger &featureBagger);
449
450 private:
451 CFeatureBagger(const CFeatureBagger&); // do not allow copy constructor
452 CFeatureBagger& operator=(const CFeatureBagger&); // do not allow assignments
453 CFeatureBag& AddBag(const GENICAM_NAMESPACE::gcstring &bagName);
454 void DeleteAllBags( void );
455 template<class _Ty>
456 void UnBagCustomAction(INodeMap *pNodeMap, _Ty setNodePtr, const GENICAM_NAMESPACE::gcstring& setNodeValue, CCommandPtr saveNodePtr );
457
458 void *m_pBags;
461 };
462
463#ifndef GENAPI_DONT_USE_DEFAULT_PERSISTENCE_FILE_FORMAT
465 // note: this method must be inlined because it uses ostream in the parameter list
466 // note: May not be used as inline if called against a library where it is already compiled.
467 inline std::ostream& operator <<(std::ostream &os, const CFeatureBagger &featureBagger)
468 {
470 if( !featureBagger.m_Info.empty() )
471 {
472 os << "# GenApi CFeatureBagger persistence file (version " << GENAPI_VERSION_MAJOR << "." << GENAPI_VERSION_MINOR << "." << GENAPI_VERSION_SUBMINOR << ")\n";
473 os << "# " << featureBagger.m_Info << "\n";
474 }
475
476 CFeatureBagger::const_iterator it;
477 for (it = featureBagger.begin(); it != featureBagger.end(); it++)
478 {
479 os << "[" << (*it).GetBagName() << "]\n";
480 os << (*it);
481 }
482
483 return os;
484 }
485
487 // note: this method must be inlined because it uses istream in the parameter list
488 // note: May not be used as inline if called against a library where it is already compiled.
489 inline std::istream& operator >> (std::istream &is, CFeatureBagger &featureBagger)
490 {
491 if (is.eof())
492 {
493 throw RUNTIME_EXCEPTION("The stream is eof");
494 }
495
496 // Check the magic
498 GENICAM_NAMESPACE::getline( is, FirstLine, '\n' );
500 bool boCFeatureBagFormatDetected = false;
501 if( GENICAM_NAMESPACE::gcstring::_npos() == FirstLine.find(MagicGUID) )
502 {
504 if( GENICAM_NAMESPACE::gcstring::_npos() == FirstLine.find(MagicGUID) )
505 {
506 throw RUNTIME_EXCEPTION("The stream is not a GenApi feature stream since it is missing the magic GUID in the first line");
507 }
508 boCFeatureBagFormatDetected = true;
509 }
510
511 std::stringstream currentBagData;
512 if (boCFeatureBagFormatDetected)
513 {
514 currentBagData << FirstLine;
515 }
516 else
517 {
518 EatComments( is );
519 }
520
521 featureBagger.DeleteAllBags();
522 // Allow to digest the 'CFeatureBag' format using the 'CFeatureBagger' class!
523 CFeatureBag *pBag = boCFeatureBagFormatDetected ? &featureBagger.AddBag("All") : NULL;
524
525 while (!is.eof())
526 {
528 GENICAM_NAMESPACE::getline(is, line);
529 if (is.fail()) // if reading from stream failed -> stop reading!
530 {
531 break;
532 }
533 if (!line.empty() && (line[0] == '['))
534 {
535 if (!currentBagData.str().empty())
536 {
537 if (pBag)
538 {
539 currentBagData >> (*pBag);
540 }
541 currentBagData.str("");
542 currentBagData.clear();
543 pBag = NULL;
544 }
545 // this is the beginning of a new section
546 const size_t pos = line.find_first_of("]");
547 const GENICAM_NAMESPACE::gcstring bagName(line.substr(1, pos - 1));
548 if( !bagName.empty() )
549 {
550 pBag = &featureBagger.AddBag(bagName);
551 }
552 }
553 else
554 {
555 currentBagData << line << "\n";
556 }
557 }
558 if (!currentBagData.str().empty() && pBag)
559 {
560 currentBagData >> (*pBag);
561 }
562 return is;
563 }
564#endif // #ifndef GENAPI_DONT_USE_DEFAULT_PERSISTENCE_FILE_FORMAT
565}
566
567#endif //_GENICAM_PERSISTENCE_H
declspec's to be used for GenApi Windows dll
virtual IBoolean & operator=(bool Value)
Set node value.
Definition IBoolean.h:62
char * TrimSpace(char *Name, std::istream &is)
Helper function cutting off space characters.
Definition Persistence.h:188
virtual void PersistFeature(IValue &item, CSelectorSet *selectorSet=NULL)=0
Stores a feature.
std::istream & EatComments(std::istream &is)
Helper function ignoring lines starting with comment character '#'.
Definition Persistence.h:170
#define GENAPI_PERSISTENCE_MAGIC_FEATUREBAGGER
the magic GUID which indicates that the file is a GenApi stream file created by the CFeatureBagger cl...
Definition Persistence.h:166
#define GENAPI_PERSISTENCE_MAGIC
the magic GUID which indicates that the file or buffer is a GenApi stream created by the CFeatureBag ...
Definition Persistence.h:163
Definition of template CPointer.
Common types used in the public GenApi interface.
Bag holding streamable features of a nodetree.
Definition Persistence.h:56
bool operator==(const CFeatureBag &FeatureBag) const
compares the content of two feature bags
bool LoadFromBag(INodeMap *pNodeMap, bool Verify=true, GENICAM_NAMESPACE::gcstring_vector *pErrorList=NULL)
int64_t StoreToBag(INodeMap *pNodeMap, const int MaxNumPersistSkriptEntries=-1, GENICAM_NAMESPACE::gcstring_vector *pFeatureFilter=NULL)
Stores the streamable nodes to this feature bag.
virtual void PersistFeature(IValue &item, CSelectorSet *selectorSet=NULL)
Stores a feature.
virtual void SetInfo(const GENICAM_NAMESPACE::gcstring &Info)
sets information about the node map
Class use to bag features.
Definition Persistence.h:385
bool UnBag(INodeMap *pNodeMap, bool Verify=true, GENICAM_NAMESPACE::gcstring_vector *pErrorList=NULL)
size_t Bag(INodeMap *pNodeMap, bool handleDefaultNodeMap=true, bool handleUserSets=false, bool handleSequencerSets=false, const int MaxNumPersistSkriptEntries=-1)
Stores the streamable nodes to this feature bags in different device configurations.
virtual void SetInfo(const GENICAM_NAMESPACE::gcstring &Info)
sets information about the node map
Encapsulates a GenApi pointer dealing with the dynamic_cast automatically.
Definition Pointer.h:50
The set of selectors selecting a given node.
Definition SelectorSet.h:40
A string class which is a clone of std::string.
Definition GCString.h:51
#define RUNTIME_EXCEPTION
Fires a runtime exception, e.g. throw RUNTIME_EXCEPTION("buh!")
Definition GCException.h:246
std::istream & operator>>(std::istream &istr, GENICAM_NAMESPACE::gcstring &str)
Definition GCString.h:245
std::ostream & operator<<(std::ostream &ostr, const GENICAM_NAMESPACE::gcstring &str)
Definition GCString.h:229