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