Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

message.h

Go to the documentation of this file.
00001 #ifndef DV_NET_SNDRCV_H 00002 #define DV_NET_SNDRCV_H 00003 // $Id: message.h,v 1.9 2003/07/07 11:25:37 dvermeir Exp $ 00004 #include <strstream> 00005 #include <string> 00006 #include <iostream> 00007 #include <stdexcept> 00008 00009 namespace Dv { 00010 namespace Net { 00011 00012 /** 00013 * A SimpleMessage wraps a byte array which it may or may not 00014 * own. A SimpleMessage can be sent to a stream and it can 00015 * received from a stream. The protocol ensures that any 00016 * byte array can be transferred. 00017 */ 00018 class SimpleMessage { 00019 public: 00020 /** 00021 * Constructor. 00022 * \param data pointer to byte array. 00023 * \param size of byte array 00024 * \warning The array will not be copied and the message will 00025 * not be its owner. 00026 */ 00027 SimpleMessage(const char* data = 0, size_t size = 0): 00028 data_(data), size_(size), owner_(false) {}; 00029 /** 00030 * Destructor. Delete the data if we are the owner. 00031 */ 00032 virtual ~SimpleMessage() { 00033 if (owner_) 00034 delete data_; 00035 } 00036 00037 /** \return pointer to data char array \warning this is not a C 00038 * string, see SimpleMessage::size */ 00039 const char* data() const { return data_; } 00040 /** \return size of data array */ 00041 const size_t size() const { return size_; } 00042 00043 /** 00044 * Send data byte-array. 00045 * The following protocol is used: 00046 * @code 00047 * size-of-encoded-byte-array <newline> encoded-byte-array 00048 * @endcode 00049 * Test stream status to find out whether the operation succeeded. 00050 * @param os stream to send to. 00051 * @return os 00052 * @sa SimpleMessage::receive 00053 */ 00054 std::ostream& send(std::ostream& os) const; 00055 /** 00056 * Receive data byte-array sent by SimpleMessage::send. 00057 * @param is stream to receive data from. 00058 * @return is 00059 * @sa SimpleMessage::send 00060 * @exception runtime_error upon any error 00061 * @warning the message will become the owner of the byte array. 00062 */ 00063 std::istream& receive(std::istream& is) throw (std::runtime_error); 00064 00065 protected: 00066 /** 00067 * Replace underlying byte array. 00068 * \param p new byte array 00069 * \param size of new byte array 00070 * \return p 00071 * \warning the message will not be the owner of the new byte array. 00072 */ 00073 const char* data(const char* p, size_t size); 00074 /** 00075 * Replace byte array by a newly allocated array of size bytes. 00076 * Note that the returned pointer is not const, so the derived class 00077 * can update the byte array. 00078 * \param size of new byte array 00079 * \return pointer to newly allocated byte array. 00080 * \warning The message owns the new byte array, so the derived 00081 * class should not delete it. 00082 */ 00083 char* data(size_t size); 00084 private: 00085 const char* data_; 00086 size_t size_; 00087 bool owner_; // are we owner of data_ 00088 }; 00089 00090 /** 00091 * Template extension of SimpleMessage. Using this template, anything 00092 * that can be printed (using \c operator>>) can be sent and anything 00093 * that can be read using \c operator<< can be received. 00094 * The template parameter type also needs a default constructor. 00095 */ 00096 template<typename T> 00097 class Message: public SimpleMessage { 00098 public: 00099 /** Constructor. Stores output of <code>operator<<(std::ostream&, const T&)</code>) */ 00100 Message(const T& t = T()) throw (std::runtime_error) { 00101 if (! (oss_ << t) ) 00102 throw std::runtime_error("Message<T>::Message(const T&) cannot store T object"); 00103 data(oss_.str(), oss_.pcount()); 00104 } 00105 /** Destructor. */ 00106 ~Message() { 00107 oss_.freeze(0); 00108 } 00109 /** Reconstruct <code>T</code> by reading from stringstream on data */ 00110 operator T() const throw (std::runtime_error) { 00111 std::istrstream iss(data(), size()); 00112 T t; 00113 if ( ! (iss >> t) ) // this will not work for string 00114 throw std::runtime_error("Message<T>::operator T() cannot read T object"); 00115 return t; 00116 } 00117 private: 00118 std::ostrstream oss_; 00119 }; 00120 00121 /** 00122 * Specialization for string. 00123 * \sa Message<T> 00124 */ 00125 template<> 00126 class Message<std::string>: public SimpleMessage { 00127 public: 00128 /** Constructor. Simply stores string. */ 00129 Message(const std::string& s) { 00130 data(s.data(), s.size()); 00131 } 00132 /** Destructor. */ 00133 ~Message() {} 00134 /** Reconstruct string. */ 00135 operator std::string() const { return std::string(data(), size()); } 00136 }; 00137 00138 00139 }} 00140 00141 inline std::ostream& 00142 operator<<(std::ostream& os, const Dv::Net::SimpleMessage& m) { 00143 return m.send(os); 00144 } 00145 00146 inline std::istream& 00147 operator>>(std::istream& is, Dv::Net::SimpleMessage& m) throw (std::runtime_error) { 00148 return m.receive(is); 00149 } 00150 00151 #endif

dvnet-0.9.11 [27 December, 2004]