/*
 *  Copyright (c) 2008-2009 Cyrille Berger <cberger@cberger.net>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * either version 2, or (at your option) any later version of the License.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#ifndef _CAUCHY_STRING_H_
#define _CAUCHY_STRING_H_

#include <string>
#include <list>
#include <vector>

namespace Cauchy {
  /**
   * String class which provides convenient function on top of \ref std::string .
   * @ingroup Cauchy
   */
  class String {
    public:
      /**
       * Construct an empty string.
       */
      String();
      /**
       * Construct a \ref String from a single character.
       */
      String(char );
      /**
       * Construct a \ref String from a C string.
       */
      String(const char* );
      /**
       * Construct a \ref String from a C++ string.
       */
      String(const std::string& );
      /**
       * Construct a \ref String from an other \ref String .
       */
      String(const String& );
      String& operator=(const String& );
      ~String();
    public:
      /**
       * Append a C string to the current \ref String, and return it the
       * result.
       */
      String& append(const char* );
      /**
       * Append a C++ string to the current \ref String, and return the
       * result.
       */
      String& append(const std::string& );
      /**
       * Append a \ref String to the current \ref String, and return the
       * result.
       */
      String& append(const String& );
    public:
      /**
       * Replace all occurences of \ref pat with \ref rep .
       */
      String& replace(const String& pat, const String& rep);
    public:
      const char* c_str() const;
      /**
       * Attempt to convert the string to an integer.
       */
      int toInt() const;
      /**
       * Attempt to convert the string to a float.
       */
      float toFloat() const;
      /**
       * @return the n first characters
       */
      String head(int n) const;
      /**
       * @return the n last characters
       */
      String tail(int n) const;
      /**
       * @return a lower case version of the string.
       */
      String toLower() const;
      /**
       * @return a upper case version of the string.
       */
      String toUpper() const;
      /**
       * Split the \ref String along the given separators
       * @param _separators list of separators given in a string (one character for one separator)
       * @return a list of \ref String
       */
      std::vector<String> split( const String& _separators, bool _allowEmpty = false) const;
      /**
       * Split the \ref String along the given separators
       * @param _separators the list of separators
       * @return a list of \ref String
       */
      std::vector<String> split( const std::list<String>& _separators, bool _allowEmpty = false) const;
      /**
       * @return true if this \ref String starts with \a _sw .
       */
      bool startWith(const Cauchy::String& _sw) const;
      bool endWith(const Cauchy::String& _sw) const;
      /**
       * @return a string without space at beginning or end
       */
      String trimmed() const;
    public:
      String& operator=(char c);
      String& operator+=(const String& s);
      String operator+(const char* _rhs) const;
      String operator+(const String& _rhs) const;
      bool operator==(const char* _rhs) const;
      bool operator==(const String& _rhs) const;
      bool operator!=(const char* _rhs) const;
      bool operator!=(const String& _rhs) const;
      bool operator<(const String& _rhs) const;
      operator const std::string& () const;
      char operator[](std::size_t idx) const;
    public:
      /**
       * @return the length of the string
       */
      std::size_t length() const;
      String substr(std::size_t _pos, std::size_t __n ) const;
      bool isEmpty() const;
    public:
      /**
       * @return a \ref String containing the number
       */
      static String number(int );
      /**
       * @return a \ref String containing the number
       */
      static String number(unsigned int );
      /**
       * @return a \ref String containing the number
       */
      static String number(float );
      /**
       * @return a \ref String containing the number
       */
      static String number(double );
    private:
      inline void deref();
      struct Private;
      Private* d;
  };
  String operator+(const char* arg1, const String& arg2);
  bool operator==(const char* arg1, const String& arg2);
  std::ostream& operator<< (std::ostream& ostr, const String& string);
  
}

#endif
