// configuration.cpp
//
// (C) 2006 - 2009 MicroNeil Research Corporation.
//
// This program is part of the MicroNeil Research Open Library Project. For
// more information go to http://www.microneil.com/OpenLibrary/index.html
//
// 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

// See configuration.hpp for details

#include "configuration.hpp"

using namespace std;

//// Helper functions //////////////////////////////////////////////////////////

// isNameChar(const char x)
// true if the character can be used in a name.

bool isNameChar(const char x) {
    return (
      isalnum(x) ||
      ('.' == x) ||
      ('-' == x) ||
      ('_' == x) ||
      (':' == x)
    );
}

// Eat Spaces and Count Lines
// While we're parsing the configuration file there are times we will need to
// skip some amount of whitespace. While doing that we need to keep track of
// any new-lines we cross so that we always know what line number we are on.
// This function makes that work a one-liner in our parsing routines.

int eatSpacesCountLines(ConfigurationData& Data, int& Index) {                  // Eat spaces and count lines.
    int LineCount = 0;                                                          // Keep the line count here.
    char C = 0;                                                                 // Keep the current character here.

    for(;;) {                                                                   // We'll be looping like this...
        C = Data.Data(Index);                                                   // Grab the character at the Index.
        if(0 == C) {                                                            // If we have run out of data
            break;                                                              // then we are certainly done.
        }
        if(isspace(C)) {                                                        // If it is a whitespace
            if('\n' == C) {                                                     // check to see if it's a new line
                ++LineCount;                                                    // and count it if it is.
            }                                                                   // Since it was a space in any case
            ++Index;                                                            // move the index past it.
        } else {                                                                // As soon as we hit something not
            break;                                                              // a whitespace we are done looping.
        }
    }
    return LineCount;                                                           // In the end return the line count.
}

// Eat NonTagText Count Lines
// This is a variation on the Eat Spaces theme except that it is used in an
// element to bypass any floating text or spaces that might be in the file. In
// a perfect world such a thing would not exist -- but just in case it does we
// want to handle it gracefully. This function will get us to the first < that
// we can find - presumably the opening tag of an element.

int eatNonTagTextCountLines(ConfigurationData& Data, int& Index) {              // Eat "stuff" and count lines.
    int LineCount = 0;                                                          // Keep the line count here.
    char C = 0;                                                                 // Keep the current character here.

    for(;;) {                                                                   // We'll be looping like this...
        C = Data.Data(Index);                                                   // Grab the character at the Index.
        if(0 == C) {                                                            // If we have run out of data
            break;                                                              // then we are certainly done.
        }
        if('\n' == C) {                                                         // check to see if it's a new line
            ++LineCount;                                                        // and count it if it is.
        } else
        if('<' == C) {                                                          // When we find our < we're done!
            break;
        }                                                                       // If C wasn't what we're after
        ++Index;                                                                // move the index past this byte.
    }
    return LineCount;                                                           // In the end return the line count.
}

// Eat Comments Count Lines
// This is another variant of Eat Spaces. In this if we are on a <!-- tag
// opening, then we will eat the rest of it through -->

int  eatCommentsCountLines(ConfigurationData& Data, int& Index) {               // Eat any <!-- -->
    int LineCount = 0;                                                          // Keep the line count here.
    char C = 0;                                                                 // Keep the current character here.

    // First - are we on a comment?

    if(                                                                         // If the text at Index doesn't
      Data.Data(Index) != '<' ||                                                // look like the start of a
      Data.Data(Index + 1) != '!' ||                                            // comment then we are done.
      Data.Data(Index + 2) != '-' ||
      Data.Data(Index + 3) != '-'
      ) {
        return 0;                                                               // Return after no changes.
    }

    // Since we are on a comment, let's eat

    Index += 4;                                                                 // Move past the comment start.

    for(;;) {                                                                   // We'll be looping like this...
        C = Data.Data(Index);                                                   // Grab the character at the Index.
        if(0 == C) {                                                            // If we have run out of data
            break;                                                              // then we are certainly done.
        }
        if('\n' == C) {                                                         // check to see if it's a new line
            ++LineCount;                                                        // and count it if it is.
        } else
        if('-' == C) {                                                          // When we find a - we check for -->
            if(
              '-' == Data.Data(Index + 1) &&                                    // If we have found the end of our
              '>' == Data.Data(Index + 2)                                       // comment then we are ready to
              ) {                                                               // stop.
                Index += 3;                                                     // Move the Index past the end
                break;                                                          // and break out of the loop.
            }
        }                                                                       // If C wasn't what we're after
        ++Index;                                                                // move the index past this byte.
    }
    return LineCount;                                                           // In the end return the line count.
}

// Eat DocSpecs Count Lines
// Another variation of Eat Spaces - this time to eat <? doc specs ?>

int eatDocSpecsCountLines(ConfigurationData& Data, int& Index) {                // Eat any <?    ?>
    int LineCount = 0;                                                          // Keep the line count here.
    char C = 0;                                                                 // Keep the current character here.

    // First - are we on a doc spec?

    if(                                                                         // If the text at Index doesn't
      Data.Data(Index) != '<' ||                                                // look like the start of a
      Data.Data(Index + 1) != '?'                                               // doc spec then we are done.
      ) {
        return 0;                                                               // Return after no changes.
    }

    // Since we are on a doc spec, let's eat

    for(;;) {                                                                   // We'll be looping like this...
        C = Data.Data(Index);                                                   // Grab the character at the Index.
        if(0 == C) {                                                            // If we have run out of data
            break;                                                              // then we are certainly done.
        }
        if('\n' == C) {                                                         // check to see if it's a new line
            ++LineCount;                                                        // and count it if it is.
        } else
        if('?' == C) {                                                          // When we find a - we check for ?>
            if('>' == Data.Data(Index + 1)) {                                   // If we foudn the end we're done!
                Index += 2;                                                     // Move the Index past the end
                break;                                                          // and break out of the loop.
            }
        }                                                                       // If C wasn't what we're after
        ++Index;                                                                // move the index past this byte.
    }
    return LineCount;                                                           // In the end return the line count.
}

// Eat Attribute Count Lines
// Another variation of Eat Spaces - this time to eat unknown attributes.

