#ifndef _STRING_INCLUDED
#define _STRING_INCLUDED
#include <stdlib.h>
#include <string.h>
namespace std
{
  class string
  {
    char* data;
  public:
    string() {data=(char*)malloc(1);data[0]=0;}
    string(const char* a)
    {
      int len=strlen(a)+1;
      data=(char*)malloc(len);
      memcpy(data,a,len);
    }
    string(char c)
    {
      data=(char*)malloc(2);
      data[0]=c;data[1]=0;
    }
    string(const string& s)
    {
      unsigned sz = s.size()+1;
      data=(char*)malloc(sz);
      memcpy(data,s.c_str(),sz);
    }
    ~string() {free(data);}
    string& operator=(const char* s)
    {free(data);unsigned len=strlen(s)+1;data=(char*)malloc(len);
    memcpy(data,s,len);return *this;}
    string& operator=(const string& s)
    {free(data);unsigned len=s.size()+1;data=(char*)malloc(len);
    memcpy(data,s.c_str(),len);return *this;}
    const char* c_str() const {return data;}
    char& operator[](unsigned pos) {return data[pos];}
    char operator[](unsigned pos) const {return data[pos];}
    unsigned size() const {return strlen(data);}
    unsigned length() const {return size();}
    bool operator==(const char* str2) const {return !strcmp(data,str2);}
    bool operator==(const string& str2) const {return !strcmp(data,str2.data);}
    int compare(const char* str2) {return strcmp(data,str2);}
    bool operator!=(const char* str2) const {return (bool)strcmp(data,str2);}
    string& replace(unsigned p0,unsigned n0,const string& str)
    {
      unsigned sz = str.size();
      char* newdata=(char*)malloc(size()+1+sz-n0);
      memcpy(newdata,data,p0);
      memcpy(newdata+p0,str.c_str(),sz);
      memcpy(newdata+p0+sz,data+p0+n0,size()+1-p0-n0);
      free(data);
      data=newdata;
      return *this;
    }
    string& insert(size_t posl,const string& str)
    { return replace(posl,0,str); }
    string& operator+=(char c)
    {
      unsigned sz=size();
      data=(char*)realloc(data,sz+2);
      data[sz]=c;data[sz+1]=0;
      return *this;
    }
    string& operator+=(const string& s)
    {
      unsigned mysz=size();
      unsigned ssz=s.size();
      data=(char*)realloc(data,mysz+1+ssz);
      memcpy(data+mysz,s.c_str(),ssz+1);
      return *this;
    }
//    friend string operator+(const string& s1, const char* s2);
//    friend string operator+(const char* s1, const string& s2);
    string& assign(const string& str, unsigned pos, unsigned n)
    {
      unsigned len=strlen(str.data);
      if (pos>len)
        pos=len;
      if (n>len||pos+n>len)
        n=len-pos;
      char* d=(char*)malloc(n+1);
      memcpy(d,str.c_str()+pos,n);
      d[n]=0;
      free(data);
      data=d;
      return *this;
    }
    string& assign(const char* s)
    {
      free(data);
      unsigned sz=strlen(s)+1;
      data=(char*)malloc(sz);
      memcpy(data,s,sz);
      return *this;
    }
    string& assign(const string& str)
    { return assign(str.data); }
    size_t find_first_of(const char* str, size_t pos=0) const
    {
      const char* p = data;
      while (pos)
      {
        if (!*p)
          return npos;
        p++;
        pos--;
      }
      while (*p)
      {
        if (strchr(str,*p))
          return p-data;
        p++;
      }
      return npos;
    }
    size_t find_first_of(const string& str, size_t pos=0) const
    { return find_first_of(str.data, pos); }
    size_t find_first_not_of(const char* str, size_t pos=0) const
    {
      const char* p = data;
      while (pos)
      {
        if (!*p)
          return npos;
        p++;
        pos--;
      }
      while (*p)
      {
        if (!strchr(str,*p))
          return p-data;
        p++;
      }
      return npos;
    }
    size_t find_first_not_of(const string& str, size_t pos=0) const
    { return find_first_not_of(str.data, pos); }
    size_t find_last_not_of(const char* str, size_t pos=npos) const
    {
      const char* p = data;
      while (pos)
      {
        if (!*p)
        {
          p--;
          break;
        }
        p++;
        pos--;
      }
      for (;;)
      {
        if (p<data)
          return npos;
        if (!strchr(str,*p))
          return p-data;
        p--;
      }
    }
    size_t find_last_not_of(const string& str, size_t pos=npos) const
    { return find_last_not_of(str.data, pos); }
    class iterator
    {
      char* cur;
    public:
      iterator(char* c):cur(c) {}
      iterator(const iterator& i):cur(i.cur) {}
      iterator& operator++() {++cur;return *this;}
      iterator operator++(int) {iterator tmp(*this);++cur;return tmp;}
      bool operator==(iterator it) {return cur==it.cur;}
      bool operator!=(iterator it) {return cur!=it.cur;}
      char& operator*() {return *cur;}
    };
    iterator begin() {return iterator(data);}
    iterator end() {return iterator(data+strlen(data));}
//    void erase() {free(data);data=(char*)malloc(1);data[0]=0;}
    string& erase(unsigned p0=0, unsigned n=(unsigned)-1)
    {
      unsigned sz=size();
      if (n>sz-p0) n=sz-p0;
      char* d=(char*)malloc(sz+1-n);
      memcpy(d,data,p0);
      memcpy(d+p0,data+p0+n,sz+1-n-p0);
      free(data);
      data=d;
      return *this;
    }
    typedef unsigned size_type;
    static const size_type npos=(size_type)-1;
    size_type find(const char* s, size_type pos=0) const
    {
      char* p=strstr(data+pos,s);
      if (!p) return npos;
      return p-data;
    }
    size_type find(char c, size_type pos=0) const
    {
      char* p=strchr(data+pos,c);
      if (!p) return npos;
      return p-data;
    }
    size_type rfind(char c, size_type pos=npos) const
    {
      size_type len=strlen(data);
      if (pos>len)
        pos=len;
      while (pos--)
        if (data[pos]==c)
          return pos;
      return npos;
    }
    string substr(unsigned pos=0,unsigned n=npos)
    {
      string res(data+pos);
      if (n<res.size()) res.erase(n);
      return res;
    }
    void clear(void)
    {
      data[0]=0;
    }
    bool empty(void) const
    {
      return (data[0]==0);
    }
    void _toupper(void)
    { strupr(data); }
    void _tolower(void)
    { strlwr(data); }
  };
}

inline std::string operator+(const std::string& s1, const char* s2)
{
  std::string res(s1);
  res += s2;
  return res;
}
inline std::string operator+(const char* s1, const std::string& s2)
{
  std::string res(s1);
  res += s2;
  return res;
}
inline std::string operator+(const std::string& s1, const std::string& s2)
{
  std::string res(s1);
  res += s2;
  return res;
}

#endif
