/*
   Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License, version 2.0,
   as published by the Free Software Foundation.

   This program is also distributed with certain software (including
   but not limited to OpenSSL) that is licensed under separate terms,
   as designated in a particular file or component or in included license
   documentation.  The authors of MySQL hereby grant you an additional
   permission to link the program and your derivative works with the
   separately licensed software that they have included with MySQL.

   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, version 2.0, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
*/

/*
 * string_helpers.hpp
 *
 */

#ifndef string_helpers_hpp
#define string_helpers_hpp

//#include <cstdio>
#include <iostream>
#include <sstream>
#include <string>
#include <set>

namespace utils {
    
//using namespace std;
//using std::cout;
//using std::endl;
//using std::flush;
using std::string;
using std::wstring;
using std::ostream;
using std::wistringstream;
using std::set;

/************************************************************
 * String Helper Functions
 ************************************************************/

/**
 * Returns the boolean value of a wide character string.
 *
 * Returns true if the argument is equal, ignoring case, to the string
 * "true"; otherwise, false.
 */
inline bool
toBool(const wstring& ws, bool vdefault)
{
    // can't get manipulators to compile
    //bool r;
    //wistringstream(ws) >> ios_base::boolalpha >> r;
    //wistringstream(ws) >> setiosflags(ios_base::boolalpha) >> r;
    // but even if compiling, this seems to return true for empty strings:
    //wistringstream wss(ws);
    //wss.flags(ios_base::boolalpha);
    //wss >> r;

    // this works but isn't worth the overhead:
    //#include <cctype>
    //wstring t;
    //std::transform(ws.begin(), ws.end(), t.begin(),
    //               static_cast< int (*)(int) >(std::tolower));

    bool val;
    if (ws.length() == 0) {
        val = vdefault;
    } else {
        // short & simple
        val = ((ws.length() == 4)
               && (ws[0] == L'T' || ws[0] == L't')
               && (ws[1] == L'R' || ws[1] == L'r')
               && (ws[2] == L'U' || ws[2] == L'u')
               && (ws[3] == L'E' || ws[3] == L'e'));
    }
    return val;
}

/**
 * Parses a wide character string as a (signed) decimal integer.
 *
 * Returns the integral value of a wide character string, the default value
 * if the string is empty, or the error value if the conversion has failed.
 */
template< typename I >
inline I
toI(const wstring& ws, I vdefault, I verror)
{
    I val;
    if (ws.length() == 0) {
        val = vdefault;
    } else {
        wistringstream wiss(ws);
        wiss >> val;
        if (wiss.fail() || !wiss.eof()) {
            val = verror;
        }
    }
    return val;
}

inline int
toInt(const wstring& ws, int vdefault, int verror)
{
    return toI< int >(ws, vdefault, verror);
}

/**
 * Returns the character representation of an int.
 */
inline string
toString(int i)
{
    // JNI crashes with gcc & operator<<(ostream &, long/int)
    //std::ostringstream o;
    //o << i;
    //return o.str();
    char s[256];
    snprintf(s, 256, "%d", i);
    return string(s);
}

/**
 * Returns a multi-byte representation of a wide-character string.
 * 
 * XXX document semantics since this conversion ignores any
 * character set encodings...
 * This function is not very efficient in that it involves multiple
 * copying operations.
 */
inline string
toString(const wstring& ws) 
{
    //sprintf(charptr,"%ls",wsdtring.c_str()); 
    string s(ws.begin(), ws.end());
    return s;
}

/**
 * Returns a string representation of all elements in the set.
 * 
 * This function is not very efficient in that it involves multiple
 * copying operations.
 */
inline string
toString(const set< string >& s)
{
    string r;
    r += "[";
    set< string >::iterator i = s.begin();
    if (i != s.end()) {
        r += "\"";
        r += *i;
        r += "\"";
        while (++i != s.end()) {
            r += ", \"";
            r += *i;
            r += "\"";
        }
    }
    r += "]";
    return r;
}    

} // utils

#endif // string_helpers_hpp