int eatAttributeCountLines(ConfigurationData& Data, int& Index) {               // Eat Attribute ( name='data' )
    int LineCount = 0;                                                          // Keep the line count here.
    char C = 0;                                                                 // Keep the current character here.

    while(isNameChar(Data.Data(Index))) ++Index;                                // Eat through the name.

    LineCount += eatSpacesCountLines(Data, Index);                              // Eat any spaces.

    if('=' != Data.Data(Index)) {                                               // We should have found our = sign.
        return LineCount;                                                       // If we did NOT then we're done.
    } else {                                                                    // If we did, then we're still
        ++Index;                                                                // going - so move past it.
    }

    LineCount += eatSpacesCountLines(Data, Index);                              // Eat any extra spaces.

    C = Data.Data(Index);                                                       // Grab the next byte.
    if(                                                                         // It should be either a
      '\'' != Data.Data(Index) &&                                               // single quote or a
      '\"' != Data.Data(Index)                                                  // double quote.
      ) {                                                                       // If it is neither of these
        return LineCount;                                                       // then we are done.
    } else {                                                                    // If it was a quote then
        ++Index;                                                                // get ready to go.
    }

    while(Data.Data(Index) != C) {                                              // Carefully eat the data.
        if(0 == Data.Data(Index)) {                                             // If we run out of Data
            return LineCount;                                                   // we are done.
        } else
        if('\n' == Data.Data(Index)) {                                          // If we find a newline then
            ++LineCount;                                                        // we count it.
        }
        ++Index;                                                                // Whatever it is move past it.
    }                                                                           // Once we've found our ending
    ++Index;                                                                    // quote, we move past it and
    return LineCount;                                                           // return our Line count.
}

// Eat DocSpecs Count Lines
// Another variation of Eat Spaces - this time to eat unknown elements.

int eatElementCountLines(ConfigurationData& Data, int& Index) {                 // Eat Element ( <name>..</name> )
    int LineCount = 0;                                                          // Keep the line count here.

    // Are we on a tag?

    if(                                                                         // If we are on an element tag then
      '<' != Data.Data(Index) ||                                                // it will start with a < followed by
      false == isNameChar(Data.Data(Index + 1))                                 // a name char (usually alpha).
      ) {                                                                       // If that is not the case then
        return 0;                                                               // we are already done.
    }

    // Capture the tag name position.

    ++Index;                                                                    // Move the Index to the start of the
    int NameIndex = Index;                                                      // name and record that spot.

    while(isNameChar(Data.Data(Index))) ++Index;                                // Move the Index past the name.

    int NameEndex = Index;                                                      // Record the end position.

    // Scan for the end of this tag.

    for(;;) {                                                                   // We're looking for a > character.
        if(0 == Data.Data(Index)) {                                             // If we run out of data
            return LineCount;                                                   // we are done.
        }

        LineCount += eatSpacesCountLines(Data, Index);                          // Eat any spaces.

        if(                                                                     // Check for an empty element tag.
          '/' == Data.Data(Index) &&                                            // It will look like a /
          '>' == Data.Data(Index + 1)                                           // followed by a >
          ) {                                                                   // If this is an empty element
            Index += 2;                                                         // Move past it and return our
            return LineCount;                                                   // Line Count... consider it
        }                                                                       // eaten.

        if('>' == Data.Data(Index)) {                                           // If we come to an ordinary end
            ++Index;                                                            // of element start tag then move
            break;                                                              // past it and break out for the
        }                                                                       // next phase.

        ++Index;                                                                // Just move past anything else.
    }

    // At this point we've passed the start tag for this element and
    // we know it's name. We also know the element is not empty so we'll
    // need to go inside it, eat those things, and look for it's end
    // tag.

    // Scan for the matching end tag and eat children.

    while(                                                                      // Keep going until we get to
      '<' != Data.Data(Index) ||                                                // an end tag (starts with < followed
      '/' != Data.Data(Index + 1)                                               // by a /). If we get to something that
      ) {                                                                       // isn't a tag we're done anyway.

        int CheckIndex = Index;                                                 // Keep track of where we start.

        LineCount += eatNonTagTextCountLines(Data, Index);                      // Eat up to the next < we encounter.
        LineCount += eatElementCountLines(Data, Index);                         // Eat any elements we encounter.
        LineCount += eatCommentsCountLines(Data, Index);                        // Eat any comments we encounter.
        LineCount += eatDocSpecsCountLines(Data, Index);                        // Eat any doc specs we encounter.

        // If we stop moving break out!

        if(CheckIndex == Index) {                                               // If we didn't move at all then
            break;                                                              // we need to break out. Could be
        }                                                                       // out of data or just confused.
    };

    if(                                                                         // If we find we are not even on
      '<' != Data.Data(Index) ||                                                // an end tag then we'll just quit
      '/' != Data.Data(Index + 1)                                               // right now.
      ) {
        return LineCount;                                                       // Even so we return our line count.
    }

    // If we find an end tag - it had better be the one we want.
    // If it is not then we'll return with the index pointing at the
    // offending end tag so that parent instances will have a shot at it
    // and/or discover the problem.

    int t = 0;                                                                  // t is for terminus, it stays in scope.
    for(t = 0; (NameIndex + t) < NameEndex; t++) {                              // Scan over the name and make sure
        if(Data.Data(NameIndex + t) != Data.Data(Index + 2 + t)) {              // it matches character by character.
            return LineCount;                                                   // If any don't match, the end tag is
        }                                                                       // wron so we return w/ Index pointing
    }                                                                           // at the bad end tag.

    if('>' == Data.Data(Index + 2 + t)) {                                       // If the name matched and the next
        Index += (3 + t);                                                       // character is our > then we move the
    }                                                                           // Index past it - all is good.
                                                                                // If not then we leave the index.
    return LineCount;                                                           // Either way we return the Line Count.
}

// Copy Data and Count Lines
// At some point in the parsing, we need to extract content from our Data
// stream and convert it into a null terminated c string. While we're at it
// we also need to keep track of any new-line characters we cross so we will
// still know what line we're on. This function makes that task a one-liner.

int copyDataCountLines(char* Bfr, ConfigurationData& Data, int Start, int End) {
    int Lines = 0;                                                              // Keep track of the lines we cross.
    int DataIndex = Start;                                                      // The Data index is separate from
    int BfrIndex = 0;                                                           // our Bfr index.
    char C = 0;                                                                 // We will be looking at each character.
    while(DataIndex < End) {                                                    // While there's more segment to do...
        C = Data.Data(DataIndex);                                               // Grab each byte.
        Bfr[BfrIndex] = C;                                                      // Copy it to our buffer.
        if('\n' == C) {                                                         // Check to see if it's a new-line
            ++Lines;                                                            // and count it if it is.
        }
        ++BfrIndex;                                                             // Move our buffer and our
        ++DataIndex;                                                            // data index pointers and
    }                                                                           // keep on going.
    Bfr[BfrIndex] = 0;                                                          // At the end, null terminate.
    return Lines;                                                               // Return our line count.
}

//// Configuration Element /////////////////////////////////////////////////////

