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

Tekkotsu v2.4.1
Generated Tue Aug 16 16:32:50 2005 by Doxygen 1.4.4