# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

mem_stream.cpp

Go 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