ConfigurationElement::~ConfigurationElement() {                                 // The descrutor clears and deletes all!

    // A configuration Element is "in charge of" or "owns" all of it's
    // down-stream components. So, when it is destroyed, it is responsible
    // for destroying all of those parts to prevent memory leaks.

    // Delete my attributes

    if(0 < myAttributes.size()) {                                               // If we have attributes...
        list<ConfigurationAttribute*>::iterator iAttribute;                     // Iterate through our attributes list.
        iAttribute = myAttributes.begin();                                      // Start at the beginning and
        while(iAttribute != myAttributes.end()) {                               // loop through the whole list.
            delete (*iAttribute);                                               // Delete each attribute
            iAttribute++;                                                       // then move the iterator.
        }                                                                       // When we're done deleting them
        myAttributes.clear();                                                   // clear the list.
    }

    // Delete my sub-elements

    if(0 < myElements.size()) {                                                 // If we have elements...
        list<ConfigurationElement*>::iterator iElement;                         // Iterate through our elements list.
        iElement = myElements.begin();                                          // Start at the beginning and
        while(iElement != myElements.end()) {                                   // loop through the whole list.
            delete (*iElement);                                                 // Delete each element
            iElement++;                                                         // then move the iterator.
        }                                                                       // When we're done deleting them
        myElements.clear();                                                     // clear the list.
    }

    // Delete my mnemonics

    if(0 < myMnemonics.size()) {                                                // If we have mnemonics...
        list<ConfigurationMnemonic*>::iterator iMnemonic;                       // Iterate through our mnemonics list.
        iMnemonic = myMnemonics.begin();                                        // Start at the beginning and
        while(iMnemonic != myMnemonics.end()) {                                 // loop through the whole list.
            delete (*iMnemonic);                                                // Delete each mnemonic
            iMnemonic++;                                                        // then move the iterator.
        }                                                                       // When we're done deleting them
        myMnemonics.clear();                                                    // clear the list.
    }

    // Delete my translators

    if(0 < myTranslators.size()) {                                              // If we have translators...
        list<ConfigurationTranslator*>::iterator iTranslator;                   // Iterate through our translators list.
        iTranslator = myTranslators.begin();                                    // Start at the beginning and
        while(iTranslator != myTranslators.end()) {                             // loop through the whole list.
            delete (*iTranslator);                                              // Delete each translator
            iTranslator++;                                                      // then move the iterator.
        }                                                                       // When we're done deleting them
        myTranslators.clear();                                                  // clear the list.
    }

    // zero things out

    myLine = 0;                                                                 // If I'm going away then I will leave
    myIndex = 0;                                                                // with everything at zero and clean.
    myLength = 0;
    myCleanFlag = true;

}

ConfigurationElement& ConfigurationElement::Element(                            // Mapping factory for convenience,
  const string Name,                                                            // requires a name, of course,
  ConfigurationTranslator& newTranslator) {                                     // Add a Translator to this element.

    ConfigurationElement* N = new ConfigurationElement(                         // Create a new Element with the
      Name,                                                                     // name provided and
      (*this));                                                                 // myself as the parent.

    myElements.push_back(N);                                                    // Add it to the list.
    N->mapTo(newTranslator);                                                    // Map the translator to it.
    return (*N);                                                                // Return the new element.
}

ConfigurationElement& ConfigurationElement::Element(                            // Mapping factory for convenience,
  const string Name,                                                            // requires a name, of course,
  string& x, string init) {                                                     // Map to a string.

    ConfigurationElement* N = new ConfigurationElement(                         // Create a new Element with the
      Name,                                                                     // name provided and
      (*this));                                                                 // myself as the parent.

    myElements.push_back(N);                                                    // Add it to the list.
    N->mapTo(x, init);                                                          // Map the variable into it.
    return (*N);                                                                // Return the new element.
}

ConfigurationElement& ConfigurationElement::Element(                            // Mapping factory for convenience,
  const string Name,                                                            // requires a name, of course,
  int& x, int init, int radix) {                                                // Map to an int.

    ConfigurationElement* N = new ConfigurationElement(                         // Create a new Element with the
      Name,                                                                     // name provided and
      (*this));                                                                 // myself as the parent.

    myElements.push_back(N);                                                    // Add it to the list.
    N->mapTo(x, init, radix);                                                   // Map the variable into it.
    return (*N);                                                                // Return the new element.
}

ConfigurationElement& ConfigurationElement::Element(                            // Mapping factory for convenience,
  const string Name,                                                            // requires a name, of course,
  double& x, double init) {                                                     // Map to a double.

    ConfigurationElement* N = new ConfigurationElement(                         // Create a new Element with the
      Name,                                                                     // name provided and
      (*this));                                                                 // myself as the parent.

    myElements.push_back(N);                                                    // Add it to the list.
    N->mapTo(x, init);                                                          // Map the variable into it.
    return (*N);                                                                // Return the new element.
}

ConfigurationElement& ConfigurationElement::Element(                            // Mapping factory for convenience,
  const string Name,                                                            // requires a name, of course,
  bool& x, bool init) {                                                         // Map to a boolean.

    ConfigurationElement* N = new ConfigurationElement(                         // Create a new Element with the
      Name,                                                                     // name provided and
      (*this));                                                                 // myself as the parent.

    myElements.push_back(N);                                                    // Add it to the list.
    N->mapTo(x, init);                                                          // Map the variable into it.
    return (*N);                                                                // Return the new element.
}

ConfigurationAttribute& ConfigurationElement::Attribute(const string Name) {    // Add an attribute using a c++ string.
    ConfigurationAttribute* N =                                                 // Create a new attribute by name and
      new ConfigurationAttribute(Name, (*this));                                // provide myself as the parent.

    myCleanFlag = false;                                                        // New attributes make us dirty.

    myAttributes.push_back(N);                                                  // Add the attribute to my list,
    return (*N);                                                                // dereference and return it.
}

ConfigurationAttribute& ConfigurationElement::Attribute(                        // Mapping factory for convenience,
  const string Name,                                                            // requires a name, of course,
  ConfigurationTranslator& newTranslator) {                                     // Add a Translator to this element.

    myCleanFlag = false;                                                        // New attributes make us dirty.

    ConfigurationAttribute* N =                                                 // Create a new attribute by name and
      new ConfigurationAttribute(Name, (*this));                                // provide myself as the parent.

    myAttributes.push_back(N);                                                  // Add the attribute to my list.
    N->mapTo(newTranslator);                                                    // Map in the provided translator.
    return(*N);                                                                 // Dereference and return the attribute.
}

ConfigurationAttribute& ConfigurationElement::Attribute(                        // Mapping factory for convenience,
  const string Name,                                                            // requires a name, of course,
  string& x, string init) {                                                     // Map to a string.

    myCleanFlag = false;                                                        // New attributes make us dirty.

    ConfigurationAttribute* N =                                                 // Create a new attribute by name and
      new ConfigurationAttribute(Name, (*this));                                // provide myself as the parent.

    myAttributes.push_back(N);                                                  // Add the attribute to my list.
    N->mapTo(x, init);                                                          // Map in the provided variable.
    return(*N);                                                                 // Dereference and return the attribute.
}

