// 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
typedef XMLReaderElement ConfigurationElement;
typedef XMLReaderAttribute ConfigurationAttribute;
typedef XMLReaderData ConfigurationData;
typedef XMLReaderTranslator ConfigurationTranslator;
typedef XMLReaderMnemonic ConfigurationMnemonic;
typedef XMLerator Configurator;
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