1 /* 2 * Message.h 3 * Created by Woody Zenfell, III on Sun Aug 31 2003. 4 */ 5 6 /* 7 Copyright (c) 2003, Woody Zenfell, III 8 9 Permission is hereby granted, free of charge, to any person obtaining a copy 10 of this software and associated documentation files (the "Software"), to deal 11 in the Software without restriction, including without limitation the rights 12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 copies of the Software, and to permit persons to whom the Software is 14 furnished to do so, subject to the following conditions: 15 16 The above copyright notice and this permission notice shall be included in 17 all copies or substantial portions of the Software. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 SOFTWARE. 26 */ 27 28 #ifndef MESSAGE_H 29 #define MESSAGE_H 30 31 #include <string.h> // memcpy 32 #include "SDL.h" 33 34 typedef Uint16 MessageTypeID; 35 36 class UninflatedMessage; 37 38 class Message 39 { 40 public: 41 virtual MessageTypeID type() const = 0; 42 43 // May return false or raise an exception on failed inflation 44 virtual bool inflateFrom(const UninflatedMessage& inUninflated) = 0; 45 46 // Caller must dispose of returned message via 'delete' 47 virtual UninflatedMessage* deflate() const = 0; 48 49 virtual Message* clone() const = 0; 50 ~Message()51 virtual ~Message() {} 52 53 protected: 54 }; 55 56 57 58 class UninflatedMessage : public Message 59 { 60 public: 61 enum { kTypeID = 0xffff }; 62 63 // If bytes are provided, this object takes ownership of them (does not copy). 64 // If no bytes are provided, this object creates a buffer of size inLength. 65 // Clients should write into the pointer returned by buffer(). 66 UninflatedMessage(MessageTypeID inType, size_t inLength, Uint8* inBytes = NULL) mType(inType)67 : mType(inType), mLength(inLength), mBuffer(inBytes) 68 { 69 if(mBuffer == NULL) 70 mBuffer = new Uint8[mLength]; 71 } 72 UninflatedMessage(const UninflatedMessage & inSource)73 UninflatedMessage(const UninflatedMessage& inSource) { copyToThis(inSource); } 74 75 UninflatedMessage& operator =(const UninflatedMessage& inSource) 76 { 77 if(&inSource != this) 78 copyToThis(inSource); 79 80 return *this; 81 } 82 type()83 MessageTypeID type() const { return kTypeID; } inflateFrom(const UninflatedMessage & inUninflated)84 bool inflateFrom(const UninflatedMessage& inUninflated) { *this = inUninflated; return true; } deflate()85 UninflatedMessage* deflate() const { return new UninflatedMessage(*this); } 86 clone()87 UninflatedMessage* clone() const { return new UninflatedMessage(*this); } 88 ~UninflatedMessage()89 ~UninflatedMessage() { delete [] mBuffer; } 90 inflatedType()91 MessageTypeID inflatedType() const { return mType; } length()92 size_t length() const { return mLength; } buffer()93 Uint8* buffer() { return mBuffer; } buffer()94 const Uint8* buffer() const { return mBuffer; } 95 96 private: copyToThis(const UninflatedMessage & inSource)97 void copyToThis(const UninflatedMessage& inSource) 98 { 99 mType = inSource.mType; 100 mLength = inSource.mLength; 101 mBuffer = new Uint8[mLength]; 102 memcpy(mBuffer, inSource.mBuffer, mLength); 103 } 104 105 MessageTypeID mType; 106 size_t mLength; 107 Uint8* mBuffer; 108 }; 109 110 111 112 class AIStream; 113 class AOStream; 114 115 class SmallMessageHelper : public Message 116 { 117 public: 118 bool inflateFrom(const UninflatedMessage& inUninflated); 119 UninflatedMessage* deflate() const; 120 121 protected: 122 virtual bool reallyInflateFrom(AIStream& inStream) = 0; 123 virtual void reallyDeflateTo(AOStream& inStream) const = 0; 124 125 private: 126 }; 127 128 129 130 class BigChunkOfDataMessage : public Message 131 { 132 public: 133 BigChunkOfDataMessage(MessageTypeID inType, const Uint8* inBuffer = NULL, size_t inLength = 0); BigChunkOfDataMessage(const BigChunkOfDataMessage & other)134 BigChunkOfDataMessage(const BigChunkOfDataMessage& other) : mLength(0), mBuffer(NULL) 135 { 136 mType = other.type(); 137 copyBufferFrom(other.buffer(), other.length()); 138 } 139 140 BigChunkOfDataMessage& operator =(const BigChunkOfDataMessage& other) 141 { 142 if(&other != this) 143 { 144 mType = other.type(); 145 copyBufferFrom(other.buffer(), other.length()); 146 } 147 148 return *this; 149 } 150 151 bool inflateFrom(const UninflatedMessage& inUninflated); 152 UninflatedMessage* deflate() const; type()153 MessageTypeID type() const { return mType; } 154 155 void copyBufferFrom(const Uint8* inBuffer, size_t inLength); 156 length()157 size_t length() const { return mLength; } buffer()158 Uint8* buffer() { return mBuffer; } buffer()159 const Uint8* buffer() const { return mBuffer; } 160 161 BigChunkOfDataMessage* clone() const; 162 163 ~BigChunkOfDataMessage(); 164 165 private: 166 MessageTypeID mType; 167 size_t mLength; 168 Uint8* mBuffer; 169 }; 170 171 172 173 template <typename tValueType> 174 class SimpleMessage : public SmallMessageHelper 175 { 176 public: 177 typedef tValueType ValueType; 178 SimpleMessage(MessageTypeID inType)179 SimpleMessage(MessageTypeID inType) 180 : mType(inType) 181 { 182 // Use default initializer for value 183 new (static_cast<void*>(&mValue)) tValueType(); 184 } 185 SimpleMessage(MessageTypeID inType,const tValueType & inValue)186 SimpleMessage(MessageTypeID inType, const tValueType& inValue) 187 : mType(inType), mValue(inValue) 188 { 189 } 190 clone()191 SimpleMessage<tValueType>* clone() const 192 { return new SimpleMessage<tValueType>(*this); } 193 type()194 MessageTypeID type() const { return mType; } 195 setValue(const tValueType & inValue)196 void setValue(const tValueType& inValue) { mValue = inValue; } value()197 const tValueType& value() const { return mValue; } 198 199 protected: reallyDeflateTo(AOStream & inStream)200 void reallyDeflateTo(AOStream& inStream) const 201 { 202 inStream << mValue; 203 } 204 reallyInflateFrom(AIStream & inStream)205 bool reallyInflateFrom(AIStream& inStream) 206 { 207 inStream >> mValue; 208 return true; 209 } 210 211 private: 212 MessageTypeID mType; 213 tValueType mValue; 214 }; 215 216 217 218 template <MessageTypeID tMessageType> 219 class DatalessMessage : public Message 220 { 221 public: 222 enum { kType = tMessageType }; 223 type()224 MessageTypeID type() const { return kType; } 225 inflateFrom(const UninflatedMessage & inUninflated)226 bool inflateFrom(const UninflatedMessage& inUninflated) 227 { 228 return inUninflated.inflatedType() == kType && inUninflated.length() == 0; 229 } 230 deflate()231 UninflatedMessage* deflate() const { return new UninflatedMessage(kType, 0); } 232 clone()233 DatalessMessage<tMessageType>* clone() const 234 { return new DatalessMessage<tMessageType>; } 235 }; 236 237 #endif // MESSAGE_H 238