/**
   License: Public Domain
   Author: stephan@wanderinghorse.net
*/
//#include <ctype.h> // for isspace()
#include "EKeyValueParser.h"
#include <iostream>
using namespace std;
EKeyValueParser::charbool_map_type EKeyValueParser::commentChars;

std::ostream &
operator<<(ostream &os, const EKeyValueParser &obj)
{
        os << obj.key();
        os << std::string("="); // gcc3 bitches if this is a char *???
        os <<obj.value();
        return os;
}

//         bool
//         operator>>( const EKeyValueParser &obj, std::istream &is )
//         {
// //                 E
// //                 is.getline
// //                 return obj.parse(;
//                 return false;
//         }

EKeyValueParser::EKeyValueParser()
{
        EKeyValueParser::init();
}

EKeyValueParser::EKeyValueParser( const string &ln )
{
        EKeyValueParser::init();
        m_key = m_val = "";
        parse( ln );
}

bool
EKeyValueParser::parse( const string &ln, const string & delim )
{
        m_line = ln;
        if( m_line.length() < 2 ) return false;

        commentIt = commentChars.find( ln[0] );
        if( commentIt != commentChars.end() ) return false;

        m_key = "";
        m_val = "";

        string::size_type offset = m_line.find( delim );

        if( offset == string::npos ) return false;


        m_key = m_line.substr( 0, offset );
        m_val = m_line.substr( offset + delim.length() );

        // strip leading/trailing spaces from m_key and m_val.
        // there must be a simpler (or at least more graceful) way...
        static const std::string space(" \t");
        while( !m_key.empty() && m_key.find_last_of( space ) == (m_key.size()-1) )
        { // trailing key whitespace
                m_key.erase( m_key.size()-1 );
        }
        while( !m_key.empty() && (m_key.find_first_of( space ) == 0 ) )
        { // leading key whitespace
                m_key.erase( 0, 1 );
        }

        while( !m_val.empty() && (m_val.find_first_of( space ) == 0 ) )
        { // leading val whitespace
                m_val.erase( 0, 1 );
        }
        while( !m_val.empty() && m_val.find_last_of( space ) == (m_val.size()-1) )
        { // trailing val whitespace
                m_val.erase( m_val.size()-1 );
        }
        // Whew. Blessed indeed is Perl.
        //CERR << "m_key=["<<m_key<<"] m_val=["<<m_val<<"]"<<endl;
        return m_key.size() > 0;
}

void
EKeyValueParser::init()
{
        static bool inited = false;
        if( !inited && (inited=true) )
        {
                commentChars[';'] = true; // classic config-file style
                commentChars['#'] = true; // bash-style
                commentChars['/'] = true; // assume '/' or '/*'. Honestly, though, it's this way only because it simplifies searching :/
                EKeyValueParser::init();
        }

}
                
