#include "StringUtils.hpp"
#include <string.h>           // strcoll()

// Uncomment the following if strcoll() does not do its comparisons
// case-insensitive in your locale.
//#define convert_to_lower_case


bool char_is_of( const char& c, const string& s) {
  return s.find( c)!=string::npos;
}

StringTokenizer::StringTokenizer( const string& s, const string& delimiters, const string& delimiter_escapes, string::size_type startPos) 
: s( s),
  delimiters( delimiters),
  delimiter_escapes( delimiter_escapes),
  currentPos( startPos),
  at_end( false)
{
}

bool StringTokenizer::hasMoreTokens() {
  return ( !at_end && 
           ( s.find_first_not_of( delimiters, currentPos) != string::npos));
}

string StringTokenizer::getNextToken() {
  string::size_type begin,   // erstes Zeichen des Tokens
                    end;     // Zeichen nach dem Token
  string token;
//  cerr << "*** " << currentPos << endl;
//  bool within_token= false;
  
  begin= s.find_first_not_of( delimiters, currentPos);
  if (begin!=string::npos) {                     // Token gefunden
    end= begin;
    
    again:
    end= s.find_first_of( delimiters, end);
    if ( end != string::npos && end >= 1 && char_is_of( s[end-1], delimiter_escapes)) 
      goto again;
      
    if (end==string::npos) {                     // s endet genau mit diesem Token
      token= s.substr( begin);
      at_end= true;
    }
    else {
      token= s.substr( begin, end-begin);
      currentPos= end;
    }
  }
  return token;
}

//---------------




int icompare( const string& s1_, const string& s2_) {
// seems we do not need to lower-case the characters... 
// strcoll() compares case-insensitive in (at least) the de_DE locale.
#ifdef convert_to_lower_case
  string s1= s1_, s2= s2_;
  string::size_type  i= 0, end;
  end= (s1.size() <= s2.size()) ? s1.size() : s2.size();
  while ( i < end ) {
    s1[i]= toupper( s1[i]);
    s2[i]= toupper( s2[i]);
    ++i;
  }
  int res= strcoll( s1.c_str(), s2.c_str());
#else
  int res= strcoll( s1_.c_str(), s2_.c_str());
#endif
//  cerr << s1 << "\t" << s2 << "\t" << res << endl;
  return res;
}

string align( string s, string::size_type length, short int alignment) {
  
  string::size_type fill= 0;
  if (length >= s.size()) fill= length - s.size();
  
  switch (alignment) {
    case FRONT:  s.append( fill, ' ');  break;
    case CENTER: { 
      string::size_type at_front= fill / 2;
      s.insert( (string::size_type) 0, at_front, ' ');
      s.append( fill - at_front, ' ');
      break;
    }
    case BACK:   s.insert( (string::size_type) 0, fill, ' ');  break;
  }
  return s;
}

// string LocalizedNumberString( long int num) {
//   
//    struct lconv *  locale_conventions= localeconv();
//   string result= numString( num);
//   
//   const int group_length= 3;
//   int pos= result.size()-group_length;
//   while ( pos > 0) {
//     result.insert( pos, locale_conventions->thousands_sep);
//     pos -= 3;
//   }
//   return result;
// } 
