Home | nevrax.com |
|
mem_stream.cppGo to the documentation of this file.00001 00007 /* Copyright, 2000 Nevrax Ltd. 00008 * 00009 * This file is part of NEVRAX NEL. 00010 * NEVRAX NEL is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2, or (at your option) 00013 * any later version. 00014 00015 * NEVRAX NEL is distributed in the hope that it will be useful, but 00016 * WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 * General Public License for more details. 00019 00020 * You should have received a copy of the GNU General Public License 00021 * along with NEVRAX NEL; see the file COPYING. If not, write to the 00022 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, 00023 * MA 02111-1307, USA. 00024 */ 00025 00026 #include "stdmisc.h" 00027 00028 #include "nel/misc/mem_stream.h" 00029 00030 namespace NLMISC 00031 { 00032 00033 00034 /* 00035 * Initialization constructor 00036 */ 00037 /*CMemStream::CMemStream( bool inputStream, bool stringmode, uint32 defaultcapacity ) : 00038 NLMISC::IStream( inputStream ), _StringMode( stringmode ) 00039 { 00040 _Buffer.resize (std::max( defaultcapacity, (uint32)4 )); // prevent from no allocation 00041 _BufPos = _Buffer.getPtr(); 00042 // _Buffer.reserve( std::max( defaultcapacity, (uint32)4 ) ); // prevent from no allocation 00043 // _BufPos = _Buffer.begin(); 00044 } 00045 */ 00046 00047 /* 00048 * Copy constructor 00049 */ 00050 /*CMemStream::CMemStream( const CMemStream& other ) : 00051 IStream (other) 00052 { 00053 operator=( other ); 00054 } 00055 */ 00056 00057 /* 00058 * Assignment operator 00059 */ 00060 /*CMemStream& CMemStream::operator=( const CMemStream& other ) 00061 { 00062 IStream::operator= (other); 00063 _Buffer = other._Buffer; 00064 _BufPos = _Buffer.getPtr() + other.lengthS(); 00065 _StringMode = other._StringMode; 00066 return *this; 00067 } 00068 */ 00069 00070 /* 00071 * serial (inherited from IStream) 00072 */ 00073 void CMemStream::serialBuffer(uint8 *buf, uint len) 00074 { 00075 // commented for optimum performance 00076 nlassert (len > 0); 00077 nlassert (buf != NULL); 00078 00079 if ( isReading() ) 00080 { 00081 // Check that we don't read more than there is to read 00082 if ( lengthS()+len > lengthR() ) 00083 { 00084 throw EStreamOverflow(); 00085 } 00086 // Serialize in 00087 CFastMem::memcpy( buf, _BufPos, len ); 00088 _BufPos += len; 00089 } 00090 else 00091 { 00092 // Serialize out 00093 00094 increaseBufferIfNecessary (len); 00095 /* uint32 oldBufferSize = _Buffer.size(); 00096 if (_BufPos - _Buffer.getPtr() + len > oldBufferSize) 00097 { 00098 // need to increase the buffer size 00099 uint32 pos = _BufPos - _Buffer.getPtr(); 00100 _Buffer.resize(oldBufferSize*2 + len); 00101 _BufPos = _Buffer.getPtr() + pos; 00102 } 00103 */ 00104 CFastMem::memcpy( _BufPos, buf, len ); 00105 _BufPos += len; 00106 00107 /* _Buffer.resize( size ); 00108 _BufPos = _Buffer.end() - len; 00109 CFastMem::memcpy( &(*_BufPos), buf, len ); 00110 _BufPos = _Buffer.end();*/ 00111 } 00112 } 00113 00114 /* 00115 * serialBit (inherited from IStream) 00116 */ 00117 void CMemStream::serialBit(bool &bit) 00118 { 00119 /* if ( _StringMode ) 00120 { 00121 */ uint8 u; 00122 if ( isReading() ) 00123 { 00124 serial( u ); 00125 bit = (u!=0); 00126 } 00127 else 00128 { 00129 u = (uint8)bit; 00130 serial( u ); 00131 } 00132 /* } 00133 else 00134 { 00135 uint len = sizeof(uint8); 00136 uint8 thebuf; 00137 00138 if ( isReading() ) 00139 { 00140 // Check that we don't read more than there is to read 00141 if ( lengthS()+len > lengthR() ) 00142 { 00143 throw EStreamOverflow(); 00144 } 00145 // Serialize in 00146 memcpy( &thebuf, &(*_BufPos), len ); 00147 _BufPos += len; 00148 bit = (thebuf!=0); 00149 } 00150 else 00151 { 00152 thebuf = (uint8)bit; 00153 // Serialize out 00154 _Buffer.resize( _Buffer.size() + len ); 00155 _BufPos = _Buffer.end() - len; 00156 memcpy( &(*_BufPos), &thebuf, len ); 00157 _BufPos = _Buffer.end(); 00158 } 00159 }*/ 00160 } 00161 00162 00163 /* 00164 * seek (inherited from IStream) 00165 */ 00166 bool CMemStream::seek (sint32 offset, TSeekOrigin origin) throw(EStream) 00167 { 00168 switch (origin) 00169 { 00170 case begin: 00171 if (offset >= (sint)length()) 00172 return false; 00173 if (offset < 0) 00174 return false; 00175 _BufPos=_Buffer.getPtr()+offset; 00176 break; 00177 case current: 00178 if (getPos ()+offset >= (sint)length()) 00179 return false; 00180 if (getPos ()+offset < 0) 00181 return false; 00182 _BufPos+=offset; 00183 break; 00184 case end: 00185 if (offset < -(sint)length()) 00186 return false; 00187 if (offset > 0) 00188 return false; 00189 _BufPos=_Buffer.getPtr()+_Buffer.size()+offset; 00190 break; 00191 } 00192 return true; 00193 } 00194 00195 00196 /* 00197 * getPos (inherited from IStream) 00198 */ 00199 /*sint32 CMemStream::getPos () throw(EStream) 00200 { 00201 return _BufPos - _Buffer.getPtr(); 00202 // if (_Buffer.getPtr() == NULL) 00203 // return 0; 00204 // else 00205 // return (sint32)&(_BufPos[0])-(sint32)&(_Buffer[0]); 00206 00207 } 00208 */ 00209 00210 /* 00211 * Clears the message 00212 */ 00213 /*void CMemStream::clear() 00214 { 00215 resetPtrTable(); 00216 _Buffer.clear(); 00217 _BufPos = _Buffer.getPtr(); 00218 } 00219 */ 00220 00221 void CMemStream::resize (uint32 size) 00222 { 00223 if (size == length()) return; 00224 // need to increase the buffer size 00225 uint32 pos = _BufPos - _Buffer.getPtr(); 00226 _Buffer.resize(size); 00227 _BufPos = _Buffer.getPtr() + pos; 00228 } 00229 00230 /* 00231 * Fills the message buffer 00232 */ 00233 /*void CMemStream::fill( const uint8 *srcbuf, uint32 len ) 00234 { 00235 if (len == 0) return; 00236 00237 _Buffer.resize( len ); 00238 _BufPos = _Buffer.getPtr(); 00239 CFastMem::memcpy( _BufPos, srcbuf, len ); 00240 } 00241 */ 00242 00243 /* EXPERIMENTAL: Returns a pointer to the message buffer for filling by an external function (use at your own risk, 00244 * you MUST fill the number of bytes you specify in "msgsize"). 00245 * This method prevents from doing one useless buffer copy, using fill(). 00246 */ 00247 /*uint8 *CMemStream::bufferToFill( uint32 msgsize ) 00248 { 00249 if (msgsize == 0) return NULL; 00250 00251 // Same as fill() but the memcpy is done by an external function 00252 _Buffer.resize( msgsize ); 00253 _BufPos = _Buffer.getPtr(); 00254 return _BufPos; 00255 } 00256 */ 00257 00258 /* 00259 * Transforms the message from input to output or from output to input 00260 */ 00261 /*void CMemStream::invert() 00262 { 00263 if ( isReading() ) 00264 { 00265 // In->Out: We want to write (serialize out) what we have read (serialized in) 00266 resetPtrTable(); 00267 setInOut( false ); 00268 // _BufPos = _Buffer.end(); 00269 } 00270 else 00271 { 00272 // Out->In: We want to read (serialize in) what we have written (serialized out) 00273 resetPtrTable(); 00274 setInOut( true ); 00275 _BufPos = _Buffer.getPtr(); 00276 } 00277 } 00278 */ 00279 00280 00281 00282 /*** String-specific methods ***/ 00283 00284 00285 //const char SEPARATOR = ' '; 00286 //const int SEP_SIZE = 1; // the code is easier to read with that 00287 00288 00289 00290 /* 00291 * Input: read from the stream until the next separator, and return the number of bytes read. The separator is then skipped. 00292 */ 00293 uint CMemStream::serialSeparatedBufferIn( uint8 *buf, uint len ) 00294 { 00295 nlassert( _StringMode && isReading() ); 00296 00297 // Check that we don't read more than there is to read 00298 if ( ( _BufPos == _Buffer.getPtr()+_Buffer.size() ) || // we are at the end 00299 ( lengthS()+len+SEP_SIZE > lengthR() ) && (_Buffer[_Buffer.size()-1] != SEPARATOR ) ) // we are before the end 00300 { 00301 throw EStreamOverflow(); 00302 } 00303 // Serialize in 00304 uint32 i = 0; 00305 while ( (i<len) && (*_BufPos) != SEPARATOR ) 00306 { 00307 *(buf+i) = *_BufPos; 00308 i++; 00309 _BufPos++; 00310 } 00311 // Exceeds len 00312 if ( (*_BufPos) != SEPARATOR ) 00313 { 00314 throw EStreamOverflow(); 00315 } 00316 _BufPos += SEP_SIZE; 00317 return i; 00318 } 00319 00320 00321 /* 00322 * Output: writes len bytes from buf into the stream 00323 */ 00324 void CMemStream::serialSeparatedBufferOut( uint8 *buf, uint len ) 00325 { 00326 nlassert( _StringMode && (!isReading()) ); 00327 00328 // Serialize out 00329 uint32 oldBufferSize = _Buffer.size(); 00330 if (_BufPos - _Buffer.getPtr() + (len + SEP_SIZE) > oldBufferSize) 00331 { 00332 // need to increase the buffer size 00333 _Buffer.resize(oldBufferSize*2 + len + SEP_SIZE); 00334 _BufPos = _Buffer.getPtr() + oldBufferSize; 00335 } 00336 00337 CFastMem::memcpy( _BufPos, buf, len ); 00338 _BufPos += len; 00339 *(_BufPos++) = SEPARATOR; 00340 00341 // Serialize out 00342 /* _Buffer.resize( _Buffer.size() + len + SEP_SIZE ); 00343 _BufPos = _Buffer.end() - len - SEP_SIZE; 00344 CFastMem::memcpy( &(*_BufPos), buf, len ); 00345 _Buffer[_Buffer.size()-1] = SEPARATOR; 00346 _BufPos = _Buffer.end(); 00347 */} 00348 00349 /* 00350 // Input 00351 #define readnumber(dest,thetype,digits,convfunc) \ 00352 char number_as_cstring [digits+1]; \ 00353 uint realdigits = serialSeparatedBufferIn( (uint8*)&number_as_cstring, digits ); \ 00354 number_as_cstring[realdigits] = '\0'; \ 00355 dest = (thetype)convfunc( number_as_cstring ); 00356 00357 // Output 00358 #define writenumber(src,format,digits) \ 00359 char number_as_cstring [digits+1]; \ 00360 sprintf( number_as_cstring, format, src ); \ 00361 serialSeparatedBufferOut( (uint8*)&number_as_cstring, strlen(number_as_cstring) ); 00362 */ 00363 00364 /* 00365 * atoihex 00366 */ 00367 /*inline int atoihex( const char* ident ) 00368 { 00369 int number; 00370 sscanf( ident, "%x", &number ); 00371 return number; 00372 } 00373 00374 inline uint32 atoui( const char *ident) 00375 { 00376 return (uint32) strtoul (ident, NULL, 10); 00377 } 00378 */ 00379 /***************************************************************/ 00380 /******************* THE FOLLOWING CODE IS COMMENTED OUT *******/ 00381 /*************************************************************** 00382 00383 // ====================================================================================================== 00384 void CMemStream::serial(uint8 &b) 00385 { 00386 if ( _StringMode ) 00387 { 00388 if ( isReading() ) 00389 { 00390 readnumber( b, uint8, 3, atoi ); // 255 00391 } 00392 else 00393 { 00394 writenumber( (uint16)b,"%hu", 3 ); 00395 } 00396 } 00397 else 00398 { 00399 fastSerial (b); 00400 } 00401 } 00402 00403 // ====================================================================================================== 00404 void CMemStream::serial(sint8 &b) 00405 { 00406 if ( _StringMode ) 00407 { 00408 if ( isReading() ) 00409 { 00410 readnumber( b, sint8, 4, atoi ); // -128 00411 } 00412 else 00413 { 00414 writenumber( (sint16)b, "%hd", 4 ); 00415 } 00416 } 00417 else 00418 { 00419 fastSerial (b); 00420 } 00421 } 00422 00423 // ====================================================================================================== 00424 void CMemStream::serial(uint16 &b) 00425 { 00426 if ( _StringMode ) 00427 { 00428 // No byte swapping in text mode 00429 if ( isReading() ) 00430 { 00431 readnumber( b, uint16, 5, atoi ); // 65535 00432 } 00433 else 00434 { 00435 writenumber( b, "%hu", 5 ); 00436 } 00437 } 00438 else 00439 { 00440 fastSerial (b); 00441 } 00442 } 00443 00444 // ====================================================================================================== 00445 void CMemStream::serial(sint16 &b) 00446 { 00447 if ( _StringMode ) 00448 { 00449 if ( isReading() ) 00450 { 00451 readnumber( b, sint16, 6, atoi ); // -32768 00452 } 00453 else 00454 { 00455 writenumber( b, "%hd", 6 ); 00456 } 00457 } 00458 else 00459 { 00460 fastSerial (b); 00461 } 00462 } 00463 00464 // ====================================================================================================== 00465 void CMemStream::serial(uint32 &b) 00466 { 00467 if ( _StringMode ) 00468 { 00469 if ( isReading() ) 00470 { 00471 readnumber( b, uint32, 10, atoui ); // 4294967295 00472 } 00473 else 00474 { 00475 writenumber( b, "%u", 10 ); 00476 } 00477 } 00478 else 00479 { 00480 fastSerial (b); 00481 } 00482 } 00483 00484 00485 // ====================================================================================================== 00486 void CMemStream::serial(sint32 &b) 00487 { 00488 if ( _StringMode ) 00489 { 00490 if ( isReading() ) 00491 { 00492 readnumber( b, sint32, 11, atoi ); // -2147483648 00493 } 00494 else 00495 { 00496 writenumber( b, "%d", 11 ); 00497 } 00498 } 00499 else 00500 { 00501 fastSerial (b); 00502 } 00503 } 00504 00505 // ====================================================================================================== 00506 void CMemStream::serial(uint64 &b) 00507 { 00508 if ( _StringMode ) 00509 { 00510 if ( isReading() ) 00511 { 00512 readnumber( b, uint64, 20, atoiInt64 ); // 18446744073709551615 00513 } 00514 else 00515 { 00516 writenumber( b, "%"NL_I64"u", 20 ); 00517 } 00518 } 00519 else 00520 { 00521 fastSerial (b); 00522 } 00523 } 00524 00525 // ====================================================================================================== 00526 void CMemStream::serial(sint64 &b) 00527 { 00528 if ( _StringMode ) 00529 { 00530 if ( isReading() ) 00531 { 00532 readnumber( b, sint64, 20, atoiInt64 ); // -9223372036854775808 00533 } 00534 else 00535 { 00536 writenumber( b, "%"NL_I64"d", 20 ); 00537 } 00538 } 00539 else 00540 { 00541 fastSerial (b); 00542 } 00543 } 00544 00545 // ====================================================================================================== 00546 void CMemStream::serial(float &b) 00547 { 00548 if ( _StringMode ) 00549 { 00550 if ( isReading() ) 00551 { 00552 readnumber( b, float, 128, atof ); // ? 00553 } 00554 else 00555 { 00556 writenumber( (double)b, "%f", 128 ); 00557 } 00558 } 00559 else 00560 { 00561 fastSerial (b); 00562 } 00563 } 00564 00565 // ====================================================================================================== 00566 void CMemStream::serial(double &b) 00567 { 00568 if ( _StringMode ) 00569 { 00570 if ( isReading() ) 00571 { 00572 readnumber( b, double, 128, atof ); // 00573 } 00574 else 00575 { 00576 writenumber( b, "%f", 128 ); 00577 } 00578 } 00579 else 00580 { 00581 fastSerial (b); 00582 } 00583 } 00584 00585 // ====================================================================================================== 00586 void CMemStream::serial(bool &b) 00587 { 00588 if ( _StringMode ) 00589 { 00590 serialBit(b); 00591 } 00592 else 00593 { 00594 #ifdef NL_LITTLE_ENDIAN 00595 if(isReading()) 00596 { 00597 IStream::serial( b ); 00598 } 00599 else 00600 { 00601 *(uint8*)_BufPos = b; 00602 _BufPos += sizeof(uint8); 00603 } 00604 #else // NL_LITTLE_ENDIAN 00605 IStream::serial( b ); 00606 #endif // NL_LITTLE_ENDIAN 00607 } 00608 } 00609 00610 00611 #ifndef NL_OS_CYGWIN 00612 // ====================================================================================================== 00613 void CMemStream::serial(char &b) 00614 { 00615 if ( _StringMode ) 00616 { 00617 char buff [2]; 00618 if ( isReading() ) 00619 { 00620 serialBuffer( (uint8*)buff, 2 ); 00621 b = buff[0]; 00622 } 00623 else 00624 { 00625 buff[0] = b; 00626 buff[1] = SEPARATOR; 00627 serialBuffer( (uint8*)buff, 2 ); 00628 } 00629 } 00630 else 00631 { 00632 fastSerial (b); 00633 } 00634 } 00635 #endif 00636 00637 // ====================================================================================================== 00638 void CMemStream::serial(std::string &b) 00639 { 00640 if ( _StringMode ) 00641 { 00642 sint32 len=0; 00643 // Read/Write the length. 00644 if(isReading()) 00645 { 00646 serial(len); 00647 nlassert( len<1000000 ); // limiting string size 00648 b.resize(len); 00649 } 00650 else 00651 { 00652 len= b.size(); 00653 serial(len); 00654 } 00655 00656 // Read/Write the string. 00657 for(sint i=0;i<len;i++) 00658 serialBuffer( (uint8*)&(b[i]), sizeof(b[i]) ); 00659 00660 char sep = SEPARATOR; 00661 serialBuffer( (uint8*)&sep, 1 ); 00662 } 00663 else 00664 { 00665 IStream::serial( b ); 00666 } 00667 } 00668 00669 00670 // ====================================================================================================== 00671 void CMemStream::serial(ucstring &b) 00672 { 00673 if ( _StringMode ) 00674 { 00675 sint32 len=0; 00676 // Read/Write the length. 00677 if(isReading()) 00678 { 00679 serial(len); 00680 b.resize(len); 00681 } 00682 else 00683 { 00684 len= b.size(); 00685 serial(len); 00686 } 00687 // Read/Write the string. 00688 for(sint i=0;i<len;i++) 00689 serialBuffer( (uint8*)&b[i], sizeof( sizeof(b[i]) ) ); 00690 00691 char sep = SEPARATOR; 00692 serialBuffer( (uint8*)&sep, 1 ); 00693 } 00694 else 00695 { 00696 IStream::serial( b ); 00697 } 00698 } 00699 00700 00701 // Specialisation of serialCont() for vector<bool> 00702 void CMemStream::serialCont(std::vector<bool> &cont) 00703 { 00704 sint32 len=0; 00705 if(isReading()) 00706 { 00707 serial(len); 00708 // special version for vector: adjut good size. 00709 contReset(cont); 00710 cont.reserve(len); 00711 00712 for(sint i=0;i<len;i++) 00713 { 00714 bool v; 00715 serial(v); 00716 cont.insert(cont.end(), v); 00717 } 00718 } 00719 else 00720 { 00721 len= cont.size(); 00722 serial(len); 00723 00724 std::vector<bool>::iterator it= cont.begin(); 00725 for(sint i=0;i<len;i++, it++) 00726 { 00727 bool b = *it; 00728 serial( b ); 00729 } 00730 } 00731 } 00732 00733 00734 // Serialisation in hexadecimal 00735 void CMemStream::serialHex(uint32 &b) 00736 { 00737 if ( _StringMode ) 00738 { 00739 if ( isReading() ) 00740 { 00741 readnumber( b, uint32, 10, atoihex ); // 4294967295 00742 } 00743 else 00744 { 00745 writenumber( b, "%x", 10 ); 00746 } 00747 } 00748 else 00749 { 00750 IStream::serial( b ); 00751 } 00752 } 00753 00754 ***************************************************************/ 00755 } 00756 00757 |