Persistence.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. //-----------------------------------------------------------------------------
  2. // (c) 2007 by National Instruments
  3. // Project: GenApi
  4. // Author: Eric Gross
  5. // $Header$
  6. //
  7. // License: This file is published under the license of the EMVA GenICam Standard Group.
  8. // A text file describing the legal terms is included in your installation as 'GenICam_license.pdf'.
  9. // If for some reason you are missing this file please contact the EMVA or visit the website
  10. // (http://www.genicam.org) for a full copy.
  11. //
  12. // THIS SOFTWARE IS PROVIDED BY THE EMVA GENICAM STANDARD GROUP "AS IS"
  13. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  14. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  15. // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE EMVA GENICAM STANDARD GROUP
  16. // OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  17. // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  18. // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  19. // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  20. // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  21. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  22. // POSSIBILITY OF SUCH DAMAGE.
  23. //-----------------------------------------------------------------------------
  24. /*!
  25. \file
  26. \brief Definition of interface IPersistScript and class CFeatureBag
  27. \ingroup GenApi_PublicUtilities
  28. */
  29. #ifndef _GENICAM_PERSISTENCE_H
  30. #define _GENICAM_PERSISTENCE_H
  31. #include <GenApi/Types.h>
  32. #include <GenApi/Pointer.h>
  33. #include <GenApi/GenApiDll.h>
  34. #include <list>
  35. #include <iostream>
  36. namespace GENAPI_NAMESPACE
  37. {
  38. //! Basic interface to persist values to
  39. interface GENAPI_DECL_ABSTRACT IPersistScript
  40. {
  41. //! sets information about the node map
  42. virtual void SetInfo(const GENICAM_NAMESPACE::gcstring &Info) = 0;
  43. //! Stores a feature
  44. virtual void PersistFeature(IValue& item) = 0;
  45. };
  46. //! Bag holding streamable features of a nodetree
  47. class GENAPI_DECL CFeatureBag : public IPersistScript
  48. {
  49. public:
  50. //! sets information about the node map
  51. virtual void SetInfo(const GENICAM_NAMESPACE::gcstring &Info);
  52. //! Stores a feature
  53. virtual void PersistFeature(IValue& item);
  54. //! Loads the features from the bag to the node tree
  55. //! \param pNodeMap The node map to load into
  56. //! \param Verify If true, all streamable features are read back
  57. //! \param pErrorList If an error occurs during loading the error message is stored in the list and the loading continues
  58. /*! For Verify=true the list of names in the feature bag is replayed again.
  59. If a node is a selector it's value is set to the value from the feature bag
  60. If not the value is read from the camera and compared with the value from the feature bag.
  61. */
  62. bool LoadFromBag(INodeMap *pNodeMap, bool Verify = true, GENICAM_NAMESPACE::gcstring_vector *pErrorList = NULL);
  63. /*! \brief Stores the streamable nodes to this feature bag
  64. \param pNodeMap The node map to persist
  65. \param MaxNumPersistSkriptEntries The max number of entries in the container; -1 means unlimited
  66. \param pFeatureFilter List of valid feature; all feature if NULL.
  67. \return number of entries in the bag
  68. */
  69. int64_t StoreToBag(INodeMap *pNodeMap, const int MaxNumPersistSkriptEntries = -1, GENICAM_NAMESPACE::gcstring_vector *pFeatureFilter = NULL);
  70. //! compares the content of two feature bags
  71. bool operator==(const CFeatureBag &FeatureBag) const;
  72. GENICAM_NAMESPACE::gcstring ToString();
  73. virtual void Destroy();
  74. virtual const GENICAM_NAMESPACE::gcstring& GetBagName( void ) const;
  75. virtual void SetBagName(const GENICAM_NAMESPACE::gcstring& bagName);
  76. //! fills the bag from a stream
  77. friend std::istream& operator >>(std::istream &is, CFeatureBag &FeatureBag);
  78. //! puts the bag into a stream
  79. friend std::ostream& operator <<(std::ostream &os, const CFeatureBag &FeatureBag);
  80. private:
  81. //! The name of the feature bag
  82. GENICAM_NAMESPACE::gcstring m_BagName;
  83. GENICAM_NAMESPACE::gcstring_vector m_Names;
  84. GENICAM_NAMESPACE::gcstring_vector m_Values;
  85. //! String describing the node map
  86. GENICAM_NAMESPACE::gcstring m_Info;
  87. bool LoadFromBagInternal(INodeMap *pNodeMap, bool Verify /* = true */, GENICAM_NAMESPACE::gcstring_vector *pErrorList = NULL);
  88. int64_t StoreToBagInternal(INodeMap *pNodeMap, const int MaxNumPersistSkriptEntries = -1, GENICAM_NAMESPACE::gcstring_vector *pFeatureFilter = NULL);
  89. friend class CFeatureBagger;
  90. };
  91. //! the magic GUID which indicates that the file or buffer is a GenApi stream created by the CFeatureBag class. Must be the first entry of a file or section.
  92. #define GENAPI_PERSISTENCE_MAGIC "{05D8C294-F295-4dfb-9D01-096BD04049F4}"
  93. //! the magic GUID which indicates that the file is a GenApi stream file created by the CFeatureBagger class. Must be the first entry of a file.
  94. #define GENAPI_PERSISTENCE_MAGIC_FEATUREBAGGER "{4709CB3C-7322-4460-84C3-DA11DDA09939}"
  95. //! Helper function ignoring lines starting with comment character '#'
  96. // note: this method must be inlined because it uses istream in the parameter list
  97. inline std::istream& EatComments(std::istream &is)
  98. {
  99. if( is.eof() )
  100. {
  101. return is;
  102. }
  103. char FirstCharacter = static_cast<char>(is.peek());
  104. while( FirstCharacter == '#' )
  105. {
  106. is.ignore(1024, '\n');
  107. FirstCharacter = static_cast<char>(is.peek());
  108. }
  109. return is;
  110. }
  111. #ifndef GENAPI_DONT_USE_DEFAULT_PERSISTENCE_FILE_FORMAT
  112. //! reads in persistent data from a stream
  113. // note: this method must be inlined because it uses istream in the parameter list
  114. // note: May not be used as inline if called against a library where it is already compiled.
  115. inline std::istream& operator >>(std::istream &is, CFeatureBag &FeatureBag)
  116. {
  117. if( is.eof() )
  118. {
  119. throw RUNTIME_EXCEPTION("The stream is eof");
  120. }
  121. FeatureBag.m_Names.clear();
  122. FeatureBag.m_Values.clear();
  123. const int BufferSize = 1024;
  124. char Buffer[BufferSize] = {0};
  125. // Check the magic
  126. is.getline(Buffer, BufferSize, '\n');
  127. GENICAM_NAMESPACE::gcstring FirstLine(Buffer);
  128. GENICAM_NAMESPACE::gcstring MagicGUID(GENAPI_PERSISTENCE_MAGIC);
  129. if( GENICAM_NAMESPACE::gcstring::_npos() == FirstLine.find(MagicGUID) )
  130. {
  131. MagicGUID = GENICAM_NAMESPACE::gcstring(GENAPI_PERSISTENCE_MAGIC_FEATUREBAGGER);
  132. if( GENICAM_NAMESPACE::gcstring::_npos() == FirstLine.find(MagicGUID) )
  133. {
  134. throw RUNTIME_EXCEPTION("The stream is not a GenApi feature stream since it is missing the magic GUID in the first line");
  135. }
  136. throw RUNTIME_EXCEPTION("The stream has been created using the CFeatureBagger class thus must be restored using the CFeatureBagger class as well");
  137. }
  138. EatComments( is );
  139. char Name[BufferSize] = {0};
  140. GENICAM_NAMESPACE::gcstring Value("");
  141. while( !is.eof() )
  142. {
  143. is.getline(Name, BufferSize, '\t');
  144. if (is.fail()) // if reading from stream failed -> stop reading!
  145. {
  146. break;
  147. }
  148. GENICAM_NAMESPACE::getline(is, Value);
  149. if (is.fail()) // if reading from stream failed -> stop reading!
  150. {
  151. break;
  152. }
  153. FeatureBag.m_Names.push_back(Name);
  154. FeatureBag.m_Values.push_back(Value);
  155. Name[0] = '\0';
  156. Value = "";
  157. EatComments( is );
  158. }
  159. return is;
  160. }
  161. //! writes out persistent data to a stream
  162. // note: this method must be inlined because it uses ostream in the parameter list
  163. // note: May not be used as inline if called against a library where it is already compiled.
  164. inline std::ostream& operator <<(std::ostream &os, const CFeatureBag &FeatureBag)
  165. {
  166. os << "# " GENAPI_PERSISTENCE_MAGIC "\n";
  167. if( !FeatureBag.m_Info.empty() )
  168. {
  169. os << "# GenApi persistence file (version " << GENAPI_VERSION_MAJOR << "." << GENAPI_VERSION_MINOR << "." << GENAPI_VERSION_SUBMINOR << ")\n";
  170. os << "# " << FeatureBag.m_Info << "\n";
  171. }
  172. // This can actually never happen the way the code is written right now, but...
  173. assert(FeatureBag.m_Names.size() == FeatureBag.m_Values.size());
  174. GENICAM_NAMESPACE::gcstring_vector::const_iterator pName = FeatureBag.m_Names.begin();
  175. GENICAM_NAMESPACE::gcstring_vector::const_iterator pValue = FeatureBag.m_Values.begin();
  176. const GENICAM_NAMESPACE::gcstring_vector::const_iterator endNames = FeatureBag.m_Names.end();
  177. for( ; pName != endNames; ++pName, ++pValue )
  178. {
  179. const GENICAM_NAMESPACE::gcstring Name(*pName);
  180. const GENICAM_NAMESPACE::gcstring Value(*pValue);
  181. os << Name << "\t" << Value << "\n";
  182. }
  183. return os;
  184. }
  185. #endif // #ifndef GENAPI_DONT_USE_DEFAULT_PERSISTENCE_FILE_FORMAT
  186. //! Class use to bag features
  187. class GENAPI_DECL CFeatureBagger
  188. {
  189. public:
  190. class GENAPI_DECL const_iterator
  191. {
  192. // Ctor / Dtor
  193. // -------------------------------------------------------------------------
  194. public:
  195. const_iterator(CFeatureBag **ppBag = NULL);
  196. // Operators
  197. // -------------------------------------------------------------------------
  198. public:
  199. const CFeatureBag & operator * (void) const;
  200. const CFeatureBag * operator -> (void) const;
  201. const_iterator & operator ++ (void);
  202. const_iterator operator ++ (int);
  203. const_iterator & operator += (intptr_t iInc);
  204. const_iterator operator + (intptr_t iInc) const;
  205. intptr_t operator - (const const_iterator &iter) const;
  206. bool operator == (const const_iterator &iter) const;
  207. bool operator != (const const_iterator &iter) const;
  208. // Member
  209. // -------------------------------------------------------------------------
  210. protected:
  211. CFeatureBag **_ppb;
  212. };
  213. explicit CFeatureBagger();
  214. virtual ~CFeatureBagger();
  215. /*! \brief Stores the streamable nodes to this feature bags in different device configurations
  216. \param handleDefaultNodeMap Stores the current nodemap if True
  217. \param handleUserSets Store all user sets if True
  218. \param handleSequencerSets Store all sequencer sets if True
  219. \param pNodeMap The node map to persist
  220. \param MaxNumPersistSkriptEntries The max number of entries in the container. -1 means unlimited
  221. \return number of bags
  222. */
  223. size_t Bag(INodeMap *pNodeMap, bool handleDefaultNodeMap = true, bool handleUserSets = false, bool handleSequencerSets = false, const int MaxNumPersistSkriptEntries = -1);
  224. //! Loads the features from the bag to the node tree
  225. //! \param Verify If true, all streamable features are read back
  226. //! \param pErrorList If an error occurs during loading the error message is stored in the list and the loading continues
  227. /*! For Verify=true the list of names in the feature bag is replayed again.
  228. If a node is a selector it's value is set to the value from the feature bag
  229. If not the value is read from the camera and compared with the value from the feature bag.
  230. */
  231. bool UnBag(INodeMap *pNodeMap, bool Verify = true, GENICAM_NAMESPACE::gcstring_vector *pErrorList = NULL);
  232. //! sets information about the node map
  233. virtual void SetInfo(const GENICAM_NAMESPACE::gcstring &Info);
  234. // Element access
  235. // ---------------------------------------------------------------------------
  236. virtual const_iterator begin(void) const;
  237. virtual const_iterator end(void) const;
  238. virtual const CFeatureBag& at(size_t uiIndex) const;
  239. virtual size_t size(void) const;
  240. //! puts the bags into a stream
  241. friend std::ostream& operator <<(std::ostream &os, const CFeatureBagger &featureBagger);
  242. //! reads the bags from a stream
  243. friend std::istream& operator >>(std::istream &is, CFeatureBagger &featureBagger);
  244. private:
  245. CFeatureBag& AddBag(const GENICAM_NAMESPACE::gcstring &bagName);
  246. void DeleteAllBags( void );
  247. template<class _Ty>
  248. void UnBagCustomAction(INodeMap *pNodeMap, _Ty setNodePtr, const GENICAM_NAMESPACE::gcstring& setNodeValue, CCommandPtr saveNodePtr );
  249. void *m_pBags;
  250. //! String describing the node map
  251. GENICAM_NAMESPACE::gcstring m_Info;
  252. };
  253. #ifndef GENAPI_DONT_USE_DEFAULT_PERSISTENCE_FILE_FORMAT
  254. //! writes out persistent data to a stream
  255. // note: this method must be inlined because it uses ostream in the parameter list
  256. // note: May not be used as inline if called against a library where it is already compiled.
  257. inline std::ostream& operator <<(std::ostream &os, const CFeatureBagger &featureBagger)
  258. {
  259. os << "# " GENAPI_PERSISTENCE_MAGIC_FEATUREBAGGER "\n";
  260. if( !featureBagger.m_Info.empty() )
  261. {
  262. os << "# GenApi CFeatureBagger persistence file (version " << GENAPI_VERSION_MAJOR << "." << GENAPI_VERSION_MINOR << "." << GENAPI_VERSION_SUBMINOR << ")\n";
  263. os << "# " << featureBagger.m_Info << "\n";
  264. }
  265. CFeatureBagger::const_iterator it;
  266. for (it = featureBagger.begin(); it != featureBagger.end(); it++)
  267. {
  268. os << "[" << (*it).GetBagName() << "]\n";
  269. os << (*it);
  270. }
  271. return os;
  272. }
  273. //! reads back persistent data from a stream
  274. // note: this method must be inlined because it uses istream in the parameter list
  275. // note: May not be used as inline if called against a library where it is already compiled.
  276. inline std::istream& operator >> (std::istream &is, CFeatureBagger &featureBagger)
  277. {
  278. if (is.eof())
  279. {
  280. throw RUNTIME_EXCEPTION("The stream is eof");
  281. }
  282. // Check the magic
  283. const int BufferSize = 1024;
  284. char Buffer[BufferSize] = { 0 };
  285. is.getline(Buffer, BufferSize, '\n');
  286. GENICAM_NAMESPACE::gcstring FirstLine(Buffer);
  287. GENICAM_NAMESPACE::gcstring MagicGUID(GENAPI_PERSISTENCE_MAGIC_FEATUREBAGGER);
  288. bool boCFeatureBagFormatDetected = false;
  289. if( GENICAM_NAMESPACE::gcstring::_npos() == FirstLine.find(MagicGUID) )
  290. {
  291. MagicGUID = GENICAM_NAMESPACE::gcstring(GENAPI_PERSISTENCE_MAGIC);
  292. if( GENICAM_NAMESPACE::gcstring::_npos() == FirstLine.find(MagicGUID) )
  293. {
  294. throw RUNTIME_EXCEPTION("The stream is not a GenApi feature stream since it is missing the magic GUID in the first line");
  295. }
  296. boCFeatureBagFormatDetected = true;
  297. }
  298. std::stringstream currentBagData;
  299. if (boCFeatureBagFormatDetected)
  300. {
  301. currentBagData << FirstLine;
  302. }
  303. else
  304. {
  305. EatComments( is );
  306. }
  307. featureBagger.DeleteAllBags();
  308. // Allow to digest the 'CFeatureBag' format using the 'CFeatureBagger' class!
  309. CFeatureBag *pBag = boCFeatureBagFormatDetected ? &featureBagger.AddBag("All") : NULL;
  310. while (!is.eof())
  311. {
  312. GENICAM_NAMESPACE::gcstring line;
  313. GENICAM_NAMESPACE::getline(is, line);
  314. if (is.fail()) // if reading from stream failed -> stop reading!
  315. {
  316. break;
  317. }
  318. if (!line.empty() && (line[0] == '['))
  319. {
  320. if (!currentBagData.str().empty())
  321. {
  322. if (pBag)
  323. {
  324. currentBagData >> (*pBag);
  325. }
  326. currentBagData.str("");
  327. currentBagData.clear();
  328. pBag = NULL;
  329. }
  330. // this is the beginning of a new section
  331. const size_t pos = line.find_first_of("]");
  332. const GENICAM_NAMESPACE::gcstring bagName(line.substr(1, pos - 1));
  333. if( !bagName.empty() )
  334. {
  335. pBag = &featureBagger.AddBag(bagName);
  336. }
  337. }
  338. else
  339. {
  340. currentBagData << line << "\n";
  341. }
  342. }
  343. if (!currentBagData.str().empty() && pBag)
  344. {
  345. currentBagData >> (*pBag);
  346. }
  347. return is;
  348. }
  349. #endif // #ifndef GENAPI_DONT_USE_DEFAULT_PERSISTENCE_FILE_FORMAT
  350. }
  351. #endif //_GENICAM_PERSISTENCE_H