1 /* 2 * This file is part of Dune Legacy. 3 * 4 * Dune Legacy is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * Dune Legacy is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with Dune Legacy. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #ifndef ENETPACKETOSTREAM_H 19 #define ENETPACKETOSTREAM_H 20 21 #include <misc/OutputStream.h> 22 23 #include <enet/enet.h> 24 25 #include <string> 26 27 class ENetPacketOStream : public OutputStream 28 { 29 public: ENetPacketOStream(enet_uint32 flags)30 explicit ENetPacketOStream(enet_uint32 flags) 31 : currentPos(0) { 32 packet = enet_packet_create(nullptr,16,flags); 33 if(packet == nullptr) { 34 THROW(OutputStream::error, "ENetPacketOStream: enet_packet_create() failed!"); 35 } 36 } 37 ENetPacketOStream(const ENetPacketOStream & p)38 ENetPacketOStream(const ENetPacketOStream& p) 39 : currentPos(0), packet(nullptr) { 40 *this = p; 41 } 42 ~ENetPacketOStream()43 ~ENetPacketOStream() { 44 if(packet != nullptr) { 45 enet_packet_destroy(packet); 46 } 47 } 48 49 ENetPacketOStream& operator=(const ENetPacketOStream& p) { 50 if(this != &p) { 51 ENetPacket* packetCopy = enet_packet_create(p.packet->data,p.packet->dataLength,p.packet->flags); 52 if(packetCopy == nullptr) { 53 THROW(InputStream::error, "ENetPacketOStream::operator=(): enet_packet_create() failed!"); 54 } 55 56 if(packet != nullptr) { 57 enet_packet_destroy(packet); 58 } 59 60 packet = packetCopy; 61 currentPos = p.currentPos; 62 } 63 64 return *this; 65 } 66 getPacket()67 ENetPacket* getPacket() { 68 if(enet_packet_resize(packet,currentPos) < 0) { 69 THROW(OutputStream::error, "ENetPacketOStream::getPacket(): enet_packet_resize() failed!"); 70 } 71 72 ENetPacket* pPacket = packet; 73 74 packet = nullptr; 75 76 return pPacket; 77 } 78 flush()79 void flush() { 80 ; 81 } 82 83 84 // write operations 85 writeString(const std::string & str)86 void writeString(const std::string& str) { 87 ensureBufferSize(currentPos + str.length() + sizeof(Uint32)); 88 89 writeUint32(str.length()); 90 91 if(!str.empty()) { 92 memcpy(packet->data + currentPos, str.c_str(), str.length()); 93 currentPos += str.length(); 94 } 95 } 96 97 writeUint8(Uint8 x)98 void writeUint8(Uint8 x) { 99 ensureBufferSize(currentPos + sizeof(Uint8)); 100 *((Uint8*) (packet->data + currentPos)) = x; 101 currentPos += sizeof(Uint8); 102 } 103 writeUint16(Uint16 x)104 void writeUint16(Uint16 x) { 105 ensureBufferSize(currentPos + sizeof(Uint16)); 106 *((Uint16*) (packet->data + currentPos)) = SDL_SwapLE16(x); 107 currentPos += sizeof(Uint16); 108 } 109 writeUint32(Uint32 x)110 void writeUint32(Uint32 x) { 111 ensureBufferSize(currentPos + sizeof(Uint32)); 112 *((Uint32*) (packet->data + currentPos)) = SDL_SwapLE32(x); 113 currentPos += sizeof(Uint32); 114 } 115 writeUint64(Uint64 x)116 void writeUint64(Uint64 x) { 117 ensureBufferSize(currentPos + sizeof(Uint64)); 118 *((Uint64*) (packet->data + currentPos)) = SDL_SwapLE64(x); 119 currentPos += sizeof(Uint64); 120 } 121 writeBool(bool x)122 void writeBool(bool x) { 123 writeUint8(x == true ? 1 : 0); 124 } 125 writeFloat(float x)126 void writeFloat(float x) { 127 Uint32 tmp; 128 memcpy(&tmp,&x,sizeof(Uint32)); // workaround for a strange optimization in gcc 4.1 129 writeUint32(tmp); 130 } 131 ensureBufferSize(size_t minBufferSize)132 void ensureBufferSize(size_t minBufferSize) { 133 if(minBufferSize < packet->dataLength) { 134 return; 135 } 136 137 size_t newBufferSize = ((packet->dataLength * 3) / 2); 138 if(newBufferSize < minBufferSize) { 139 newBufferSize = minBufferSize; 140 } 141 142 if(enet_packet_resize(packet,newBufferSize) < 0) { 143 THROW(OutputStream::error, "ENetPacketOStream::ensureBufferSize(): enet_packet_resize() failed!"); 144 } 145 } 146 147 148 private: 149 size_t currentPos; 150 ENetPacket* packet; 151 }; 152 153 #endif // ENETPACKETOSTREAM_H 154