ConfigurationAttribute& ConfigurationElement::Attribute(                        // Mapping factory for convenience,
  const string Name,                                                            // requires a name, of course,
  int& x, int init, int radix) {                                                // Map to an int.

    myCleanFlag = false;                                                        // New attributes make us dirty.

    ConfigurationAttribute* N =                                                 // Create a new attribute by name and
      new ConfigurationAttribute(Name, (*this));                                // provide myself as the parent.

    myAttributes.push_back(N);                                                  // Add the attribute to my list.
    N->mapTo(x, init, radix);                                                   // Map in the provided variable.
    return(*N);                                                                 // Dereference and return the attribute.
}

ConfigurationAttribute& ConfigurationElement::Attribute(                        // Mapping factory for convenience,
  const string Name,                                                            // requires a name, of course,
  double& x, double init) {                                                     // Map to a double.

    myCleanFlag = false;                                                        // New attributes make us dirty.

    ConfigurationAttribute* N =                                                 // Create a new attribute by name and
      new ConfigurationAttribute(Name, (*this));                                // provide myself as the parent.

    myAttributes.push_back(N);                                                  // Add the attribute to my list.
    N->mapTo(x, init);                                                          // Map in the provided variable.
    return(*N);                                                                 // Dereference and return the attribute.
}

ConfigurationAttribute& ConfigurationElement::Attribute(                        // Mapping factory for convenience,
  const string Name,                                                            // requires a name, of course,
  bool& x, bool init) {                                                         // Map to a boolean.

    myCleanFlag = false;                                                        // New attributes make us dirty.

    ConfigurationAttribute* N =                                                 // Create a new attribute by name and
      new ConfigurationAttribute(Name, (*this));                                // provide myself as the parent.

    myAttributes.push_back(N);                                                  // Add the attribute to my list.
    N->mapTo(x, init);                                                          // Map in the provided variable.
    return(*N);                                                                 // Dereference and return the attribute.
}

ConfigurationElement& ConfigurationElement::mapTo(                              // Add a Translator to this element.
  ConfigurationTranslator& newTranslator) {                                     // Given a new translator I can own,
    myTranslators.push_back(&newTranslator);                                    // add the translator to my list
    myCleanFlag = false;                                                        // get dirty for the new translator
    return(*this);                                                              // then dereference and return myself.
}

ConfigurationElement& ConfigurationElement::mapTo(                              // Map to a string.
  string& x, string init) {                                                     // Given a string and init value,
    ConfigurationTranslator* N =                                                // create a new translator for it
      new StringTranslator(x, init);                                            // with the values i'm given,
    myTranslators.push_back(N);                                                 // push it onto my list, then
    myCleanFlag = false;                                                        // get dirty for the new translator
    return(*this);                                                              // then dereference and return myself.
}

ConfigurationElement& ConfigurationElement::mapTo(                              // Map to an int.
  int& x, int init, int radix) {                                                // Given an int and init values,
    ConfigurationTranslator* N =                                                // create a new translator for it
      new IntegerTranslator(x, init, radix);                                    // with the values i'm given,
    myTranslators.push_back(N);                                                 // push it onto my list, then
    myCleanFlag = false;                                                        // get dirty for the new translator
    return(*this);                                                              // then dereference and return myself.
}

ConfigurationElement& ConfigurationElement::mapTo(                              // Map to a double.
  double& x, double init) {                                                     // Given a double and it's init value,
    ConfigurationTranslator* N =                                                // create a new translator for it
      new DoubleTranslator(x, init);                                            // with the values i'm given,
    myTranslators.push_back(N);                                                 // push it onto my list, then
    myCleanFlag = false;                                                        // get dirty for the new translator
    return(*this);                                                              // then dereference and return myself.
}

ConfigurationElement& ConfigurationElement::mapTo(                              // Map to a boolean.
  bool& x, bool init) {                                                         // Given a bool and it's init value,
    ConfigurationTranslator* N =                                                // create a new translator for it
      new BoolTranslator(x, init);                                              // with the values i'm given,
    myTranslators.push_back(N);                                                 // push it onto my list, then
    myCleanFlag = false;                                                        // get dirty for the new translator
    return(*this);                                                              // then dereference and return myself.
}

void ConfigurationElement::initialize() {                                       // Reset all translators to defaults.

    // Initialize the elements below me

    if(0 < myElements.size()) {                                                 // If we have elements...
        list<ConfigurationElement*>::iterator iElement;                         // Iterate through our elements list.
        iElement = myElements.begin();                                          // Start at the beginning and
        while(iElement != myElements.end()) {                                   // loop through the whole list.
            (*iElement)->initialize();                                          // Initialize each element
            iElement++;                                                         // then move the iterator.
        }
    }

    // Once that's done, see about myself

    if(true == myCleanFlag) return;                                             // If I'm already clean, return.

    // Initialize my own translators

    if(0 < myTranslators.size()) {                                              // If we have translators...
        list<ConfigurationTranslator*>::iterator iTranslator;                   // Iterate through our translators list.
        iTranslator = myTranslators.begin();                                    // Start at the beginning and
        while(iTranslator != myTranslators.end()) {                             // loop through the whole list.
            (*iTranslator)->initialize();                                       // Initialize each translator
            iTranslator++;                                                      // then move the iterator.
        }
    }

    // Initialize my own attributes

    if(0 < myAttributes.size()) {                                               // If we have attributes...
        list<ConfigurationAttribute*>::iterator iAttribute;                     // Iterate through our attributes list.
        iAttribute = myAttributes.begin();                                      // Start at the beginning and
        while(iAttribute != myAttributes.end()) {                               // loop through the whole list.
            (*iAttribute)->initialize();                                        // Initialize each attribute
            ++iAttribute;                                                       // then move the iterator.
        }
    }

    // Zero things out

    myLine = 0;                                                                 // Initialized means to be as if
    myIndex = 0;                                                                // no interpet() call has been made.
    myLength = 0;

    // At this point we know we are clean

    myCleanFlag = true;                                                         // Clean as a whistle!

}

void ConfigurationElement::runStartConfigurators(ConfigurationData& D) {        // Does what it says ;-)
    list<Configurator*>::iterator iConfigurator;                                // Iterate through our Configurators list.
    iConfigurator = myStartConfigurators.begin();                               // Start at the beginning and
    while(iConfigurator != myStartConfigurators.end()) {                        // loop through the whole list.
        (** iConfigurator)(*this, D);                                           // Launch each configurator with self.
        ++iConfigurator;                                                        // Move to the next.
    }
}

