Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

XMLLoadSave.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_XMLLoadSave_h_
00003 #define INCLUDED_XMLLoadSave_h_
00004 
00005 #include "LoadSave.h"
00006 
00007 /*! @cond INTERNAL */
00008 // libxml2 forward declarations
00009 extern "C" {
00010   struct _xmlNode;
00011   struct _xmlDoc;
00012   struct _xmlAttr;
00013   typedef _xmlNode xmlNode;
00014   typedef _xmlDoc xmlDoc;
00015   typedef _xmlAttr xmlAttr;
00016 }
00017 /*! @endcond */
00018 
00019 //! XMLLoadSave adds functions for XML format serialization, although if you write binary LoadSave functions as well, you can do either
00020 class XMLLoadSave : public virtual LoadSave {
00021 public:
00022   
00023   //! an exception to be thrown when a bad XML file is parsed, allows file position information to be passed to the user
00024   class bad_format : public std::exception {
00025   public:
00026     //!constructor
00027     bad_format(xmlNode * node) throw() : std::exception(), node_(node), msg_("invalid format in xml data") {}
00028     //!constructor
00029     bad_format(xmlNode * node, const std::string& msg) throw() : std::exception(), node_(node), msg_(msg) {}
00030     //!copy constructor
00031     bad_format(const bad_format& bf) : std::exception(bf), node_(bf.node_), msg_(bf.msg_) {}
00032     //!assignment
00033     bad_format& operator=(const bad_format& bf) { std::exception::operator=(bf); node_=bf.node_; msg_=bf.msg_; return *this; }
00034     virtual ~bad_format() throw() {} //!< destructor
00035     virtual const char * what() const throw() { return msg_.c_str(); } //!< standard interface for getting the exception's message string
00036     virtual xmlNode * getNode() const throw() { return node_; } //!< returns the xmlNode at which the error occurred
00037   protected:
00038     xmlNode * node_; //!< the node of the error
00039     std::string msg_; //!< message regarding the type of error
00040   };
00041   
00042   XMLLoadSave(); //!< constructor
00043   XMLLoadSave(const XMLLoadSave& xls); //!< copy constructor
00044   XMLLoadSave& operator=(const XMLLoadSave& xls); //!< assignment operator
00045   virtual ~XMLLoadSave(); //!< destructor
00046   
00047   //! This is called when the subclass needs to update its values from those values in the parse tree
00048   /*! @a node is the current node in the tree -- it may be the root, but it
00049    *  may also be a subnode within the tree if a recursive structure is used */
00050   virtual void loadXML(xmlNode* node)=0;
00051   //! This is called when XMLLoadSave needs to have the subclass update values in the tree currently in memory -- may already be filled out by previous contents
00052   /*! @a node is the current node in the tree -- it may be the root, but it
00053    *  may also be a subnode within the tree if a recursive structure is used */
00054   virtual void saveXML(xmlNode * node) const=0;
00055   
00056   virtual unsigned int getBinSize() const;
00057   virtual unsigned int loadBuffer(const char buf[], unsigned int len, const char* filename=NULL);
00058   virtual unsigned int saveBuffer(char buf[], unsigned int len) const;
00059 
00060   virtual unsigned int loadFile(const char* filename);
00061   virtual unsigned int saveFile(const char* filename) const;
00062   
00063   virtual unsigned int loadFileStream(FILE* f, const char* filename=NULL);
00064   virtual unsigned int saveFileStream(FILE* f) const;
00065 
00066   //! loads from a std::istream, optionally cleaning up stream to allow additional loads if @a asFragment is true
00067   virtual unsigned int loadStream(std::istream& is, bool asFragment=false);
00068   
00069   //! saves to a std::ostream, optionally skipping xml document header if @a asFragment is true
00070   virtual unsigned int saveStream(std::ostream& os, bool asFragment) const;
00071   virtual unsigned int saveStream(std::ostream& os) const { return saveStream(os,false); }
00072   
00073   //! resets the parse tree currently in memory so that a future save will write a "fresh" copy from scratch.
00074   /*! You may also want to call this in order to save memory after a Load so that
00075    *  the parse tree information isn't retained in memory if you don't care about
00076    *  retaining the file formatting */
00077   virtual void clearParseTree();
00078 
00079   //! assigns a parse tree which you have obtained from some other source
00080   /*! This doesn't update the contents of the subclass's values.  The values in
00081    *  @a doc will be overwritten by those in the subclass on the next Save.
00082    *  If you wish to have the subclass's values updated from @a doc, call
00083    *  readParseTree() after calling this. */
00084   virtual void setParseTree(xmlDoc* doc) const;
00085   
00086   //! returns the current parse tree, either from a previous Load, Save, or setParseTree()
00087   virtual xmlDoc* getParseTree() const { return xmldocument; }
00088   
00089   //! sets the object's parse tree to NULL and returns the former tree, which is then caller's responisibility
00090   virtual xmlDoc* stealParseTree(xmlDoc* newdoc=NULL) const;
00091   
00092   //! calls loadXML with the root of the current parse tree
00093   virtual void readParseTree();
00094   //! calls saveXML with the root of the current parse tree
00095   virtual void writeParseTree() const;
00096   
00097   //! allows you to set the compression level used by libxml2 -- this corresponds to the compression level setting of zlib, i.e. 0-9
00098   virtual void setCompression(int level);
00099   //! returns the current compression level setting used by libxml2 (via zlib)
00100   virtual int getCompression() const { return compressionLevel; }
00101   
00102 protected:
00103   //! returns the root element of the xml document
00104   virtual xmlNode* FindRootXMLElement(xmlDoc* doc) const;
00105 
00106   //! cleans up after an error occurs and sends a message to cerr
00107   void reportError(const std::string& context, const bad_format& err) const;
00108 
00109   //! called by libxml2 when it's ready for more data to be read from the source (in this case, a file)
00110   static int fileReadCallback(void* f,char* buf, int len);
00111   //! called by libxml2 when it's done reading data
00112   static int fileCloseCallback(void* f);
00113   
00114   //! returns the next element following @a cur
00115   /*! You should call this with node->next, otherwise you'll just keep getting the same node back again */
00116   static xmlNode* skipToElement(xmlNode* cur);
00117 
00118   //! returns the next element following @a cur; comment is set to the concatination of any comments is encountered in the interim
00119   /*! You should call this with node->next, otherwise you'll just keep getting the same node back again */
00120   static xmlNode* skipToElement(xmlNode* cur, std::string& comment);
00121 
00122   //! the cached xml parse tree -- contains additional formatting information such as white space and comments
00123   mutable xmlDoc* xmldocument;
00124 
00125   //! the current compression level, or level to be used for the next save
00126   int compressionLevel;
00127   
00128   //! if true, the saved document will use automatic indenting and formatting
00129   bool autoFormat;
00130 
00131   //static const char * const base64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00132   
00133   //! allows automatic (de)initialization of libxml when the first or last XMLLoadSave class is created or destroyed
00134   class AutoInit {
00135   public:
00136     AutoInit(); //!< if #libxmlrefc is 0, calls libxml2 initialization and configuration functions
00137     ~AutoInit(); //!< if #libxmlrefc is 1, calls libxml2 destruction functions
00138   protected:
00139     static unsigned int libxmlrefc; //!< current number of XMLLoadSave subclass instances
00140   } libxmlInit; //!< allows tracking of libxml usage so the library can be initialized and destructed automatically
00141   
00142 };
00143 
00144 /*! @file
00145  * @brief 
00146  * @author Ethan Tira-Thompson (ejt) (Creator)
00147  */
00148 
00149 #endif

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:53 2016 by Doxygen 1.6.3