// XMLReader.hpp // // (C) 2006 - 2009 MicroNeil Research Corporation. // See http://www.codedweller.com for details. // // This program is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the // Free Software Foundation; either version 2 of the License, or (at your // option) any later version. // // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for // more details. // // You should have received a copy of the GNU General Public License along with // this program; if not, write to the Free Software Foundation, Inc., 59 Temple // Place, Suite 330, Boston, MA 02111-1307 USA // // What about this ============================================================= // The XMLReader module provides a platform for reading configuration files // (or string data) containing well-formed xml and mapping that data to program // variables. // The idea is to provide the ability for an object or application to provide // a modular "XMLReader" object that models a hierarchical collection of // "settings" that can be represented easily in code and in xml. // // The following is an example model of a XMLReader in code and that same // XMLReader fully populated in xml. // // The code might look like this... // // int IntValue, DefaultInt = 3; // double DblValue, DefaultDbl = 3.14159; // bool BooleanValue, DefaultBool = false; // string StringValue, DefaultString = "NoStringHere"; // // SpecialConfigurator : public XMLReaderHandler { // Create a special handler to build a list // ... // public: // // XMLReaderHandler& Startup(XMLReaderElement& E) { // This function returns a handy handler to // return MyStartupXMLReaderHandler; // (re) initialize this handler ;-) // } // // void Operator()() { // Each time the configurator is called // ... // } // // int Attribute1; // these items are interpreted and added // double Attribute2; // to the list. A XMLReaderHandler COULD // string Attribute3; // do something entirely different though ;-) // string Contents; // ... // } Special; // // XMLReaderElement SampleConfig("SampleConfiguration"); // Define a sample config (doc element) // SampleConfig // Populate the SampleConfig // .atStartCall(Special.Startup()) // .Element("Integer", IntValue, DefaultInt).End() // Link an element to an int w/ default. // .Element("Double", DblValue, DefaultDbl).End("Double") // Link an element to a dbl w/ default. // .Element("String", StringValue, DefaultString).End("String") // Link an element to a string w/ default. // .Element("ComplexElements") // Create a sub element. // .Element("Complex1") // Sub element Complex1 has attributes. // .Attribute("IntAtt", IntValue, DefaultInt) // Complex1 has an integer attribute. // .Attribute("DblAtt", DblValue, DefaultDbl) // Complex1 has a dbl attribute. // .Element("IntAtt", IntValue).End() // IntAtt can also be set by a sub element. // .Element("DblAtt", DblValue).End() // DblAtt can also be set by a sub element. // .End() // That's it for Complex1. // .Element("Complex2") // Create the Complex2 sub element. // .Attribute("C2I", IntValue, DefaultInt) // C2I attribute. // .Attribute("C2D", DblValue) // C2D attribute - no default. // .Attribute("C2S", StringValue, DefultString) // C2S attribute - string w/ default. // .End("Complex2") // End of element throws if doesn't match. // .Element("Complex3", Special.Contents) // Element 3 using a special configurator. // .Attribute("A1", Special.Attribute1) // Set A1 and A2 and A3 and when the // .Attribute("A2", Special.Attribute2) // element has been completed, Special() // .Attribute("A3", Special.Attribute3) // will be called to record the entries. // .atEndCall(Special) // Here's where we register the handler. // .End() // Closing Complex3 to be ice. // .End() // Closing ComplexElements to be nice. // .End(); // Closing SampleConfiguration to be nice. // // The XML might look like this... // // // 10 // 2.4 // This is a sample string // // // 24 // // // stuff in here // Another instance // Each one gets passed to Special() on activation // This way, Special() can build a list or some other // interesting thing with all of these. // // // // Include This Header Once Only =============================================== #ifndef XMLReader_included #define XMLReader_included #include #include #include #include #include #include namespace CodeDweller { class XMLReaderElement; // Elements exist class XMLReaderAttribute; // Attributes exist class XMLReaderData; // Data exists class XMLReaderTranslator; // Translators exist class XMLReaderMnemonic; // Mnemonics exist class XMLerator; // XMLerators exist class XMLeratorSetTrueOnComplete; typedef XMLReaderElement ConfigurationElement; typedef XMLReaderAttribute ConfigurationAttribute; typedef XMLReaderData ConfigurationData; typedef XMLReaderTranslator ConfigurationTranslator; typedef XMLReaderMnemonic ConfigurationMnemonic; typedef XMLerator Configurator; typedef XMLeratorSetTrueOnComplete ConfiguratorSetTrueOnComplete; class RawTranslator { private: int *IndexAssignment = 0; int *EndexAssignment = 0; std::string *RawDataAssignment = 0; public: void setRawDataAssignment(std::string &RawData); void setIndexAssignment(int &Index, int &Endex); void translate(int Index, int Endex, XMLReaderData &Data); }; //// XMLReader Element ///////////////////////////////////////////////////// // // Elements make up the core of a configuration. That is, a configuration is a // tree of elements. Elements translate directly to well formed xml elements in // a configuration file or string. class XMLReaderElement { private: std::string myName; // Elements have a name. // External important things I remember but don't touch... XMLReaderElement* myParent; // They may have a parrent. std::list myStartXMLerators; // Call these when we start Interpret() std::list myEndXMLerators; // Call these when we finish Interpret() // Internal / subordinate things I own and kill... std::list myAttributes; // They may have a list of attributes. std::list myElements; // They may have a list of sub-elements. std::list myMnemonics; // They may have a list of mnemonics. std::list myTranslators; // They may have a list of translators. RawTranslator myRawTranslator; // Provides entire element. // During Interpret() operations we keep track of where we are seen... int myLine; // Last line number I was seen on. int myIndex; // Last char position I was seen on. int myEndex; // Last char of element. int myLength; // Last segment length. bool myCleanFlag; // Keep track of initialization. bool myInitOnInterpretFlag; // Initialize() at each Interpret()? void runStartXMLerators(XMLReaderData& D); // Does what it says ;-) void runEndXMLerators(XMLReaderData& D); // Does what it says ;-) public: XMLReaderElement(const char* Name); // Must be constructed with a name XMLReaderElement(const std::string Name); // either c string or c++ string. XMLReaderElement(const char* Name, XMLReaderElement& Parent); // Sub-elements are constructed with a XMLReaderElement(const std::string Name, XMLReaderElement& Parent); // parrent. // Upon desctruction an element will delete all subordinate objects: // * All sub element objects. // * All attribute objects. // * All mnemonic objects. // * All translator objects. // It is important to use new when passing one of these objects to an // element or attribute to prevent problems with the delete operation. // NORMALLY these things would be created using factory methods on the // element and attribute objects themselves - so be careful. // It will not delete XMLerators - they must // be deleted elsewhere because they may have been // re-used and this element wouldn't know about it ;-) ~XMLReaderElement(); // The descrutor clears and deletes all! // Elements can be probed for some simple, useful things. std::string Name(); // Get the name of this element. XMLReaderElement& Parent(); // Get the parent of this element. XMLReaderElement& Parent(XMLReaderElement& newParent); // Set the parent of this element. // Note - if there is no parent (an element is the root) then it will // return a reference to itself when Parent() is called. int Line(); // Get the last line number. int Index(); // Get the last data position. int Length(); // Get the last length. // Elements can contain either data or sub-elements. XMLReaderElement& Element(const char* Name); // Add a new sub element by c string name. XMLReaderElement& Element(const std::string Name); // Add a new sub element by c++ string name. //// Mapping element factory methods for convenience. //// Root-Node elements are _usually_ empty and without attributes in xml //// so we don't make any of that type of convenience constructor here. // char* versions XMLReaderElement& Element( // Mapping factory for convenience, const char* Name, // requires a name, of course, XMLReaderTranslator& newTranslator); // Add a Translator to this element. XMLReaderElement& Element( // Mapping factory for convenience, const char* Name, // requires a name, of course, std::string& x, std::string init = std::string("")); // Map to a string. XMLReaderElement& Element( // Mapping factory for convenience, const char* Name, // requires a name, of course, int& x, int init = 0, int radix = 0); // Map to an int. XMLReaderElement& Element( // Mapping factory for convenience, const char* Name, // requires a name, of course, double& x, double init = 0.0); // Map to a double. XMLReaderElement& Element( // Mapping factory for convenience, const char* Name, // requires a name, of course, bool& x, bool init = false); // Map to a boolean. // string versions XMLReaderElement& Element( // Mapping factory for convenience, const std::string Name, // requires a name, of course, XMLReaderTranslator& newTranslator); // Add a Translator to this element. XMLReaderElement& Element( // Mapping factory for convenience, const std::string Name, // requires a name, of course, std::string& x, std::string init = std::string("")); // Map to a string. XMLReaderElement& Element( // Mapping factory for convenience, const std::string Name, // requires a name, of course, int& x, int init = 0, int radix = 0); // Map to an int. XMLReaderElement& Element( // Mapping factory for convenience, const std::string Name, // requires a name, of course, double& x, double init = 0.0); // Map to a double. XMLReaderElement& Element( // Mapping factory for convenience, const std::string Name, // requires a name, of course, bool& x, bool init = false); // Map to a boolean. XMLReaderElement& RawData( // Copy entire element to std::string &Element); // a string. XMLReaderElement& RawIndex( // Copy indices of the entire int &Index, int &Endex); // element. // End methods for heading back up the tree at the end of an element. class EndNameDoesNotMatch {}; // Throw when End(name) doesn't match. XMLReaderElement& End(); // Return this element's parent. XMLReaderElement& End(const char* Name); // Check the name and return the parent XMLReaderElement& End(const std::string Name); // if the name is correct - or throw! // Elements can have attributes. XMLReaderAttribute& Attribute(const char* Name); // Add an attribute using a cstring. XMLReaderAttribute& Attribute(const std::string Name); // Add an attribute using a c++ string. //// Mapping Attribute factory methods for convenience. // char* versions XMLReaderAttribute& Attribute( // Mapping factory for convenience, const char* Name, // requires a name, of course, XMLReaderTranslator& newTranslator); // Add a Translator to this element. XMLReaderAttribute& Attribute( // Mapping factory for convenience, const char* Name, // requires a name, of course, std::string& x, std::string init = std::string("")); // Map to a string. XMLReaderAttribute& Attribute( // Mapping factory for convenience, const char* Name, // requires a name, of course, int& x, int init = 0, int radix = 0); // Map to an int. XMLReaderAttribute& Attribute( // Mapping factory for convenience, const char* Name, // requires a name, of course, double& x, double init = 0.0); // Map to a double. XMLReaderAttribute& Attribute( // Mapping factory for convenience, const char* Name, // requires a name, of course, bool& x, bool init = false); // Map to a boolean. // string versions XMLReaderAttribute& Attribute( // Mapping factory for convenience, const std::string Name, // requires a name, of course, XMLReaderTranslator& newTranslator); // Add a Translator to this element. XMLReaderAttribute& Attribute( // Mapping factory for convenience, const std::string Name, // requires a name, of course, std::string& x, std::string init = std::string("")); // Map to a string. XMLReaderAttribute& Attribute( // Mapping factory for convenience, const std::string Name, // requires a name, of course, int& x, int init = 0, int radix = 0); // Map to an int. XMLReaderAttribute& Attribute( // Mapping factory for convenience, const std::string Name, // requires a name, of course, double& x, double init = 0.0); // Map to a double. XMLReaderAttribute& Attribute( // Mapping factory for convenience, const std::string Name, // requires a name, of course, bool& x, bool init = false); // Map to a boolean. // Elements can Initialize() at each Interpret() call. XMLReaderElement& setInitOnInterpret(); // Set the init on interpret flag. // Elements can call external functions to aid in special operations // such as building lists. XMLReaderElement& atStartCall(XMLerator& Functor); // Add an atStart call-back to this element. XMLReaderElement& atEndCall(XMLerator& Functor); // Add an atEnd call-back to this element. // Extracting data from the element's contents is done with // translators. A good set of primatives are built in, but the user // can also make their own. If an Element is mapped to more than // one then they are all called once the element's contents are // collected. A translator takes the data provided by the element, // converts it into the expected type, and sets one or more variables // to the converted value. Usually - just one variable. XMLReaderElement& mapTo(XMLReaderTranslator& newTranslator); // Add a Translator to this element. XMLReaderElement& mapTo(std::string& x, std::string init = std::string("")); // Map to a string. XMLReaderElement& mapTo(int& x, int init = 0, int radix = 0); // Map to an int. XMLReaderElement& mapTo(double& x, double init = 0.0); // Map to a double. XMLReaderElement& mapTo(bool& x, bool init = false); // Map to a boolean. // An Element's contents may use some special mnemonics to make a // XMLReader easier to understand and less error prone. When the // contents match a mnemnoic then the translation of the mnemonic is // passed to the Translators instead of the raw contents. XMLReaderElement& Mnemonic(const char* name, const char* value); // Add a mnemonic using c strings. XMLReaderElement& Mnemonic(const char* name, const std::string value); // Add a mnemonic using c & c++ strings. XMLReaderElement& Mnemonic(const std::string name, const char* value); // Add a mnemonic using c++ & c strings. XMLReaderElement& Mnemonic(const std::string name, const std::string value); // Add a mnemonic using c++ strings. // The way data gets into an element tree is that it is Interpret()ed // recursively. The data is loaded into a XMLReaderData object which // is passed to the top Element. That element interpretes the data, moves // the interpretation pointers, and passes the data on to it's subordinate // elements in turn. They do the same recursively. When the last sub - // element has had it's way with the data, the interpretation process is // complete. The XMLReaderData object will contain the original data // and a log of anything that happened during the interpretation process. // // Each time an element is asked to Interpret() data, it calls any atStart // configurators, translates any attributes, then either translates it's // contents or passes the data to it's children, then calls any atEnd // configurators. // // To ensure that the correct default values are used the Initialize() is // always called on all internal attributes and elements before any data is // interpreted. To prevent this from being inefficient, a boolean flag is // kept in each element to keep track of whether it is clean and if it is // then the call to Initialize will simply return (skipping subordinate // elements along the way). // // Interpret returns true if this object found itself at the current // Data.Index and false if not. This helps keep the recursive parsing // code simpler ;-) void initialize(); // Reset all translators to defaults. void notifyDirty(); // Set dirty (if translators change). bool interpret(XMLReaderData& Data); // (re) Interpret this data. }; //// XMLReader Attribute /////////////////////////////////////////////////// // // Attributes translate directly to well formed xml attributes (within the // start tag of an element). class XMLReaderAttribute { private: std::string myName; // Elements have a name. XMLReaderElement& myParent; // They may have a parrent. std::list myMnemonics; // They may have a list of mnemonics. std::list myTranslators; // They may have a list of translators. int myLine; // Last line number I was seen on. int myIndex; // Last char position I was seen on. int myLength; // Last segment length. public: XMLReaderAttribute(const char* Name, XMLReaderElement& Parent); // Sub-elements are constructed with a XMLReaderAttribute(const std::string Name, XMLReaderElement& Parent); // parrent. // Attributes delete their Mnemonics and Translators when they go. // See Elements for similar warnings about objects provided to // this object... you must use new to be safe, or better yet - stick to // the built in factory methods ;-) ~XMLReaderAttribute(); // Crush, Kill, Destroy! // Attributes can be probed for some simple, useful things. std::string Name(); // Get the name of this attribute. XMLReaderElement& Parent(); // Get the parent of this attribute. int Line(); // Get the last line number. int Index(); // Get the last data position. int Length(); // Get the last length. void notifyDirty(); // Attributes use this when they change. // For convenience in building configurations, an Attribute offers // some call-through methods to it's parrent Element. This allows for // clear, concise .method() coding that mimics an outline of the // configuration structure. //// For switching back to the parent element and adding new sub-elements. XMLReaderElement& Element(const char* Name); // Add a new sub element by c string name. XMLReaderElement& Element(const std::string Name); // Add a new sub element by c++ string name. //// Mapping element factory methods for convenience. //// Root-Node elements are _usually_ empty and without attributes in xml //// so we don't make any of that type of convenience constructor here. // char* versions XMLReaderElement& Element( // Mapping factory for convenience, const char* Name, // requires a name, of course, XMLReaderTranslator& newTranslator); // Add a Translator to this element. XMLReaderElement& Element( // Mapping factory for convenience, const char* Name, // requires a name, of course, std::string& x, std::string init = std::string("")); // Map to a string. XMLReaderElement& Element( // Mapping factory for convenience, const char* Name, // requires a name, of course, int& x, int init = 0, int radix = 0); // Map to an int. XMLReaderElement& Element( // Mapping factory for convenience, const char* Name, // requires a name, of course, double& x, double init = 0.0); // Map to a double. XMLReaderElement& Element( // Mapping factory for convenience, const char* Name, // requires a name, of course, bool& x, bool init = false); // Map to a boolean. // string versions XMLReaderElement& Element( // Mapping factory for convenience, const std::string Name, // requires a name, of course, XMLReaderTranslator& newTranslator); // Add a Translator to this element. XMLReaderElement& Element( // Mapping factory for convenience, const std::string Name, // requires a name, of course, std::string& x, std::string init = std::string("")); // Map to a string. XMLReaderElement& Element( // Mapping factory for convenience, const std::string Name, // requires a name, of course, int& x, int init = 0, int radix = 0); // Map to an int. XMLReaderElement& Element( // Mapping factory for convenience, const std::string Name, // requires a name, of course, double& x, double init = 0.0); // Map to a double. XMLReaderElement& Element( // Mapping factory for convenience, const std::string Name, // requires a name, of course, bool& x, bool init = false); // Map to a boolean. // End methods for heading back up the tree at the end of an element. XMLReaderElement& End(); // Return this element's parent. XMLReaderElement& End(const char* Name); // Check the name and return the parent XMLReaderElement& End(const std::string Name); // if the name is correct - or throw! //// For adding new attributes to the parent element. XMLReaderAttribute& Attribute(const char* Name); // Add an attribute using a cstring. XMLReaderAttribute& Attribute(const std::string Name); // Add an attribute using a c++ string. //// Mapping Attribute factory methods for convenience. // char* versions XMLReaderAttribute& Attribute( // Mapping factory for convenience, const char* Name, // requires a name, of course, XMLReaderTranslator& newTranslator); // Add a Translator to this element. XMLReaderAttribute& Attribute( // Mapping factory for convenience, const char* Name, // requires a name, of course, std::string& x, std::string init = std::string("")); // Map to a string. XMLReaderAttribute& Attribute( // Mapping factory for convenience, const char* Name, // requires a name, of course, int& x, int init = 0, int radix = 0); // Map to an int. XMLReaderAttribute& Attribute( // Mapping factory for convenience, const char* Name, // requires a name, of course, double& x, double init = 0.0); // Map to a double. XMLReaderAttribute& Attribute( // Mapping factory for convenience, const char* Name, // requires a name, of course, bool& x, bool init = false); // Map to a boolean. // string versions XMLReaderAttribute& Attribute( // Mapping factory for convenience, const std::string Name, // requires a name, of course, XMLReaderTranslator& newTranslator); // Add a Translator to this element. XMLReaderAttribute& Attribute( // Mapping factory for convenience, const std::string Name, // requires a name, of course, std::string& x, std::string init = std::string("")); // Map to a string. XMLReaderAttribute& Attribute( // Mapping factory for convenience, const std::string Name, // requires a name, of course, int& x, int init = 0, int radix = 0); // Map to an int. XMLReaderAttribute& Attribute( // Mapping factory for convenience, const std::string Name, // requires a name, of course, double& x, double init = 0.0); // Map to a double. XMLReaderAttribute& Attribute( // Mapping factory for convenience, const std::string Name, // requires a name, of course, bool& x, bool init = false); // Map to a boolean. //// Set Init On Interprete for the parent element. XMLReaderElement& setInitOnInterpret(); // Set the init on interpret flag. //// For adding configurators to the parent element. XMLReaderElement& atStartCall(XMLerator& Functor); // Add an atStart call-back to this element. XMLReaderElement& atEndCall(XMLerator& Functor); // Add an atEnd call-back to this element. // Of course, the most useful thing about attributes is that they can // be mapped to variables using translators. The same as those that // apply to the parent element's contents. Here they are for use on this // attribute. XMLReaderAttribute& mapTo(XMLReaderTranslator& newTranslator); // Add a Translator to this attribute. XMLReaderAttribute& mapTo(std::string& x, std::string init = std::string("")); // Map to a string. XMLReaderAttribute& mapTo(int& x, int init, int radix = 0); // Map to an int. XMLReaderAttribute& mapTo(double& x, double init = 0.0); // Map to a double. XMLReaderAttribute& mapTo(bool& x, bool init = false); // Map to a boolean. // Attributes can have mnemonics just like elements. XMLReaderAttribute& Mnemonic(const char* name, const char* value); // Add a mnemonic using a c string. XMLReaderAttribute& Mnemonic(const char* name, const std::string value); // Add a mnemonic using c & c++ strings. XMLReaderAttribute& Mnemonic(const std::string name, const char* value); // Add a mnemonic using c++ & c strings. XMLReaderAttribute& Mnemonic(const std::string name, const std::string value); // Add a mnemonic using a c++ string. // Attributes participate in the Interprete() task just like elements. void initialize(); // Reset all translators to defaults. bool interpret(XMLReaderData& Data); // (re) Interpret this data. }; //// XMLReader Data //////////////////////////////////////////////////////// // // A XMLReaderData object holds on to the configuration source data and // provideds a place to log any information about how the configuration was // interpreted. It also creates and destroys a handy char[] to contain the // data. To make this beastie easier to handle, we use the Named Constructor // Idiom and hide the true constructor in the private section. class XMLReaderData { // XMLReader Data Source private: char* myDataBuffer; // The actual data buffer. int myBufferSize; // Size of the current buffer. int myIndex; // The current interpretation index. int myLine; // Current line number. public: XMLReaderData(const char* FileName); // Constructor from c string file name. XMLReaderData(const std::string FileName); // Constructor from c++ string file name. XMLReaderData(const char* Data, int Length); // Raw constructor from text buffer. ~XMLReaderData(); // Destroys the internal buffer etc. char Data(int Index); // Returns char from Data[Index] int Index(); // Reads the current Index. int Index(int i); // Changes the current Index. int Line(); // Reads the current Line number. int addNewLines(int Count); // Increments the Line number. std::string extract(int Index, int Endex) const ; // Return substring of buffer. std::stringstream Log; // Convenient Interpret log. }; //// XMLReader Translator ////////////////////////////////////////////////// // // A Translator converts the contents provided to it in string form into some // other data type. The object here is a prototype for that, followed by a // collection of the basic translators used for built-in mapTo()s. class XMLReaderTranslator { // Translators exist public: virtual ~XMLReaderTranslator(){}; // Stop No Virt Dtor warnings. virtual void translate(const char* Value) = 0; // Pure virtual translator. virtual void initialize() = 0; // Pure virtual initializer. }; class StringTranslator : public XMLReaderTranslator { private: std::string& myVariable; // Variable to map. std::string myInitializer; // Initial/Default value. public: StringTranslator( // Construct this with std::string& Variable, // the variable to map, std::string Inititializer); // and the default value. void translate(const char* Value); // Provide a translation method. void initialize(); // Provide an initialization method. }; class IntegerTranslator : public XMLReaderTranslator { private: int& myVariable; // Variable to map. int myInitializer; // Initial/Default value. int myRadix; // Radix for strtol() public: IntegerTranslator( // Construct this with int& Variable, // the variable to map, int Inititializer, // and the default value. int Radix); // For this one we also need a Radix. void translate(const char* Value); // Provide a translation method. void initialize(); // Provide an initialization method. }; class DoubleTranslator : public XMLReaderTranslator { private: double& myVariable; // Variable to map. double myInitializer; // Initial/Default value. public: DoubleTranslator( // Construct this with double& Variable, // the variable to map, double Inititializer); // and the default value. void translate(const char* Value); // Provide a translation method. void initialize(); // Provide an initialization method. }; class BoolTranslator : public XMLReaderTranslator { private: bool& myVariable; // Variable to map. bool myInitializer; // Initial/Default value. public: BoolTranslator( // Construct this with bool& Variable, // the variable to map, bool Inititializer); // and the default value. void translate(const char* Value); // Provide a translation method. void initialize(); // Provide an initialization method. }; //// XMLReader Mnemonic //////////////////////////////////////////////////// // // A Mnemonic allows the actual contents of an element or attribute to be // exchanged for a different "named" value to help eliminate "magic numbers" // and "secret codes" from configurations. One way this might be used is to // map an enumeration to the appropriate integer values, or things like YES and // NO to boolean true and false (respectively) when turning on/off program // options. class XMLReaderMnemonic { // Mnemonics private: std::string myName; // What is the Mnemonic? std::string myValue; // What is the translation? public: XMLReaderMnemonic(std::string Name, std::string Value); // To make one, provide both parts. bool test(std::string Name); // Test to see if this Mnemonic matches. std::string Value(); // If it does then we will need it's value. }; //// XMLerator ////////////////////////////////////////////////////////////// // // An XMLerator is a "functor" or "closure" or "callback" that can be used to // support sophisticated interpretation options. The most basic and necessary // of these is support for list building. Consider an object created to contain // a list of records where each record might be represented as a collection of // attributes and elements. The object would have data elements mapped to the // attributes and elements in the configuration and then control elements which // are functors for initializing the list and storing new entries as they are // completed. The object here is a pure virtual prototype. class XMLerator { // XMLerators exist public: virtual void operator()(XMLReaderElement& E, XMLReaderData& D) = 0; // Pure virtual configurator. virtual ~XMLerator() {} // Virtual dtor keeps warnings away. }; //// Include our inline methods //////////////////////////////////////////////// #include "XMLReader.inline.hpp" //// Utilities ///////////////////////////////////////////////////////////////// // SetTrueOnComplete XMLerator ////////////////////////////////////////////// class XMLeratorSetTrueOnComplete : public XMLerator { // XMLerator set's a boolean true. private: bool* myBoolean; // The boolean to set. public: XMLeratorSetTrueOnComplete(); // Must init to NULL for safety. void setup(bool& Target); // Link to the target boolean. void operator()(XMLReaderElement& E, XMLReaderData& D); // Handle the operation. }; } #endif // End Of Include Only Once