void ConfigurationElement::runEndConfigurators(ConfigurationData& D) {          // Does what it says ;-)
    list<Configurator*>::iterator iConfigurator;                                // Iterate through our Configurators list.
    iConfigurator = myEndConfigurators.begin();                                 // Start at the beginning and
    while(iConfigurator != myEndConfigurators.end()) {                          // loop through the whole list.
        (** iConfigurator)(*this, D);                                           // Launch each configurator with self.
        ++iConfigurator;                                                        // Move to the next.
    }
}

bool ConfigurationElement::interpret(ConfigurationData& Data) {                 // (re) Interpret this data.

    int Index = Data.Index();                                                   // Our working index.
    int Startdex = 0;                                                           // Where our data starts.
    int Stopdex = 0;                                                            // Where our data stops.
    int NewLines = 0;                                                           // Keep a count of new lines.

    //// Pre-Processing / Cleanup / Find <name...
    // Eat anything up to the first <
    // Eat any comments <!-- this is a comment etc -->
    // Eat any doctype headers <?xml version="1.0" etc ?>

    for(;;) {
        int StartingPoint = Index;                                              // Where did we start each pass?
        NewLines += eatNonTagTextCountLines(Data, Index);                       // Eat any spaces we find.
        NewLines += eatCommentsCountLines(Data, Index);                         // Eat any <!-- -->
        NewLines += eatDocSpecsCountLines(Data, Index);                         // Eat any <?    ?>
        if(StartingPoint == Index) { break; }                                   // If we didn't move on this pass
    }                                                                           // then we are done with cleanup!

    // Update Data to move past any of the preceeding junk. This way, other
    // element processors will be able to skip any cleanup work we did.

    Data.Index(Index);                                                          // Move the Index.
    Data.addNewLines(NewLines);                                                 // Update the Line Number.
    NewLines = 0;                                                               // Reset our internal Lines counter.

    // Find my name.

    if(Data.Data(Index) != '<') {                                               // If we're not on a tag open then
        return false;                                                           // we are not at an element.
    } else {                                                                    // Otherwise we are safe to move
        ++Index;                                                                // past it and scan for our name.
    }

    for(unsigned int I = 0; I < myName.length(); I++) {                         // For the length of our name,
        char x = Data.Data(Index + I);                                          // get each corresponding Data byte
        if(x != myName.at(I)) {                                                 // check it sudden death style.
            return false;                                                       // No-Match means we are not it.
        }
    }                                                                           // If the name checks out then
    Index += myName.length();                                                   // move the Index past our name.

    // At this point we have found ourselves so we will activate and interpret
    // our Data.

    if(true == myInitOnInterpretFlag) {                                         // If we are supposed to Init before
        initialize();                                                           // we Interpret then do it.
    }

    // Since we are activating we must set our state so we know where we are.

    myLine = Data.Line();                                                       // We know where we start...
    myIndex = Data.Index();                                                     // We know our index...
    myLength = 0;                                                               // We don't know our length yet.

    runStartConfigurators(Data);                                                // Run the start configurators.

    myCleanFlag = false;                                                        // Now we start to get dirty.

    // First, we will run through any attributes we have.

    bool ThisIsAnEmptyElement = false;                                          // We'll use this to signal empties.

    for(;;) {                                                                   // This is how we roll..

        NewLines += eatSpacesCountLines(Data, Index);                           // Eat any spaces we find.
        Data.Index(Index);                                                      // Move the Index.
        Data.addNewLines(NewLines);                                             // Update the Line Number.
        NewLines = 0;                                                           // Reset our internal Lines counter.

        // Now we look at the next character. Either it's an attribute, or
        // it's the end of the tag, or it's some kind of junk. If it's junk
        // we will skip it. We will continue parsing until we get to the end
        // of the Data or the end of the opening tag (either stopping at / if
        // the element is empty or > if the element is not empty.

        if(isalpha(Data.Data(Index))) {                                         // If it looks like an attribute...
            bool ParseHappened = false;                                         // Start pessimistically at each pass.
            list<ConfigurationAttribute*>::iterator iAttribute;                 // Iterate through our attributes list.
            iAttribute = myAttributes.begin();                                  // Start at the beginning and
            while(iAttribute != myAttributes.end()) {                           // loop through the whole list.
                ParseHappened = (* iAttribute)->interpret(Data);                // Have each attribute interpret(Data)
                ++iAttribute;                                                   // Remember to move to the next one.
                if(ParseHappened) break;                                        // If a Parse Happened, break the inner
            }                                                                   // loop and start the next pass.
            if(false == ParseHappened) {                                        // If we didn't recognize the attribute
                NewLines += eatAttributeCountLines(Data, Index);                // then eat it.
                Data.Index(Index);                                              // Sync up our Index.
                Data.addNewLines(NewLines);                                     // Sync up our NewLines.
                NewLines = 0;                                                   // Zero our NewLines count.
            } else {                                                            // If we DID recognize the attribute then
                Index = Data.Index();                                           // sync up our Index for the next one.
            }
        } else
        if(0 == Data.Data(Index)) {                                             // If it looks like the end of Data
            break;                                                              // we will break out - we're done.
        } else
        if(                                                                     // If it looks like the end of an empty
          '/' == Data.Data(Index) &&                                            // element (starts with / and ends with
          '>' == Data.Data(Index + 1)                                           // >) then this must be an empty element.
          ) {
            ThisIsAnEmptyElement = true;                                        // Set the empty element flag and
            Index += 2;                                                         // Move past the end of the tag and
            break;                                                              // break out of the loop.
        } else
        if('>' == Data.Data(Index)) {                                           // If it looks like the end of an open
            Index += 1;                                                         // tag then move past the end and
            break;                                                              // break out of the loop.

        } else {                                                                // If it looks like anything else then
            ++Index;                                                            // we don't know what it is so we creep
        }                                                                       // past it.
    }

    Data.Index(Index);                                                          // Sync up our index

    // At this point we're done processing our open tag and any attributes it
    // may have contained, and we are syncrhonized with Data.

    if(ThisIsAnEmptyElement) {                                                  // If the element was self closing then
        runEndConfigurators(Data);                                              // run the End Configurators and return
        return true;                                                            // true to the caller.
    }

    // At this point we have contents and/or elements to process. We will keep
    // track of any contents using Startdex and Stopdex.

    Startdex = Index;

    // Now we will process through any elements there may be until we reach
    // our end tag. If we have no sub-elements listed, we'll simply skip that
    // step on each pass... So, we roll like this:
    // Check for end of Data.
    // Check for our end tag.
    // Check for a sub-element.
    // If none of these work then break out.

    for(;;) {                                                                   // Loop through our content like this.

        int CheckPoint = Index;                                                 // Where did we start each pass?

        // Check for end of data //

        if(0 == Data.Data(Index)) {                                             // If we are at end of data then we're
            return false;                                                       // broken so we return false.
        } else

        // Check for our own end tag //

        if(                                                                     // If this looks like an end tag
          '<' == Data.Data(Index) &&                                            // (Starts with < followed by
          '/' == Data.Data(Index + 1)                                           // a / character)
          ) {                                                                   // Then it _should_ be our own.
            Stopdex = Index;                                                    // Capture this position for content.
            Index += 2;                                                         // Move Index to where the name starts.
            for(unsigned int I = 0; I < myName.length(); I++) {                 // For the length of the name,
                char x = Data.Data(Index + I);                                  // check each corresponding Data byte.
                if(x != myName.at(I)) {                                         // If we fail to match at any point
                    return false;                                               // then things are very broken
                }                                                               // so we return false.
            }                                                                   // If the name checks out then
            Index += myName.length();                                           // move past our name.
            if('>' != Data.Data(Index)) {                                       // Being very strict, if the next
                return false;                                                   // byte is not > then fail!
            } else {                                                            // If all goes well then we move
            ++Index;                                                            // past the > and we are done.
            break;                                                              // Break to move to the next step.
            }
        } else

        // Check for a subordinate element //

        if(                                                                     // If this looks like an element
          '<' == Data.Data(Index) &&                                            // starting with < and a name
          isalpha(Data.Data(Index + 1))                                         // beginning with an alpha character...
          ) {
            bool ElementHappened = false;                                       // We'll check our elements.
            Data.Index(Index);                                                  // Sync our index.
            Data.addNewLines(NewLines);                                         // Sync our lines.
            NewLines = 0;                                                       // Reset our new lines count.
            if(0 < myElements.size()) {                                         // If we have elements check them.

                list<ConfigurationElement*>::iterator iElement;                 // Iterate through our elements list.
                iElement = myElements.begin();                                  // Start at the beginning and
                while(iElement != myElements.end()) {                           // loop through the whole list.
                    ConfigurationElement& doNode = **iElement;                  // Grab the element we're on.
                    ElementHappened = doNode.interpret(Data);                   // Have each element interpret(Data)
                    Index = Data.Index();                                       // Capitalze on any cleanup work.
                    ++iElement;                                                 // Remember to move to the next.
                    if(ElementHappened) break;                                  // If an Element Happened, break the
                }                                                               // loop and start the next pass.
                if(false == ElementHappened) {                                  // If we did not recognize the Element
                    NewLines += eatElementCountLines(Data, Index);              // then eat it *****
                    Data.Index(Index);                                          // Resync our Index.
                    Data.addNewLines(NewLines);                                 // Sync our line count.
                    NewLines = 0;                                               // Reset our internal count.
                }
            } else {                                                            // If we don't own any elements then
                NewLines += eatElementCountLines(Data, Index);                  // eat the ones we find.
            }

        // Handle any untidy messes here //

        } else {                                                                // If we're on something unknown then
            NewLines += eatSpacesCountLines(Data, Index);                       // Eat any spaces we find.
            NewLines += eatCommentsCountLines(Data, Index);                     // Eat any <!-- -->
            NewLines += eatDocSpecsCountLines(Data, Index);                     // Eat any <?    ?>
            NewLines += eatNonTagTextCountLines(Data, Index);                   // Eat any non tag bytes.
            Data.Index(Index);                                                  // Sync our Index.
            Data.addNewLines(NewLines);                                         // Sync our line number.
            NewLines = 0;                                                       // Clear our lines count.
        }

        // If we get stuck looping on something we don't know how to clean
        // and don't know how to interpret then we need to break out of the
        // insanity. This way, anything that doesn't make sense won't be able
        // to stall us or cause us to interpret something incorrectly later
        // on... If we're the top element, the interpret() process will end.
        // If we are deeper then it is likely our superirors will also not
        // understand and so they will also end the same way.

        if(CheckPoint == Index) return false;                                   // If we haven't moved, punt!
    }

    // When we're done with our loop sync up with Data again.

    Data.Index(Index);                                                          // Sync up our Index.
    Data.addNewLines(NewLines);                                                 // Sync up our NewLines count.
    NewLines = 0;                                                               // zero our local count.

    // Once our elements have been procssed and we get to our end tag we can
    // process our content (if we have Translators registered).

    if(
      0 < myTranslators.size() &&                                               // If we have translators and
      Stopdex > Startdex                                                        // we have content to translate
      ) {                                                                       // then translate the content!
        // Create the Content buffer...

        int BfrSize = Stopdex - Startdex;                                       // How big a buffer do we need?
        char Bfr[BfrSize];                                                      // Make one that size.

        copyDataCountLines(Bfr, Data, Startdex, Stopdex);                       // Get our data and ignore our lines.

        // Now we can get on with translation.

        char* TranslationData = Bfr;                                            // TranslationData is what we translate.

        // Translate our data by Mnemonic

        if(0 < myMnemonics.size()) {                                            // If we have mnemonics...
            list<ConfigurationMnemonic*>::iterator iMnemonic;                   // Iterate through our mnemonics list.
            iMnemonic = myMnemonics.begin();                                    // Start at the beginning and
            while(iMnemonic != myMnemonics.end()) {                             // loop through the whole list.
                if(true == ((*iMnemonic)->test(TranslationData))) {             // Check to see if the mnemonic matches.
                    TranslationData = const_cast<char*>(                        // If it does match, substitute it's
                        (*iMnemonic)->Value().c_str());                         // value for translation and stop
                    break;                                                      // looking.
                } else {                                                        // If it does not match, move to the
                    ++iMnemonic;                                                // next mnemonic and test again.
                }                                                               // That is, until we run out of
            }                                                                   // mnemonics to test.
        }

        // Put our TranslationData through each Translator.

        list<ConfigurationTranslator*>::iterator iTranslator;                   // Iterate through our translators list.
        iTranslator = myTranslators.begin();                                    // Start at the beginning and
        while(iTranslator != myTranslators.end()) {                             // loop through the whole list.
            (*iTranslator)->translate(TranslationData);                         // Pass the data to each one then
            ++iTranslator;                                                      // move on to the next.
        }
    }

    // And finally, after all is done successfully...

    runEndConfigurators(Data);                                                  // Launch the End Configurators.
    return true;                                                                // Return our success!
}

