#ifndef _STRINGUTILS_H
#define _STRINGUTILS_H

#include <stdio.h>
#include <string.h>

#ifdef g29
#include <hash_set>
#else
#include <ext/hash_set>
#endif

#include <iostream>

using std::string;
using std::ostream;
using std::istream;
using std::vector;

/*
  A utility class that is used to manage strings/chars
  
KEYWORDS
  string

AUTHORS
  Oranit Dror (mailto: oranit@tau.ac.il)

  Copyright: SAMBA group, Tel-Aviv Univ. Israel, 2002.

CHANGES LOG
<UL>
<LI>
07.11.07 Oranit Dror
Adding the 'toUpperCase' method
Addition of eqstr struct for string comparison with STL
</LI>
<LI>
18.04.07 Alex
added stringSplit method
</LI>
<LI>
<LI>
12.06.05 Dina
added isBlankLine method
</LI>
<LI>
7.11.04 Alex Shulman
getLine changed to be a template to support gzipped stream of type gzstream
</LI>
<LI>
17.05.04 Dina Duhovny and Oranit Dror
Fixing a bug in the getLine method (in the previous version EOF was
read)    
</LI>
<LI>
13.06.04 M.Shatsky. 
added functions:
static string l2str(long l)
static string d2str(double d)
static string getLine(istream &istr)
</LI>
</UL>

*/

#ifndef g29
namespace __gnu_cxx
{
  using std::size_t;
  
  template<> struct hash< string>
  {
    size_t operator()(const string& __s) const { 
      return __stl_hash_string(__s.c_str()); }
  };
}
#endif

// for STL string comparison
struct eqstr
{
  bool operator()(const char* s1, const char* s2) const
  {
    return strcmp(s1, s2) == 0;
  }
};

class StringUtils{
public:

  //// 
  // Trims spaces at the left side of a string
  static inline string trim_left(const string& str )
  {
    unsigned int i=str.find_first_not_of(" \t");
    if(str.size()==0 || i >= str.size())
      return str;
    return str.substr( i ) ;
  }
 
  ////
  // Trims spaces at the right side of a string
  static inline string trim_right(const string& str )
  {
    unsigned int i=str.find_last_not_of(" \t");
    if(str.size()==0 || i >= str.size())
      return str;
    return str.substr(0, i + 1);
  }
  
  //// 
  // Trims spaces at both sides of a string
  static inline string trim(const string& str )
  {
    return trim_left(trim_right(str));
  }
 
  //// turns all the string to upper case
  static string toUpperCase(const string& s);

  ////
  // return a string, which is the concatenation of s2 to s1
  static char* concat(const char* const s1,
                      const char* const s2);


  ////
  // reverse the order of the given chars
  static void reverse(char *s);

  //// Erases chars from a stream
  static void eraseLine(ostream& i_s,int size=80);
  
  //// Splits a given line by the given delimiter
  static void stringSplit(const string str, string delim, vector< string>&  results);

  //// Reads a line from an input stream (till EOF or \n)
  template< class StreamT>
  static string getLine(StreamT& istr);

  //// Return true if the line is empty or spaces and tabs only
  static bool isBlankLine(const char *const line);

  //// converts long into string
  static string l2str(long l);
  
  //// converts double into string
  static string d2str(double d);
};

//// Reads a line from an input stream (till EOF or \n)
template< class StreamT>
string StringUtils::getLine(StreamT& istr){
  string o_str;
  char c;

  while (istr.get(c)) {
    if(c != '\n') {
      o_str.append(1, c);
    } else
      break;
  };
  
  return o_str;
  }

#endif //_STRINGUTILS_H

