#ifndef __pxx_string_hh__
#define __pxx_string_hh__

#include "pxx_common.hh"
#include "pxx_exception.hh"
#include "pxx_stream.hh"

namespace pxx
{

struct StringDataInfo
{
  unsigned ref_count ;
  size_t capacity ;
};

template <typename type_t>
class String
{

private:

  type_t* data ;
  StringDataInfo* datainfo ;
  size_t length ;

public:

  String (size_t _length = 0) ;
  String (type_t const* _s, const_t _const = non_const_data) ;
  String (type_t const* _s, size_t _len, const_t _const = non_const_data) ;
  String (String const& _s) ;
  ~String () ;
  String& operator = (String const& _s) ;

  type_t const* get_data () const ;

  String operator + (String const& _s) const ;
  String& operator << (String const& _s) ;
  String substring (size_t _from, size_t _len) const ;
  void replace (size_t _from, String const& _s) ;
  String head (size_t _len) const ;
  String tail (size_t _from) const ;
  type_t const& operator [] (size_t _index) const ;
  type_t& operator [] (size_t _index) ;
  size_t get_length () const ;
  size_t get_capacity () const ;

  template<typename _type_t>
  friend Stream& operator << (Stream& _stream, String<_type_t> _s) ;

private:

  void deconstify () ;
  void expand (size_t _extra) ;
  static inline size_t compute_length (type_t const* _strdata) ;

public:

  class NonTerminated :
    public Exception
  {
  public:
    void print()
      { fprintf(stderr, "String data is not null terminated\n"); }
  };

};

//template class String<char> ;
typedef String<char> CString ;
//template class String<wchar_t> ;
typedef String<wchar_t> WString ;

}

#endif // __pxx_string_hh__