//// Configuration Attribute ///////////////////////////////////////////////////

ConfigurationAttribute::~ConfigurationAttribute() {                             // Crush, Kill, Destroy!

    // Delete my mnemonics

    if(0 < myMnemonics.size()) {                                                // If we have mnemonics...
        list<ConfigurationMnemonic*>::iterator iMnemonic;                       // Iterate through our mnemonics list.
        iMnemonic = myMnemonics.begin();                                        // Start at the beginning and
        while(iMnemonic != myMnemonics.end()) {                                 // loop through the whole list.
            delete (*iMnemonic);                                                // Delete each mnemonic
            iMnemonic++;                                                        // then move the iterator.
        }                                                                       // When we're done deleting them
        myMnemonics.clear();                                                    // clear the list.
    }

    // Delete my translators

    if(0 < myTranslators.size()) {                                              // If we have translators...
        list<ConfigurationTranslator*>::iterator iTranslator;                   // Iterate through our translators list.
        iTranslator = myTranslators.begin();                                    // Start at the beginning and
        while(iTranslator != myTranslators.end()) {                             // loop through the whole list.
            delete (*iTranslator);                                              // Delete each translator
            iTranslator++;                                                      // then move the iterator.
        }                                                                       // When we're done deleting them
        myTranslators.clear();                                                  // clear the list.
    }

    // zero things out

    myLine = 0;                                                                 // If I'm going away then I will leave
    myIndex = 0;                                                                // with everything at zero and clean.
    myLength = 0;
}

