#ifndef _BSSTREAM_H
#define _BSSTREAM_H

#include <list>

namespace text_tools {

using namespace std;

class bstringstream {
   list< char > buffer;

   void cpy(char * ptr, size_t size) {
      for(size_t i = 0; i < size; i++, ptr++) {
         buffer.push_back(*ptr); 
      } 
   }

   void read(char * ptr, size_t size) {
      for(size_t i = 0; i < size; i++, ptr++) {
         *ptr = buffer.front();
         buffer.pop_front();
      } 
   }

public:
   bstringstream() {
   }

   bstringstream(const bstringstream & cp) {
      buffer = cp.buffer;
   }

   bstringstream(char * buffer, size_t sz) {
      cpy(buffer, sz);
   }

   ~bstringstream() {
       buffer.clear();
   }

   bstringstream & operator=(const bstringstream & cp) {
      buffer = cp.buffer;
      return *this;
   }

   size_t size() const {
      return buffer.size();
   }

   list< char > & get_data() {
       return buffer;
   }

   char * get_new_buffer() const {
      char * ret = new char [ buffer.size() ];
      char * p = ret;
      
      for(list< char >::const_iterator ptr = buffer.begin(); ptr != buffer.end(); ptr++, p++) {
         *p = *ptr;
      }
      
      return ret;
   }

   bstringstream & operator<<(const long l) {
      char * ptr = (char*)&l;
      cpy(ptr, sizeof(long));
      return *this;
   }

   bstringstream & operator<<(const int l) {
      char * ptr = (char*)&l;
      cpy(ptr, sizeof(int));
      return *this;
   }

   bstringstream & operator<<(const float l) {
      char * ptr = (char*)&l;
      cpy(ptr, sizeof(float));
      return *this;
   }

   bstringstream & operator<<(const double l) {
      char * ptr = (char*)&l;
      cpy(ptr, sizeof(double));
      return *this;
   }

   bstringstream & operator<<(const short l) {
      char * ptr = (char*)&l;
      cpy(ptr, sizeof(short));
      return *this;
   }

   bstringstream & operator<<(const char l) {
      char * ptr = (char*)&l;
      cpy(ptr, sizeof(char));
      return *this;
   }

   bstringstream & operator<<(const unsigned long l) {
      char * ptr = (char*)&l;
      cpy(ptr, sizeof(unsigned long));
      return *this;
   }

   bstringstream & operator<<(const unsigned int l) {
      char * ptr = (char*)&l;
      cpy(ptr, sizeof(unsigned int));
      return *this;
   }

   bstringstream & operator<<(const unsigned short l) {
      char * ptr = (char*)&l;
      cpy(ptr, sizeof(unsigned short));
      return *this;
   }

   bstringstream & operator<<(const unsigned char l) {
      char * ptr = (char*)&l;
      cpy(ptr, sizeof(unsigned char));
      return *this;
   }

   bstringstream & operator<<(const bool l) {
      char * ptr = (char*)&l;
      cpy(ptr, sizeof(bool));
      return *this;
   }

   bstringstream & operator<<(const string & l) {
      size_t sz = l.size() + 1;
      char * ptr = (char*)&sz;
      cpy(ptr, sizeof(size_t));
      cpy((char*)l.c_str(), l.size());
      char ch[1] = { '\0' };
      cpy(ch, 1);
      return *this;
   }

   bstringstream & operator>>(string & str) {
      size_t sz = 0U;
      read((char*)&sz, sizeof(size_t));
      char * buffer = new char[sz];
      read(buffer, sz);
      str = buffer;
      delete [] buffer;
      return *this;
   }

   bstringstream & operator>>(const unsigned int & ival) {
      read((char*)&ival, sizeof(unsigned int));
      return *this;
   }

   void write(ostream & out) {
      char * buf = get_new_buffer();
      out.write(buf, buffer.size());
      delete [] buf;
   }
};

}

#endif /* _BSSTREAM_H */
