# 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  

string_stream.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 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 "nel/misc/string_stream.h"
00027 
00028 #include <vector>
00029 
00030 namespace NLMISC {
00031 
00032 
00033 const char SEPARATOR = ' ';
00034 const int SEP_SIZE = 1; // the code is easier to read with that
00035 
00036 
00037 
00038 /*
00039  * Input: read from the stream until the next separator, and return the number of bytes read. The separator is then skipped.
00040  */
00041 uint CStringStream::serialSeparatedBufferIn( uint8 *buf, uint len )
00042 {
00043         nlassert( isReading() );
00044 
00045         // Check that we don't read more than there is to read
00046         if ( ( _BufPos == _Buffer.end() ) || // we are at the end
00047                  ( lengthS()+len+SEP_SIZE > lengthR() ) && (_Buffer[_Buffer.size()-1] != SEPARATOR ) ) // we are before the end
00048         {
00049                 throw EStreamOverflow();
00050         }
00051         // Serialize in
00052         uint32 i = 0;
00053         while ( (i<len) && (*_BufPos) != SEPARATOR )
00054         {
00055                 *(buf+i) = *_BufPos;
00056                 i++;
00057                 _BufPos++;
00058         }
00059         // Exceeds len
00060         if ( (*_BufPos) != SEPARATOR )
00061         {
00062                 throw EStreamOverflow();
00063         }
00064         _BufPos += SEP_SIZE;
00065         return i;
00066 }
00067 
00068 /*
00069  * Output: writes len bytes from buf into the stream
00070  */
00071 void CStringStream::serialSeparatedBufferOut( uint8 *buf, uint len )
00072 {
00073         nlassert( ! isReading() );
00074         
00075         // Serialize out
00076         _Buffer.resize( _Buffer.size() + len + SEP_SIZE );
00077         _BufPos = _Buffer.end() - len - SEP_SIZE;
00078         memcpy( &(*_BufPos), buf, len );
00079         _Buffer[_Buffer.size()-1] = SEPARATOR;
00080         _BufPos = _Buffer.end();
00081 }
00082 
00083 
00084 // Input
00085 #define readnumber(dest,thetype,digits,convfunc) \
00086         char number_as_cstring [digits+1]; \
00087         uint realdigits = serialSeparatedBufferIn( (uint8*)&number_as_cstring, digits ); \
00088         number_as_cstring[realdigits] = '\0'; \
00089         dest = (thetype)convfunc( number_as_cstring );
00090 
00091 // Output
00092 #define writenumber(src,format,digits) \
00093         char number_as_cstring [digits+1]; \
00094         sprintf( number_as_cstring, format, src ); \
00095         serialSeparatedBufferOut( (uint8*)&number_as_cstring, strlen(number_as_cstring) );
00096 
00098 
00099 /*
00100  * atoihex
00101  */
00102 inline int atoihex( const char* ident )
00103 {
00104         int number;
00105         sscanf( ident, "%x", &number );
00106         return number;
00107 }
00108 
00109 inline uint32 atoui( const char *ident)
00110 {
00111         return (uint32) strtoul (ident, NULL, 10);
00112 }
00113 
00114 // ======================================================================================================
00115 void            CStringStream::serial(uint8 &b) 
00116 {
00117         if ( isReading() )
00118         {
00119                 readnumber( b, uint8, 3, atoi ); // 255
00120         }
00121         else
00122         {
00123                 writenumber( (uint16)b,"%hu", 3 );
00124         }
00125 }
00126 
00127 // ======================================================================================================
00128 void            CStringStream::serial(sint8 &b) 
00129 {
00130         if ( isReading() )
00131         {
00132                 readnumber( b, sint8, 4, atoi ); // -128
00133         }
00134         else
00135         {
00136                 writenumber( (sint16)b, "%hd", 4 );
00137         }
00138 }
00139 
00140 // ======================================================================================================
00141 void            CStringStream::serial(uint16 &b) 
00142 {
00143         // No byte swapping in text mode
00144         if ( isReading() )
00145         {
00146                 readnumber( b, uint16, 5, atoi ); // 65535
00147         }
00148         else
00149         {
00150                 writenumber( b, "%hu", 5 );
00151         }
00152 }
00153 
00154 // ======================================================================================================
00155 void            CStringStream::serial(sint16 &b) 
00156 {
00157         if ( isReading() )
00158         {
00159                 readnumber( b, sint16, 6, atoi ); // -32768
00160         }
00161         else
00162         {
00163                 writenumber( b, "%hd", 6 );
00164         }
00165 }
00166 
00167 // ======================================================================================================
00168 void            CStringStream::serial(uint32 &b) 
00169 {
00170         if ( isReading() )
00171         {
00172                 readnumber( b, uint32, 10, atoui ); // 4294967295
00173         }
00174         else
00175         {
00176                 writenumber( b, "%u", 10 );
00177         }
00178 }
00179 
00180 // ======================================================================================================
00181 void            CStringStream::serial(sint32 &b) 
00182 {
00183         if ( isReading() )
00184         {
00185                 readnumber( b, sint32, 11, atoi ); // -2147483648
00186         }
00187         else
00188         {
00189                 writenumber( b, "%d", 11 );
00190         }
00191 }
00192 
00193 // ======================================================================================================
00194 void            CStringStream::serial(uint64 &b) 
00195 {
00196         if ( isReading() )
00197         {
00198                 readnumber( b, uint64, 20, atoiInt64 ); // 18446744073709551615
00199         }
00200         else
00201         {
00202                 writenumber( b, "%"NL_I64"u", 20 );
00203         }
00204 }
00205 
00206 // ======================================================================================================
00207 void            CStringStream::serial(sint64 &b) 
00208 {
00209         if ( isReading() )
00210         {
00211                 readnumber( b, sint64, 20, atoiInt64 ); // -9223372036854775808
00212         }
00213         else
00214         {
00215                 writenumber( b, "%"NL_I64"d", 20 );
00216         }
00217 }
00218 
00219 // ======================================================================================================
00220 void            CStringStream::serial(float &b) 
00221 {
00222         if ( isReading() )
00223         {
00224                 readnumber( b, float, 128, atof ); // ?
00225         }
00226         else
00227         {
00228                 writenumber( (double)b, "%f", 128 );
00229         }
00230 }
00231 
00232 // ======================================================================================================
00233         void            CStringStream::serial(double &b) 
00234 {
00235         if ( isReading() )
00236         {
00237                 readnumber( b, double, 128, atof ); //
00238         }
00239         else
00240         {
00241                 writenumber( b, "%f", 128 );
00242         }
00243 }
00244 
00245 // ======================================================================================================
00246 void            CStringStream::serial(bool &b) 
00247 {
00248         serialBit(b);
00249 }
00250 
00251 
00252 // ======================================================================================================
00253 void                    CStringStream::serialBit(bool &bit)
00254 {
00255         uint8 u;
00256         if ( isReading() )
00257         {
00258                 serial( u );
00259                 bit = (u!=0);
00260         }
00261         else
00262         {
00263                 u = (uint8)bit;
00264                 serial( u );
00265         }
00266 }
00267 
00268 
00269 #ifndef NL_OS_CYGWIN
00270 // ======================================================================================================
00271 void            CStringStream::serial(char &b) 
00272 {
00273         char buff [2];
00274         if ( isReading() )
00275         {
00276                 serialBuffer( (uint8*)buff, 2 );
00277                 b = buff[0];
00278         }
00279         else
00280         {
00281                 buff[0] = b;
00282                 buff[1] = SEPARATOR;
00283                 serialBuffer( (uint8*)buff, 2 );
00284         }
00285 
00286 }
00287 #endif
00288 
00289 // ======================================================================================================
00290 void            CStringStream::serial(std::string &b) 
00291 {
00292         sint32  len=0;
00293         // Read/Write the length.
00294         if(isReading())
00295         {
00296                 serial(len);
00297                 nlassert( len<1000000 ); // limiting string size
00298                 b.resize(len);
00299         }
00300         else
00301         {
00302                 len= b.size();
00303                 serial(len);
00304         }
00305         
00306         // Read/Write the string.
00307         for(sint i=0;i<len;i++)
00308                 serialBuffer( (uint8*)&(b[i]), sizeof(b[i]) );
00309 
00310         char sep = SEPARATOR;
00311         serialBuffer( (uint8*)&sep, 1 );
00312 }
00313 
00314 
00315 // ======================================================================================================
00316 void            CStringStream::serial(ucstring &b) 
00317 {
00318         sint32  len=0;
00319         // Read/Write the length.
00320         if(isReading())
00321         {
00322                 serial(len);
00323                 b.resize(len);
00324         }
00325         else
00326         {
00327                 len= b.size();
00328                 serial(len);
00329         }
00330         // Read/Write the string.
00331         for(sint i=0;i<len;i++)
00332                 serialBuffer( (uint8*)&b[i], sizeof( sizeof(b[i]) ) );
00333 
00334         char sep = SEPARATOR;
00335         serialBuffer( (uint8*)&sep, 1 );
00336 }
00337 
00338 
00339 // Specialisation of serialCont() for vector<bool>
00340 void    CStringStream::serialCont(std::vector<bool> &cont)
00341 {
00342         sint32  len=0;
00343         if(isReading())
00344         {
00345                 serial(len);
00346                 // special version for vector: adjut good size.
00347                 contReset(cont);
00348                 cont.reserve(len);
00349 
00350                 for(sint i=0;i<len;i++)
00351                 {
00352                         bool    v;
00353                         serial(v);
00354                         cont.insert(cont.end(), v);
00355                 }
00356         }
00357         else
00358         {
00359                 len= cont.size();
00360                 serial(len);
00361 
00362                 std::vector<bool>::iterator it= cont.begin();
00363                 for(sint i=0;i<len;i++, it++)
00364                 {
00365                         bool b = *it;
00366                         serial( b );
00367                 }
00368         }
00369 }
00370 
00371 
00372 /*
00373  * Serialisation in hexadecimal
00374  */
00375 void    CStringStream::serialHex(uint32 &b)
00376 {
00377         if ( isReading() )
00378         {
00379                 readnumber( b, uint32, 10, atoihex ); // 4294967295
00380         }
00381         else
00382         {
00383                 writenumber( b, "%x", 10 );
00384         }
00385 }
00386 
00387 
00388 } // NLMISC