ConfigurationAttribute& ConfigurationAttribute::mapTo(                          // Add a Translator to this attribute.
  ConfigurationTranslator& newTranslator) {                                     // Given a new translator I can own,
    myTranslators.push_back(&newTranslator);                                    // add the translator to my list
    myParent.notifyDirty();                                                     // get dirty for the new translator
    return(*this);                                                              // then dereference and return myself.
}

ConfigurationAttribute& ConfigurationAttribute::mapTo(                          // Map to a string.
  string& x, string init) {                                                     // Given a string and init value,
    ConfigurationTranslator* N =                                                // create a new translator for it
      new StringTranslator(x, init);                                            // with the values i'm given,
    myTranslators.push_back(N);                                                 // push it onto my list, then
    myParent.notifyDirty();                                                     // get dirty for the new translator
    return(*this);                                                              // dereference and return myself.
}

ConfigurationAttribute& ConfigurationAttribute::mapTo(                          // Map to an int.
  int& x, int init, int radix) {                                                // Given an int and init values,
    ConfigurationTranslator* N =                                                // create a new translator for it
      new IntegerTranslator(x, init, radix);                                    // with the values i'm given,
    myTranslators.push_back(N);                                                 // push it onto my list, then
    myParent.notifyDirty();                                                     // get dirty for the new translator
    return(*this);                                                              // dereference and return myself.
}

ConfigurationAttribute& ConfigurationAttribute::mapTo(                          // Map to a double.
  double& x, double init) {                                                     // Given a double and it's init value,
    ConfigurationTranslator* N =                                                // create a new translator for it
      new DoubleTranslator(x, init);                                            // with the values i'm given,
    myTranslators.push_back(N);                                                 // push it onto my list, then
    myParent.notifyDirty();                                                     // get dirty for the new translator
    return(*this);                                                              // then dereference and return myself.
}

ConfigurationAttribute& ConfigurationAttribute::mapTo(                          // Map to a boolean.
  bool& x, bool init) {                                                         // Given a bool and it's init value,
    ConfigurationTranslator* N =                                                // create a new translator for it
      new BoolTranslator(x, init);                                              // with the values i'm given,
    myTranslators.push_back(N);                                                 // push it onto my list, then
    myParent.notifyDirty();                                                     // get dirty for the new translator
    return(*this);                                                              // then dereference and return myself.
}

void ConfigurationAttribute::initialize() {                                     // Reset all translators to defaults.

    if(0 < myTranslators.size()) {                                              // If we have translators...
        list<ConfigurationTranslator*>::iterator iTranslator;                   // Iterate through our translators list.
        iTranslator = myTranslators.begin();                                    // Start at the beginning and
        while(iTranslator != myTranslators.end()) {                             // loop through the whole list.
            (*iTranslator)->initialize();                                       // initialize each translator
            iTranslator++;                                                      // then move the iterator.
        }                                                                       // When we're done deleting them
    }

    // zero things out

    myLine = 0;                                                                 // Initialized means to be as if
    myIndex = 0;                                                                // no interpet() call has been made.
    myLength = 0;
}

bool ConfigurationAttribute::interpret(ConfigurationData& Data) {               // (re) Interpret this data.

    int Index = Data.Index();                                                   // Our working index.
    int Startdex = 0;                                                           // Where our data starts.
    int Stopdex = 0;                                                            // Where our data stops.
    int NewLines = 0;                                                           // Keep a count of new lines.

    // Find our name.

    for(unsigned int I = 0; I < myName.length(); I++) {                         // For the length of the name,
        char x = Data.Data(Index + I);                                          // get each corresponding Data byte
        if(x != myName.at(I)) {                                                 // check it sudden death style.
            return false;                                                       // No-Match means we are not it.
        }
    }                                                                           // If the name checks out then
    Index += myName.length();                                                   // move the Index past our name.

    NewLines += eatSpacesCountLines(Data, Index);                               // Eat any spaces we find.

    // Find our = sign.

    if('=' != Data.Data(Index)) {                                               // Next we should see an =
        return false;                                                           // If we don't we're done.
    } else {                                                                    // If we do then we can
        ++Index;                                                                // move past it.
    }

    NewLines += eatSpacesCountLines(Data, Index);                               // Eat any spaces we find.

    // Find our first quote character.

    char QuoteCharacter = 0;
    if('\'' == Data.Data(Index) || '\"' == Data.Data(Index)) {                  // Next we should find ' or "
        QuoteCharacter = Data.Data(Index);                                      // If we found it record it then
        ++Index; Startdex = Index;                                              // move to and record our start of data.
    } else {                                                                    // If we don't
        return false;                                                           // we are done.
    }

    // Find our last quote character.

    for(;;) {                                                                   // Here is how we will roll...
        char C = Data.Data(Index);                                              // Grab the character at Index.
        if(0 == C) {                                                            // If we run out of Data then
            return false;                                                       // We didn't find anything.
        }
        if(QuoteCharacter == C) {                                               // If we find our QuoteCharacter
            Stopdex = Index;                                                    // we have our Stopdex and
            break;                                                              // we can stop the loop.
        }
        ++Index;                                                                // Otherwise keep on looking.
    }

    // Read our data.

    int BfrSize = Stopdex - Startdex;                                           // How big a buffer do we need?
    char Bfr[BfrSize];                                                          // Make one that size.

    NewLines += copyDataCountLines(Bfr, Data, Startdex, Stopdex);               // Get our data and count our lines.

    // Now we can get on with translation.

    char* TranslationData = Bfr;                                                // TranslationData is what we translate.

    // Translate our data by Mnemonic

    if(0 < myMnemonics.size()) {                                                // If we have mnemonics...
        list<ConfigurationMnemonic*>::iterator iMnemonic;                       // Iterate through our mnemonics list.
        iMnemonic = myMnemonics.begin();                                        // Start at the beginning and
        while(iMnemonic != myMnemonics.end()) {                                 // loop through the whole list.
            if(true == ((*iMnemonic)->test(TranslationData))){                  // Check to see if the mnemonic matches.
                TranslationData = const_cast<char*>(                            // If it does match, substitute it's
                  (*iMnemonic)->Value().c_str());                               // value for translation and stop
                break;                                                          // looking.
            } else {                                                            // If it does not match, move to the
                ++iMnemonic;                                                    // next mnemonic and test again.
            }                                                                   // That is, until we run out of
        }                                                                       // mnemonics to test.
    }

    // Put our TranslationData through each Translator.

    if(0 < myTranslators.size()) {                                              // We'd better have translators!
        list<ConfigurationTranslator*>::iterator iTranslator;                   // Iterate through our translators list.
        iTranslator = myTranslators.begin();                                    // Start at the beginning and
        while(iTranslator != myTranslators.end()) {                             // loop through the whole list.
            (*iTranslator)->translate(TranslationData);                         // Pass the data to each one and
            ++iTranslator;                                                      // move on to the next one.
        }
    }

    // Capture our position data.

    myLine = Data.Line();                                                       // Capture the line I was on.
    myIndex = Data.Index();                                                     // Capture the Index where I started.
    myLength = Stopdex + 1 - myIndex;                                           // Capture my segment length.

    // Update Data for the next segment.

    Data.Index(Stopdex + 1);                                                    // Move the Index.
    Data.addNewLines(NewLines);                                                 // Update the Line Number.

    return true;                                                                // If we got here, we succeeded!
}

