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 
41 namespace 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 
85  GENICAM_NAMESPACE::gcstring ToString();
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 
99  CFeatureBag();
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
187  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  }
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 
255  GENICAM_NAMESPACE::gcstring FirstLine;
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
464  // 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
497  GENICAM_NAMESPACE::gcstring FirstLine;
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
virtual void PersistFeature(IValue &item, CSelectorSet *selectorSet=NULL)=0
Stores a feature.
Common types used in the public GenApi interface.
Bag holding streamable features of a nodetree.
Definition: Persistence.h:55
std::istream & getline(std::istream &is, GENICAM_NAMESPACE::gcstring &str)
Definition: GCString.h:192
std::istream & EatComments(std::istream &is)
Helper function ignoring lines starting with comment character &#39;#&#39;.
Definition: Persistence.h:170
GENICAM_INTERFACE GENAPI_DECL_ABSTRACT IPersistScript
Basic interface to persist values to.
Definition: Persistence.h:46
char * TrimSpace(char *Name, std::istream &is)
Helper function cutting off space characters.
Definition: Persistence.h:188
#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 RUNTIME_EXCEPTION
Fires a runtime exception, e.g. throw RUNTIME_EXCEPTION("buh!")
Definition: GCException.h:246
The set of selectors selecting a given node.
Definition: SelectorSet.h:39
std::ostream & operator<<(std::ostream &ostr, const GENICAM_NAMESPACE::gcstring &str)
Definition: GCString.h:229
virtual IBoolean & operator=(bool Value)
Set node value.
Definition: IBoolean.h:62
Encapsulates a GenApi pointer dealing with the dynamic_cast automatically.
Definition: Pointer.h:49
std::istream & operator>>(std::istream &istr, GENICAM_NAMESPACE::gcstring &str)
Definition: GCString.h:245
Class use to bag features.
Definition: Persistence.h:384
GENICAM_INTERFACE INodeMap
Interface to access the node map.
Definition: INode.h:50
GENICAM_INTERFACE GENAPI_DECL_ABSTRACT IValue
Interface for value properties.
Definition: IValue.h:59
Definition of template CPointer.
A string class which is a clone of std::string.
Definition: GCString.h:50
declspec&#39;s to be used for GenApi Windows dll
Definition: ChunkAdapter.h:37
#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