#ifndef STRINGCONVERT_H
#define STRINGCONVERT_H

#include <sstream>
using namespace std;

#include <typedefs.h>

/** String serialize by appending to a string with the 
  same syntax as the operator << (ostream &,T). 
  For example:
  string str; ... 
  str << "t=" << t << "\n";
*/
template< typename T >
string& operator << (string& str, T const & x);

// Functional conversion functions.
// These are more compact that the class stringconvert and code using them
// is easier to use.
// See also stringserialization.h

/** Convert from a string. int x; string s="35"; stringfrom(x,s); */
template< typename T >
void stringfrom(T & targ, stringc & str);
/** Convert to a string. string s; stringto(s,36); */
template< typename T >
void stringto(string & str, T const data);
/** Convert to a string. Function form of stringto. */
template< typename T >
stringc stringto(T const data);

/*!
\brief String helper functions. 
*/
class stringconvert
{
public:

  /** Convert from a data type to a string. */
  template <typename T>
  static stringc tostring(T const x)
  {
    stringstream ss;
    ss << x;
    return ss.str();
  }
  /** Convert or interpret from a string to a data type. */
  template< typename T>
  static void fromstring( T & x, stringc & s)
  {
    stringstream ss(s);
    ss >> x;
  }

  /** Repeated replace a string on the original source string. 
Taken from http://snipplr.com/view/1055/find-and-replace-one-string-with-another/ */
  static void findandreplace
  ( 
    string& source, 
    stringc & find, 
    stringc & replace 
  );

  /** Find and replace function. */
  static stringc findandreplacefn
  ( 
    stringc & source, 
    stringc & find, 
    stringc & replace 
  ); 

};

// Possible to expand. e.g. isstringhex, isstringip4 ...

// Characters and not numerical values tested!
// Remove white space around string.

/** Is the string digits only? */
boolc isstringdigits(stringc & str);
/** Is the string an integer? Not testing the
 value so 7.0 is not regared as an integer. */ 
boolc isstringinteger(stringc & str);
/** e.g. float or double >= zero. */
boolc isstringzero_or_positive_real(stringc & str);
/** Integers are a subset of the reals. */
boolc isstringreal(stringc & str);
/** Looks for negative sign and a real number. */
boolc isstringnegative(stringc & str);

/** Helper function to wrap data in tags. */
template< typename T >
stringc stringtag( T x, stringc & tag )
{
  string s1 = "<" + tag + ">";
  s1 += stringto(x);
  s1 += ( "</" + tag + ">\n");
  return s1;
}

//---------------------------------------------------------
//  Implementation.

template< typename T >
string& operator << (string& str, T const & x)
{
  stringstream ss;
  ss << x;
  str += ss.str(); 

  return str;
}

template< typename T >
void stringfrom(T & targ, stringc & str)
{
  stringstream ss(str);
  ss >> targ;
}  

template< typename T >
void stringto(string & str, T const data)
{
  stringstream ss;
  ss << data;
  str = ss.str();
}

template< typename T >
stringc stringto(T const data)
{
  stringstream ss;
  ss << data;
  return ss.str();
}




#endif