//// Configuratino Data ////////////////////////////////////////////////////////

ConfigurationData::ConfigurationData(const char* Data, int Length) :            // Raw constructor from buffer.
  myBufferSize(Length),                                                         // and it's length.
  myIndex(0),                                                                   // Our Index is zero
  myLine(1) {                                                                   // We start on line 1
    myDataBuffer = new char[myBufferSize];                                      // Allocate a buffer.
    memcpy(myDataBuffer, Data, myBufferSize);                                   // Copy the data.
}

ConfigurationData::ConfigurationData(const char* FileName) :
  myDataBuffer(NULL),                                                           // No data buffer yet.
  myBufferSize(0),                                                              // No length yet.
  myIndex(0),                                                                   // Our Index is zero
  myLine(1) {                                                                   // We start on line 1
    try {                                                                       // Capture any throws.
        ifstream CFGFile(FileName);                                             // Open the file.
        CFGFile.seekg(0,ios::end);                                              // Seek to the end
        myBufferSize = CFGFile.tellg();                                         // to find out what size it is.
        myDataBuffer = new char[myBufferSize];                                  // Make a new buffer the right size.
        CFGFile.seekg(0,ios::beg);                                              // Seek to the beginning and
        CFGFile.read(myDataBuffer, myBufferSize);                               // read the file into the buffer.
        if(CFGFile.bad()) {                                                     // If the read failed, we're unusable!
            delete[] myDataBuffer;                                              // Delete the buffer
            myDataBuffer = NULL;                                                // and Null it's pointer.
            myBufferSize = 0;                                                   // Set the length to zero.
        }                                                                       // Usually everything will work
        CFGFile.close();                                                        // At the end, always close our file.
    } catch (...) {                                                             // If something went wrong clean up.
        if(NULL != myDataBuffer) {                                              // If the data buffer was allocated
            delete[] myDataBuffer;                                              // Delete the buffer
            myDataBuffer = NULL;                                                // and Null it's pointer.
        }
        myBufferSize = 0;                                                       // The BufferSize will be zero
    }                                                                           // indicating there is no Data.
}

ConfigurationData::ConfigurationData(const string FileName) :                   // Raw constructor from file.
  myDataBuffer(NULL),                                                           // No data buffer yet.
  myBufferSize(0),                                                              // No length yet.
  myIndex(0),                                                                   // Our Index is zero
  myLine(1) {                                                                   // We start on line 1
    try {                                                                       // Capture any throws.
        ifstream CFGFile(FileName.c_str());                                     // Open the file.
        CFGFile.seekg(0,ios::end);                                              // Seek to the end
        myBufferSize = CFGFile.tellg();                                         // to find out what size it is.
        myDataBuffer = new char[myBufferSize];                                  // Make a new buffer the right size.
        CFGFile.seekg(0,ios::beg);                                              // Seek to the beginning and
        CFGFile.read(myDataBuffer, myBufferSize);                               // read the file into the buffer.
        if(CFGFile.bad()) {                                                     // If the read failed, we're unusable!
            delete[] myDataBuffer;                                              // Delete the buffer
            myDataBuffer = NULL;                                                // and Null it's pointer.
            myBufferSize = 0;                                                   // Set the length to zero.
        }                                                                       // Usually everything will work
        CFGFile.close();                                                        // At the end, always close our file.
    } catch (...) {                                                             // If something went wrong clean up.
        if(NULL != myDataBuffer) {                                              // If the data buffer was allocated
            delete[] myDataBuffer;                                              // Delete the buffer
            myDataBuffer = NULL;                                                // and Null it's pointer.
        }
        myBufferSize = 0;                                                       // The BufferSize will be zero
    }                                                                           // indicating there is no Data.
}

ConfigurationData::~ConfigurationData() {                                       // Destroys the internal buffer etc.
    if(NULL != myDataBuffer) {                                                  // If we have allocated a buffer,
        delete[] myDataBuffer;                                                  // delete that buffer
        myDataBuffer = NULL;                                                    // and null the pointer.
    }
    myBufferSize = 0;                                                           // Zero everything for safety.
    myIndex = 0;
    myLine = 0;
}

//// Utilities /////////////////////////////////////////////////////////////////

// SetTrueOnComplete Configurator //////////////////////////////////////////////

ConfiguratorSetTrueOnComplete::ConfiguratorSetTrueOnComplete() :                // Constructor ensures the pointer
  myBoolean(NULL) {                                                             // is NULL for safety.
}

void ConfiguratorSetTrueOnComplete::setup(bool& Target) {                       // The setup() method links us to a
    myBoolean = &Target;                                                        // target boolean.
}

void ConfiguratorSetTrueOnComplete::operator()(                                 // The operator()
  ConfigurationElement& E, ConfigurationData& D) {                              // When activated, this fellow
    if(NULL != myBoolean) {                                                     // checks it's pointer for safety
        *myBoolean = true;                                                      // and if ok, sets the target to
    }                                                                           // true.
}

