stream.cpp
Engine/source/core/stream/stream.cpp
Public Defines
define
IMPLEMENT_ENDIAN_OVERLOADED_READ(type) bool (type* out_read) \ { \ type temp; \ bool = read(sizeof(type), &temp); \ *out_read = convertLEndianToHost(temp); \ return ; \ }
define
IMPLEMENT_ENDIAN_OVERLOADED_WRITE(type) bool (type in_write) \ { \ type temp = convertHostToLEndian(in_write); \ return write(sizeof(type), &temp); \ }
define
IMPLEMENT_OVERLOADED_READ(type) bool (type* out_read) \ { \ return read(sizeof(type), out_read); \ }
define
IMPLEMENT_OVERLOADED_WRITE(type) bool (type in_write) \ { \ return write(sizeof(type), &in_write); \ }
Detailed Description
Public Defines
IMPLEMENT_ENDIAN_OVERLOADED_READ(type) bool (type* out_read) \ { \ type temp; \ bool = read(sizeof(type), &temp); \ *out_read = convertLEndianToHost(temp); \ return ; \ }
IMPLEMENT_ENDIAN_OVERLOADED_WRITE(type) bool (type in_write) \ { \ type temp = convertHostToLEndian(in_write); \ return write(sizeof(type), &temp); \ }
IMPLEMENT_OVERLOADED_READ(type) bool (type* out_read) \ { \ return read(sizeof(type), out_read); \ }
IMPLEMENT_OVERLOADED_WRITE(type) bool (type in_write) \ { \ return write(sizeof(type), &in_write); \ }
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "core/color.h" 25#include "core/util/rawData.h" 26#include "core/frameAllocator.h" 27#include "platform/platformNet.h" 28 29#include "core/stream/stream.h" 30 31#include "core/stringTable.h" 32#include "core/strings/stringFunctions.h" 33 34#include "core/util/byteBuffer.h" 35#include "core/util/endian.h" 36#include "core/util/str.h" 37 38 39#define IMPLEMENT_OVERLOADED_READ(type) \ 40 bool Stream::read(type* out_read) \ 41 { \ 42 return read(sizeof(type), out_read); \ 43 } 44 45#define IMPLEMENT_OVERLOADED_WRITE(type) \ 46 bool Stream::write(type in_write) \ 47 { \ 48 return write(sizeof(type), &in_write); \ 49 } 50 51#define IMPLEMENT_ENDIAN_OVERLOADED_READ(type) \ 52 bool Stream::read(type* out_read) \ 53 { \ 54 type temp; \ 55 bool success = read(sizeof(type), &temp); \ 56 *out_read = convertLEndianToHost(temp); \ 57 return success; \ 58 } 59 60#define IMPLEMENT_ENDIAN_OVERLOADED_WRITE(type) \ 61 bool Stream::write(type in_write) \ 62 { \ 63 type temp = convertHostToLEndian(in_write); \ 64 return write(sizeof(type), &temp); \ 65 } 66 67IMPLEMENT_OVERLOADED_WRITE(S8) 68IMPLEMENT_OVERLOADED_WRITE(U8) 69 70IMPLEMENT_ENDIAN_OVERLOADED_WRITE(S16) 71IMPLEMENT_ENDIAN_OVERLOADED_WRITE(S32) 72IMPLEMENT_ENDIAN_OVERLOADED_WRITE(U16) 73IMPLEMENT_ENDIAN_OVERLOADED_WRITE(U32) 74IMPLEMENT_ENDIAN_OVERLOADED_WRITE(U64) 75IMPLEMENT_ENDIAN_OVERLOADED_WRITE(F32) 76IMPLEMENT_ENDIAN_OVERLOADED_WRITE(F64) 77 78IMPLEMENT_OVERLOADED_READ(S8) 79IMPLEMENT_OVERLOADED_READ(U8) 80 81IMPLEMENT_ENDIAN_OVERLOADED_READ(S16) 82IMPLEMENT_ENDIAN_OVERLOADED_READ(S32) 83IMPLEMENT_ENDIAN_OVERLOADED_READ(U16) 84IMPLEMENT_ENDIAN_OVERLOADED_READ(U32) 85IMPLEMENT_ENDIAN_OVERLOADED_READ(U64) 86IMPLEMENT_ENDIAN_OVERLOADED_READ(F32) 87IMPLEMENT_ENDIAN_OVERLOADED_READ(F64) 88 89 90Stream::Stream() 91 : m_streamStatus(Closed) 92{ 93} 94 95const char* Stream::getStatusString(const StreamStatus in_status) 96{ 97 switch (in_status) { 98 case Ok: 99 return "StreamOk"; 100 case IOError: 101 return "StreamIOError"; 102 case EOS: 103 return "StreamEOS"; 104 case IllegalCall: 105 return "StreamIllegalCall"; 106 case Closed: 107 return "StreamClosed"; 108 case UnknownError: 109 return "StreamUnknownError"; 110 111 default: 112 return "Invalid Stream::Status"; 113 } 114} 115 116void Stream::writeString(const char *string, S32 maxLen) 117{ 118 S32 len = string ? dStrlen(string) : 0; 119 if(len > maxLen) 120 len = maxLen; 121 122 write(U8(len)); 123 if(len) 124 write(len, string); 125} 126 127bool Stream::writeFormattedBuffer(const char *format, ...) 128{ 129 char buffer[4096]; 130 va_list args; 131 va_start(args, format); 132 const S32 length = dVsprintf(buffer, sizeof(buffer), format, args); 133 134 // Sanity! 135 AssertFatal(length <= sizeof(buffer), "writeFormattedBuffer - String format exceeded buffer size. This will cause corruption."); 136 137 return write(length, buffer); 138} 139 140void Stream::readString(char buf[256]) 141{ 142 U8 len; 143 read(&len); 144 read(S32(len), buf); 145 buf[len] = 0; 146} 147 148const char *Stream::readSTString(bool casesens) 149{ 150 char buf[256]; 151 readString(buf); 152 return StringTable->insert(buf, casesens); 153} 154 155void Stream::readLongString(U32 maxStringLen, char *stringBuf) 156{ 157 U32 len; 158 read(&len); 159 if(len >= maxStringLen) 160 { 161 m_streamStatus = IOError; 162 return; 163 } 164 read(len, stringBuf); 165 stringBuf[len] = 0; 166} 167 168void Stream::writeLongString(U32 maxStringLen, const char *string) 169{ 170 U32 len = dStrlen(string); 171 if(len > maxStringLen) 172 len = maxStringLen; 173 write(len); 174 write(len, string); 175} 176 177void Stream::readLine(U8 *buffer, U32 bufferSize) 178{ 179 bufferSize--; // account for NULL terminator 180 U8 *buff = buffer; 181 U8 *buffEnd = buff + bufferSize; 182 *buff = '\r'; 183 184 // strip off preceding white space 185 while ( *buff == '\r' ) 186 { 187 if ( !read(buff) || *buff == '\n' ) 188 { 189 *buff = 0; 190 return; 191 } 192 } 193 194 // read line 195 while ( buff != buffEnd && read(++buff) && *buff != '\n' ) 196 { 197 if ( *buff == '\r' ) 198 { 199 200#if defined(TORQUE_OS_MAC) 201 U32 pushPos = getPosition(); // in case we need to back up. 202 if (read(buff)) // feeling free to overwrite the \r as the NULL below will overwrite again... 203 if (*buff != '\n') // then push our position back. 204 setPosition(pushPos); 205 break; // we're always done after seeing the CR... 206#else 207 buff--; // 'erases' the CR of a CRLF 208#endif 209 210 } 211 } 212 *buff = 0; 213} 214 215void Stream::writeText(const char *text) 216{ 217 if (text && text[0]) 218 write(dStrlen(text), text); 219} 220 221void Stream::writeLine(const U8 *buffer) 222{ 223 write(dStrlen((const char *)buffer), buffer); 224 write(2, "\r\n"); 225} 226 227void Stream::_write(const String & str) 228{ 229 U32 len = str.length(); 230 231 if (len<255) 232 write(U8(len)); 233 else 234 { 235 // longer string, write full length 236 write(U8(255)); 237 238 // fail if longer than 16 bits (will truncate string modulo 2^16) 239 AssertFatal(len < (1<<16),"String too long"); 240 241 len &= (1<<16)-1; 242 write(U16(len)); 243 } 244 245 write(len,str.c_str()); 246} 247 248void Stream::_read(String * str) 249{ 250 U16 len; 251 252 U8 len8; 253 read(&len8); 254 if (len8==255) 255 read(&len); 256 else 257 len = len8; 258 259 char * buffer = (char*)FrameAllocator::alloc(len); 260 read(len, buffer); 261 *str = String(buffer,len); 262} 263 264 265bool Stream::write(const ColorI& rColor) 266{ 267 bool success = write(rColor.red); 268 success |= write(rColor.green); 269 success |= write(rColor.blue); 270 success |= write(rColor.alpha); 271 272 return success; 273} 274 275bool Stream::write(const LinearColorF& rColor) 276{ 277 ColorI temp = LinearColorF(rColor).toColorI(); 278 return write(temp); 279} 280 281bool Stream::read(ColorI* pColor) 282{ 283 bool success = read(&pColor->red); 284 success |= read(&pColor->green); 285 success |= read(&pColor->blue); 286 success |= read(&pColor->alpha); 287 288 return success; 289} 290 291bool Stream::read(LinearColorF* pColor) 292{ 293 ColorI temp; 294 bool success = read(&temp); 295 296 *pColor = temp; 297 return success; 298} 299 300bool Stream::write(const NetAddress &na) 301{ 302 bool success = write(na.type); 303 success &= write(na.port); 304 success &= write(sizeof(na.address), &na.address); 305 return success; 306} 307 308bool Stream::read(NetAddress *na) 309{ 310 bool success = read(&na->type); 311 success &= read(&na->port); 312 success &= read(sizeof(na->address), &na->address); 313 return success; 314} 315 316bool Stream::write(const NetSocket &so) 317{ 318 return write(so.getHandle()); 319} 320 321bool Stream::read(NetSocket* so) 322{ 323 S32 handle = -1; 324 bool success = read(&handle); 325 *so = NetSocket::fromHandle(handle); 326 return success; 327} 328 329bool Stream::write(const RawData &rd) 330{ 331 bool s = write(rd.size); 332 s &= write(rd.size, rd.data); 333 return s; 334} 335 336bool Stream::read(RawData *rd) 337{ 338 U32 size = 0; 339 bool s = read(&size); 340 341 rd->alloc(size); 342 s &= read(rd->size, rd->data); 343 344 return s; 345} 346 347bool Stream::write(const Torque::ByteBuffer &rd) 348{ 349 bool s = write(rd.getBufferSize()); 350 s &= write(rd.getBufferSize(), rd.getBuffer()); 351 return s; 352} 353 354bool Stream::read(Torque::ByteBuffer *rd) 355{ 356 U32 size = 0; 357 bool s = read(&size); 358 359 rd->resize(size); 360 s &= read(rd->getBufferSize(), rd->getBuffer()); 361 362 return s; 363} 364 365bool Stream::copyFrom(Stream *other) 366{ 367 U8 buffer[1024]; 368 U32 numBytes = other->getStreamSize() - other->getPosition(); 369 while((other->getStatus() != Stream::EOS) && numBytes > 0) 370 { 371 U32 numRead = numBytes > sizeof(buffer) ? sizeof(buffer) : numBytes; 372 if(! other->read(numRead, buffer)) 373 return false; 374 375 if(! write(numRead, buffer)) 376 return false; 377 378 numBytes -= numRead; 379 } 380 381 return true; 382} 383 384Stream* Stream::clone() const 385{ 386 return NULL; 387} 388