#ifndef _UDP_STREAM_H
#define _UDP_STREAM_H

#include <iostream>
#include <string>
#include <sstream>

#include "udp.h"

namespace net_tools {

class datagram {
  char * buffer;
  size_t offset;
  size_t the_size;
public:
  datagram(const size_t & size) {
     offset = 0U; 
     this->the_size = size;
     buffer = new char[size];
     for(size_t i = 0; i < size; i++) 
        buffer[i] = '\0';
  }
  ~datagram() {
     delete [] buffer;
  }  
  datagram & operator<<(const string & str)  throw(const char *) {
     size_t i;
     if(str.size() > the_size) {
        throw "error: datagram data overflow...";
     }  
     else {
        for(i = 0; i < str.size() && offset < the_size; offset++, i++) {
           buffer[offset] = str[i];
        }  
     }
     return *this;
  }
  template< class T >
  datagram & operator<<(const T & val)  {
      stringstream st;
      st << val;
      string temp;
      st >> temp;
      temp = st.str();
      size_t i;
      for(i = 0;
         offset < the_size && i < temp.size();
         offset++, i++) { 
        buffer[offset] = temp[i];
      }
      return *this;
   }
   size_t size() const { return the_size; }
   char * ptr() const { return buffer; }
   void clear() { 
      for(size_t i = 0; i < the_size; i++) {
         buffer[i] = '\0';
      }
   }

   char & operator[](const size_t index) throw(const char*) {
     if(index > the_size)
        throw "bad datagram index...";
      return buffer[index];
   }
};


class udp_stream {
   string host;
   int port;
   udp_socket udp;
public:
   udp_stream(const string & host, 
              const int port,
              udp_socket::udp_type the_type)
   : udp(host, port, the_type) {
      this->host = host;
      this->port = port;
   }
   udp_stream & operator<<(const datagram & dat) {
      udp.send(dat.ptr(), dat.size());
      return *this;
   }
   udp_stream & operator>>(datagram & dat) {
      char * buffer = dat.ptr();
      udp.recive(buffer, dat.size());
      return *this;
   }
};

}

#endif /* _UDP_STREAEM_H */

