#ifndef _utl_StringCompare_h_
#define _utl_StringCompare_h_

#include <string>
#include <algorithm>
#include <cctype>


namespace utl {

  /**
    \class CharEqualNoCase StringCompare.h utl/StringCompare.h
    \brief Utility class to compare characters in a case-independent way.

    This class is a predicate to be used in a string comparison. The
    comparison is done using the standard tolower function, which implies that
    the locale is taken into account.

    \author Lukas Nellen
    \date   22-Aug-2008
    \ingroup stl
  */
  class CharEqualNoCase : public std::binary_function<const char, const char, bool> {
    public:
      bool operator()(const char a, const char b) const
      { return std::tolower(a) == std::tolower(b); }
  };

  /** \brief Utility to compare strings for equivalence.
      It takes a predicate to determine the equivalence of individual
      characters.
  */
  template<class Predicate>
  inline
  bool
  StringEquivalent(const std::string& a, const std::string& b, Predicate p)
  {
    return a.size() == b.size() &&
      std::equal(a.begin(), a.end(), b.begin(), p);
  }

  /** \brief Utility to compare strings for equivalence.
      The two-argument variant internally uses the predicate \c CharEqualNoCase,
      which implements case-insensitive equivalence.
  */
  inline
  bool
  StringEquivalent(const std::string& a, const std::string& b)
  {
    return StringEquivalent(a, b, CharEqualNoCase());
  }

  /** \brief Utility to search for a substring within a string according to
   *  a given search predicate.
   */
  template <class Predicate>
  inline
  bool
  ContainsSubstring(const std::string& a, const std::string& b, Predicate p)
  {
    return std::search(a.begin(), a.end(), b.begin(), b.end(), p) != a.end();
  }

  /** \brief Syntactic sugar for searching within a string for a substring.
      Search is case-sensitive.
   */
  inline
  bool
  ContainsSubstring(const std::string& a, const std::string& b)
  {
    return ContainsSubstring(a, b, std::equal_to<char>());
  }

  /** \brief Syntactic sugar for searching within a string for a substring.
      Search is case-insensitive.
   */
  inline
  bool
  ContainsSubstringEquivalent(const std::string& a, const std::string& b)
  {
    return ContainsSubstring(a, b, CharEqualNoCase());
  }

}

#endif