#ifndef __MString_h__
#define __MString_h__

#include "ZString.h"
#include <iostream>
#include <sstream>
#include <ostream>

namespace coreutils {
   
   ///
   /// Use the MString object when you need a permanent backing store on the heap
   /// for a ZString style functionality. Because MString has a backing store we
   /// added functionalities to build strings as well as the parsing power of the
   /// ZString.
   ///
   
   class MString : public ZString {
      
    public:
      ///
      ///
      ///
      
      MString();
      
      ///
      ///
      ///
      
      MString(const char *data);
      MString(void *alias);
      
      ///
      /// Consructor providing the initial setup of the MString object.
      ///
      
      MString(unsigned char *data, size_t length);
      
      MString(const char *data, size_t length);
      
      MString(const unsigned char *data, size_t length);

//      MString (ZString zstring);
      
      ///
      /// Consructor providing a copy of a ZString.
      ///
      
      MString (ZString &zstring);
      MString (const ZString &zstring);

      ///
      /// Consructor providing a copy of a ZString.
      ///
      
      MString(MString &mstring);
      
//      MString(MString mstring);
      
      ///
      /// Consructor providing a copy of a MString.
      ///
      
      MString(const MString &mstring);
      
      ///
      /// Consructor from a string.
      ///
      
      MString(std::string data);
      
      ///
      ///
      ///
      
      MString(char *data, size_t length);
      
      ///
      ///
      ///
      
      MString(std::FILE *file);

      ///
      ///
      ///

      MString(double value);
      
      ///
      ///
      ///
      
      virtual ~MString();
      
//      ~MString();
      
      ///
      /// Assignment operator will copy data to backing store.
      ///
      
      //      MString& operator=(coreutils::ZString& data);
      
      ///
      /// Assignment operator will copy data to backing store.
      ///

      MString &operator=(coreutils::MString data);
      MString &operator=(coreutils::ZString value);

      MString &operator=(std::string value);

      ///
      /// Assignment operator will copy data to backing store.
      ///
      
      MString &operator=(const char *data);
      
      ///
      /// Assignment operator will copy data to backing store.
      ///
      
      MString &operator=(char data);
      
      ///
      /// Assignment operator for saving a double value..
      ///
      
      MString &operator=(double value);
      
      ///
      /// Assignment operator for saving an integer value..
      ///
      
      MString &operator=(int value);
      
      ///
      ///
      ///
      
      MString &operator<<(const char *value);

      ///
      ///
      ///
      
      MString &operator<<(const int value);
      
      ///
      ///
      ///
      
      MString &operator<<(coreutils::ZString zstring);

      ///
      ///
      ///
      
      MString &operator<<(char value);

      ///
      ///
      ///
      
//      MString &operator<<(std::ostream (*f)(std::ostream&) );
      MString &operator<<(std::basic_ostream<char> (*pf)(std::basic_ostream<char>&));

      ///
      /// 
      ///

      MString &operator<<(std::ifstream &pf);

      ///
      /// 
      ///

      MString &operator<<(std::ostream &out);
      
      ///
      ///
      ///
      
      void insert(char ch, int offset);

      ///
      ///
      ///
      
      void insert(ZString value, int offset);

      ///
      ///
      ///
      
//      void insert(std::string value, int offset);
      
      ///
      ///
      ///
      
      void replace(char ch, int offset);

      ///
      ///
      ///
      
      void replace(ZString &value, int offset);

      ///
      ///
      ///

      void replace(std::string value, int offset);
      
      ///
      /// Remove specified number of characters at cursor.
      ///
      
      void remove(int length);

      ///
      /// Remove specified nummber of characters from specified offset.
      ///
      
      void remove(int offset, int length);
      
      ///
      ///
      ///
      
      MString &write(char ch);
      
      ///
      ///
      ///
      
      MString &write(ZString value);

      ///
      /// Read data from a socket and store in MString.
      ///

      MString &read(int fd);
      MString &read(int fd, int len);
      
      ///
      ///
      ///
      
      int offset();

      ///
      ///
      ///
      
      MString toBinary();

      ///
      ///
      ///

      MString fromBinary();

      ///
      ///
      ///

      MString toHex();

      ///
      ///
      ///

      MString fromHex();

      ///
      ///
      ///

      MString toBase64();

      ///
      ///
      ///

      MString fromBase64();

      ///
      ///
      ///

      MString toUpper();

      ///
      ///
      ///


      MString toLower();

      ///
      ///
      ///

      MString toCGI();

      ///
      ///
      ///

      MString fromCGI();

    protected:
      void setSize(int size);

      ///
      /// This method is called whenever a change is made to the MString storage.
      ///

      virtual void onChange();
      
    private:
      int bufferSize = 0;
      char hexChar(char c);
      
   };
   
}

#endif
