/***************************************************************************
                          SIMPLY POWERFUL TOOLKIT (SPTK)
                          CBuffer.h  -  description
                             -------------------
    begin                : Mon Apr 17 2000
    copyright            : (C) 2000-2006 by Alexey S.Parshin
    email                : alexeyp@gmail.com
 ***************************************************************************/

/***************************************************************************
   This library is free software; you can redistribute it and/or modify it 
   under the terms of the GNU Library General Public License as published by
   the Free Software Foundation; either version 2 of the License, or (at 
   your option) any later version.

   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 Library
   General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; if not, write to the Free Software Foundation, 
   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.

   Please report all bugs and problems to "alexeyp@gmail.com"
 ***************************************************************************/

#ifndef __CBUFFER_H__
#define __CBUFFER_H__

#include <sptk3/sptk.h>

#include <string>

namespace sptk {

   /// @addtogroup utility Utility Classes
   /// @{

   /// @brief Memory data buffer
   ///
   /// Generic buffer with a special memory-allocation strategy for effective append() operation 
	class SP_EXPORT CBuffer {
	protected:
		unsigned m_size;     ///< Allocated size of the buffer
		unsigned m_bytes;    ///< Actual size of the data in buffer
		char *   m_buffer;   ///< The buffer itself
	public:

      /// Default constructor creates an empty buffer.
      /// The return of the bytes() method will be 0.
      /// @param sz buffer size to be pre-allocated
		CBuffer(unsigned sz=16);

      /// Constructor creates a buffer from string.
      /// The string is copied inside the buffer.
      /// The return of the bytes() method will be the input string length.
      /// @param str const char *, input string
		CBuffer(const char *str);

      /// Constructor creates a buffer from string.
      /// The string is copied inside the buffer.
      /// The return of the bytes() method will be the input string length.
      /// @param str const std::string&, input string
		CBuffer(const std::string& str);

      /// Constructor creates a buffer from void *data.
      /// The data is copied inside the buffer.
      /// The return of the bytes() method will be the input data size.
      /// @param data void * data buffer
      /// @param sz data buffer size
		CBuffer(const void *data,unsigned sz);

      /// Copy constructor creates a buffer from another buffer.
      /// The data is copied inside the buffer.
      /// The return of the bytes() method will be the input data size.
      /// @param buffer CBuffer, data buffer
		CBuffer(const CBuffer& buffer);

      /// Destructor releases the allocated memory
		~CBuffer();

      /// Method data()
      /// @returns pointer on the data buffer.
		char *data() const { return m_buffer; }

      /// Method checkSize() checks if the current buffer size is enogh
      /// to fit in the sz (required memory size) bytes. Allocates memory
      /// if needed.
      /// @param sz required memory size
      /// @returns success (true) or failure (false)
		bool checkSize(unsigned sz);

      /// Method set() copies the external data of size sz into the current buffer.
      /// Allocates memory if needed.
      /// @param data external data buffer
      /// @param sz required memory size
      /// @returns success (true) or failure (false)
		void set(const char *data,unsigned sz);

      /// Method append() appends a single to the current buffer.
      /// Allocates memory if needed.
      /// @param ch single character
      /// @returns success (true) or failure (false)
		bool append(char ch);

      /// Method append() appends the external data of size sz to the current buffer.
      /// Allocates memory if needed.
      /// @param data external data buffer
      /// @param sz required memory size
      /// @returns success (true) or failure (false)
		bool append(const char *data,unsigned sz);

      /// Method append() appends the string to the current buffer.
      /// Allocates memory if needed.
      /// @param str std::string
      /// @returns success (true) or failure (false)
		bool append(const std::string& str) { return append(str.c_str(),str.length()); }

      /// Method reset() truncates the current buffer to the size sz.
      /// Deallocates unused memory if needed.
      /// @param sz the required data size in bytes
		void reset(unsigned sz=0);

      /// Method fill() fills the bytes() charcters in buffer with character ch.
      /// @param ch the charater to fill the buffer
		void fill(char ch);

      /// Returns thes size of memory allocated for the data buffer
      /// @returns buffer size 
		unsigned size()  const { return m_size;   }

      /// Returns the size of data in the data buffer
      /// @returns data size
		unsigned bytes() const { return m_bytes;  }

      /// Sets the size of the data buffer to b. This method
      /// simply sets the internal buffer size. It doesn't check anything
      /// so use it this caution.
      /// @param b the new size of the buffer
		void bytes(unsigned b) { m_bytes = b;     }

      /// Loads the buffer from file fileName.
      /// @param fileName std::string, the name of the input file
		void loadFromFile(std::string fileName);

      /// Saves the buffer to the file fileName.
      /// @param fileName std::string, the name of the output file
		void saveToFile(std::string fileName) const;

      /// Assigns from CBuffer
      /// @param b const CBuffer&, the buffer to assign from
      /// @returns this object
		CBuffer& operator = (const CBuffer& b);

      /// Assigns from CString
      /// @param str const std::string&, the string to assign from
      /// @returns this object
		CBuffer& operator = (const std::string& str);

      /// Assigns from char *
      /// @param str const char *, the string to assign from
      /// @returns this object
		CBuffer& operator = (const char *str);
	};
	/// @}
}
#endif
