#ifndef SGB_KEYVALUEPARSER_H
#define SGB_KEYVALUEPARSER_H

#include <string>
#include <map>
#include <list>

using namespace std;
/**
   License: Public Domain
   Author: stephan@wanderinghorse.net
*/

// todo: move this stuff into the classes it belongs in and use STL naming conventions:
// can't move it yet because other code uses it :/ (lame excuse: use perl!)
typedef std::map<std::string,std::string> strstr_map_type;
typedef strstr_map_type::iterator strstr_map_iterator;
typedef strstr_map_type::const_iterator StringStringConstIterator;
typedef strstr_map_type::value_type StringStringPair;

typedef std::map<std::string,bool> TrueMap;
typedef TrueMap::iterator TrueMapIterator;
typedef TrueMap::value_type TrueMapPair;


typedef std::map<std::string,bool> StringBoolMap;
typedef StringBoolMap::iterator StringBoolIterator;
typedef StringBoolMap::value_type StringBoolPair;

typedef std::list<std::string> StringList;
typedef StringList::iterator StringListIterator;

/**
   EKeyValueParser is a class for parsing "key=value"-style lines,
   like those which would come from a configuration file.
*/
class EKeyValueParser
{
public:
        explicit EKeyValueParser( const string &line );
        EKeyValueParser();
        virtual ~EKeyValueParser() {};

        // enters k.key()=k.value() into os.
        friend std::ostream & operator << (std::ostream &os, const EKeyValueParser &);

        /**
           Parses 'line' into a key/value pair. To be parseable the line must be in the form:

           key=value

           Extra whitespace around the '=' is removed, as are leading and
           trailing whitespace around the key and value. This behaviour is
           arguable but probably desireable in most cases (it is in all of
           mine, and i wrote the damned thing ;).

           todo: add a whitespace removal policy as optional 3rd argument?

           delimiter is the string which separates the key and
           value, so a line in the format:
    
           key{alternateDelimiter}value...
    
           (minus the braces) is parseable.

           That is:
           parse( "one;two",";" )
           results in key() == "one" and value() == "two"

           This function returns false if it does not consider the line to be parseable.
           Use key() and value() to get the parsed values. Use line() to get the whole
           string passed to parse (as if you'd ever need it, though subclasses might).
           line() /is/ guaranteed to be set to line by this call, unlike key() and value().
       
           If this function returns false, the values returned by key() and value()
           cannot be considered reliable (i.e., they are undefined).

           This function will return false if a line contains no key (like
           '=value'), but empty values are not an error (i.e., they will not
           cause this function to return false).

        */
        bool parse( const string &line, const string & delimiter = "=" );


        /**
           Returns the parsed-out key. Only valid if parse() returned true.
        */
        inline const string & key() const { return this->m_key; };
        /**
           Returns the parsed-out value (may be empty). Only valid if parse() returned true.
        */
        inline const string & value() const {return this->m_val; };

        /**
           Returns the last whole line passed to parse().
        */
        inline const string & line() const { return this->m_line;};

private:
        typedef std::map<char,bool> charbool_map_type;
        typedef charbool_map_type::iterator charbool_map_iterator;
        //typedef charbool_map_type::value_type CharBoolPair;
        static void init();
        string m_key;
        string m_val;
        string m_line;
        static charbool_map_type commentChars;
        charbool_map_iterator commentIt;
        string::const_iterator strIt;
};

#endif // SGB_KEYVALUEPARSER_H
