00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef NL_BIT_MEM_STREAM_H
00025 #define NL_BIT_MEM_STREAM_H
00026
00027 #include "types_nl.h"
00028 #include "mem_stream.h"
00029
00030
00031 namespace NLMISC {
00032
00033
00034
00035
00036
00037 #ifndef NL_NO_DEBUG
00038 # ifdef NL_OS_WINDOWS
00039 # define LOG_ALL_TRAFFIC
00040 # else
00041 # undef LOG_ALL_TRAFFIC
00042 # endif
00043 #endif
00044
00045 #ifdef LOG_ALL_TRAFFIC
00046
00047 extern bool VerboseAllTraffic;
00048
00049 #define serialAndLog1( v ) \
00050 _serialAndLog( #v, v );
00051
00052 #define serialAndLog2( v, s ) \
00053 _serialAndLog( #v, v, s );
00054
00055 #define serialBitAndLog( v ) \
00056 _serialBitAndLog( #v, v );
00057
00058 #define serialAdaptAndLog( argstr, b, type ) \
00059 uint32 ub=0; \
00060 if ( isReading() ) \
00061 { \
00062 _serialAndLog( argstr, ub, sizeof(type)*8 ); \
00063 b = (type)ub; \
00064 } \
00065 else \
00066 { \
00067 ub = (uint32)b; \
00068 _serialAndLog( argstr, ub, sizeof(type)*8 ); \
00069 }
00070
00071 #ifdef NL_LITTLE_ENDIAN
00072
00073 #define serialAdapt64AndLog( argstr, b ) \
00074 _serialAndLog( argstr, *((uint32*)(&b)), 32 ); \
00075 _serialAndLog( argstr, *((uint32*)(&b)+1), 32 );
00076
00077 #else
00078
00079 #define serialAdapt64AndLog( argstr, b ) \
00080 serialAndLog( argstr, *((uint32*)(&b)+1), 32); \
00081 serialAndLog( argstr, *((uint32*)(&b)), 32);
00082
00083 #endif
00084
00085
00086 #else
00087
00088 #define serialAndLog1 serial
00089 #define serialAndLog2 serial
00090 #define serialBitAndLog serialBit
00091
00092
00093 #endif
00094
00095 #define serialAdapt( b, type ) \
00096 uint32 ub=0; \
00097 if ( isReading() ) \
00098 { \
00099 serial( ub, sizeof(type)*8 ); \
00100 b = (type)ub; \
00101 } \
00102 else \
00103 { \
00104 ub = (uint32)b; \
00105 serial( ub, sizeof(type)*8 ); \
00106 }
00107
00108 #ifdef NL_LITTLE_ENDIAN
00109
00110 #define serialAdapt64( b ) \
00111 serial( *((uint32*)(&b)), 32); \
00112 serial( *((uint32*)(&b)+1), 32);
00113
00114 #else
00115
00116 #define serialAdapt64( b ) \
00117 serial( *((uint32*)(&b)+1), 32); \
00118 serial( *((uint32*)(&b)), 32);
00119
00120 #endif
00121
00122
00123 class CBitSet;
00124
00125
00126
00127
00128
00129 struct TBMSSerialInfo
00130 {
00131 enum TSerialType { B, U, U64, F, BF, Buffer, NbSerialTypes };
00132
00133 TBMSSerialInfo( uint32 bitpos, uint32 bitsize, TSerialType type, const char *symbol )
00134 {
00135 nlassert( bitpos < 800000 );
00136 BitPos = bitpos;
00137 BitSize = bitsize;
00138 Type = type;
00139 Symbol = symbol;
00140 }
00141
00142 uint32 BitPos;
00143 uint32 BitSize;
00144 TSerialType Type;
00145 const char *Symbol;
00146 };
00147
00148 extern const char * SerialTypeToCStr [ TBMSSerialInfo::NbSerialTypes ];
00149
00150
00151 typedef std::vector< TBMSSerialInfo > TBMSSerialInfoList;
00152
00153
00154
00155
00156
00157 struct TBMSDbgInfoData
00158 {
00160 TBMSDbgInfoData() : List(), CurrentBrowsedItem(0), NextSymbol(NULL), AddEventIsEnabled(true) {}
00161
00163 TBMSSerialInfoList List;
00164
00166 uint32 CurrentBrowsedItem;
00167
00169 const char *NextSymbol;
00170
00172 bool AddEventIsEnabled;
00173 };
00174
00175 class CBitMemStream;
00176
00177
00178
00179
00180 class CBMSDbgInfo
00181 {
00182 public:
00183
00184 #ifdef NL_DEBUG
00186 CBMSDbgInfo() : _DbgData(NULL) { init(); }
00187 #else
00189 CBMSDbgInfo() {}
00190 #endif
00191
00192 #ifdef NL_DEBUG
00194 CBMSDbgInfo( const CBMSDbgInfo& src ) : _DbgData(NULL)
00195 {
00196 init();
00197 operator=( src );
00198 }
00199
00201 CBMSDbgInfo& operator=( const CBMSDbgInfo& src )
00202 {
00203 *_DbgData = *src._DbgData;
00204 return *this;
00205 }
00206
00208 ~CBMSDbgInfo()
00209 {
00210 delete _DbgData;
00211 _DbgData = NULL;
00212 }
00213
00214 #endif
00215 void swap(CBMSDbgInfo &other)
00216 {
00217 #ifdef NL_DEBUG
00218 std::swap(_DbgData, other._DbgData);
00219 #endif
00220 }
00221
00223 void addSerial( uint32 bitpos, uint32 size, TBMSSerialInfo::TSerialType type )
00224 {
00225 #ifdef NL_DEBUG
00226 if ( ! _DbgData->AddEventIsEnabled )
00227 {
00228 _DbgData->NextSymbol = NULL;
00229 return;
00230 }
00231
00232 TBMSSerialInfo serialItem( bitpos, size, type, _DbgData->NextSymbol );
00233 _DbgData->List.push_back( serialItem );
00234 _DbgData->NextSymbol = NULL;
00235 #endif
00236 }
00237
00239 void addPoke( uint32 bitpos, uint32 size, TBMSSerialInfo::TSerialType type )
00240 {
00241 #ifdef NL_DEBUG
00242 if ( ! _DbgData->AddEventIsEnabled )
00243 {
00244 _DbgData->NextSymbol = NULL;
00245 return;
00246 }
00247
00248 TBMSSerialInfo serialItem( bitpos, size, type, _DbgData->NextSymbol );
00249
00251 bool found = false;
00252 TBMSSerialInfoList::iterator itl;
00253 for ( itl=_DbgData->List.begin(); itl!=_DbgData->List.end(); ++itl )
00254 {
00255 if ( (*itl).BitPos == bitpos )
00256 {
00257
00258 (*itl) = serialItem;
00259 found = true;
00260 break;
00261 }
00262 }
00263 if ( ! found )
00264 {
00265 nlwarning( "Missing reserve() corresponding to poke()" );
00266 }
00267 _DbgData->NextSymbol = NULL;
00268 #endif
00269 }
00270
00272 void setSymbolOfNextSerialEvent( const char *symbol )
00273 {
00274 #ifdef NL_DEBUG
00275 _DbgData->NextSymbol = symbol;
00276 #endif
00277 }
00278
00280 void clear()
00281 {
00282 #ifdef NL_DEBUG
00283 _DbgData->List.clear();
00284 #endif
00285 }
00286
00288 void beginEventBrowsing()
00289 {
00290 #ifdef NL_DEBUG
00291 _DbgData->CurrentBrowsedItem = 0;
00292 _DbgData->AddEventIsEnabled = false;
00293 #endif
00294 }
00295
00297 void endEventBrowsing()
00298 {
00299 #ifdef NL_DEBUG
00300 _DbgData->AddEventIsEnabled = true;
00301 #endif
00302 }
00303
00305 std::string getEventIdAtBitPos( uint32 bitpos, sint32 *eventId )
00306 {
00307 #ifdef NL_DEBUG
00308 if ( _DbgData->CurrentBrowsedItem < _DbgData->List.size() )
00309 {
00310 if ( bitpos == _DbgData->List[_DbgData->CurrentBrowsedItem].BitPos )
00311 {
00312 *eventId = (sint32)_DbgData->CurrentBrowsedItem;
00313 ++_DbgData->CurrentBrowsedItem;
00314 return toString( "(%u)", _DbgData->CurrentBrowsedItem - 1 );
00315 }
00316
00317 }
00318 #endif
00319 *eventId = -1;
00320 return std::string();
00321 }
00322
00324 std::string getEventLegendAtBitPos( CBitMemStream& bms, sint32 eventId );
00325
00326 private:
00327
00328 #ifdef NL_DEBUG
00330 void init()
00331 {
00332 _DbgData = new TBMSDbgInfoData();
00333 }
00334
00336 TBMSDbgInfoData *_DbgData;
00337 #endif
00338 };
00339
00340
00361 class CBitMemStream : public CMemStream
00362 {
00363 public:
00364
00366 CBitMemStream( bool inputStream=false, uint32 defaultcapacity=32 );
00367
00369 CBitMemStream( const CBitMemStream& other );
00370
00372 CBitMemStream& operator=( const CBitMemStream& other )
00373 {
00374 CMemStream::operator=( other );
00375 _FreeBits = other._FreeBits;
00376 _DbgInfo = other._DbgInfo;
00377 return *this;
00378 }
00379
00380
00381 void swap(CBitMemStream &other);
00382
00390 void resetBufPos()
00391 {
00392
00393
00395 nlassert( ! ((!isReading()) && _Buffer.getBuffer().empty()) );
00396
00397 CMemStream::resetBufPos();
00398 if ( !isReading() )
00399
00400 *(_Buffer.getBufferWrite().getPtr()+_Buffer.Pos) = 0;
00401 _FreeBits = 8;
00402 _DbgInfo.clear();
00403 }
00404
00411 virtual uint32 length() const
00412 {
00413 if ( isReading() )
00414 {
00415 return lengthR();
00416 }
00417 else
00418 {
00419 if ( _FreeBits == 8 )
00420 return lengthS();
00421 else
00422 return lengthS() + 1;
00423 }
00424 }
00425
00427 virtual void invert()
00428 {
00429 if ( ! isReading() )
00430 {
00431
00432 ++_Buffer.Pos;
00433 }
00434 CMemStream::invert();
00435 if ( ! isReading() )
00436 {
00437 #ifdef NL_DEBUG
00438
00439 nlassert( _Buffer.Pos == _Buffer.getBuffer().size() );
00440 #endif
00441
00442 --(_Buffer.Pos);
00443 }
00444
00445 }
00446
00448 virtual void clear()
00449 {
00450 CMemStream::clear();
00451 resetBufPos();
00452 }
00453
00455 sint32 getPosInBit() const
00456 {
00457
00458 return (_Buffer.Pos + 1)*8 - _FreeBits;
00459 }
00460
00462 void displayStream( const char *title="", CLog *log = NLMISC::DebugLog );
00463
00465 void fill( const uint8 *srcbuf, uint32 len )
00466 {
00467 _FreeBits = 8;
00468 _DbgInfo.clear();
00469 CMemStream::fill( srcbuf, len );
00470 }
00471
00473 uint8 *bufferToFill( uint32 msgsize )
00474 {
00475 _FreeBits = 8;
00476 _DbgInfo.clear();
00477 return CMemStream::bufferToFill( msgsize );
00478 }
00479
00481 void append( const CBitMemStream& newBits );
00482
00484 virtual void serialBuffer(uint8 *buf, uint len);
00485
00487 virtual void serialBit( bool& bit );
00488
00489 #ifdef LOG_ALL_TRAFFIC
00490 void _serialAndLog( const char *argstr, uint32& value, uint nbits );
00491 void _serialAndLog( const char *argstr, uint64& value, uint nbits );
00492 void _serialBitAndLog( const char *argstr, bool& bit );
00493 #endif
00494
00499 void serial( uint32& value, uint nbits, bool resetvalue=true )
00500 {
00501 _DbgInfo.addSerial( getPosInBit(), nbits, TBMSSerialInfo::U );
00502 internalSerial( value, nbits, resetvalue );
00503 }
00504
00508 void serial( uint64& value, uint nbits )
00509 {
00510 _DbgInfo.addSerial( getPosInBit(), nbits, TBMSSerialInfo::U64 );
00511 internalSerial( value, nbits );
00512 }
00513
00518 sint32 reserve( uint byteLen );
00519
00524 void reserveBits( uint nbits );
00525
00526
00527
00528
00529
00530
00531
00532
00533 void poke( uint32 value, uint bitpos, uint nbits );
00534
00540 void pokeBits( const NLMISC::CBitSet& bitfield, uint bitpos );
00541
00546 void readBits( NLMISC::CBitSet& bitfield );
00547
00549 void displayLastBits( sint nbits, sint bitpos=-1, NLMISC::CLog *log=NLMISC::DebugLog );
00550
00552 std::string getSerialItem( const TBMSSerialInfo& serialItem );
00553
00555 template<class T>
00556 void serial(T &obj) { obj.serial(*this); }
00557
00558
00559 template<class T>
00560 void serialCont(std::vector<T> &cont) {CMemStream::serialCont(cont);}
00561 template<class T>
00562 void serialCont(std::list<T> &cont) {CMemStream::serialCont(cont);}
00563 template<class T>
00564 void serialCont(std::deque<T> &cont) {CMemStream::serialCont(cont);}
00565 template<class T>
00566 void serialCont(std::set<T> &cont) {CMemStream::serialCont(cont);}
00567 template<class T>
00568 void serialCont(std::multiset<T> &cont) {CMemStream::serialCont(cont);}
00569 template<class K, class T>
00570 void serialCont(std::map<K, T> &cont) {CMemStream::serialCont(cont);}
00571 template<class K, class T>
00572 void serialCont(std::multimap<K, T> &cont) {CMemStream::serialCont(cont);}
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614 #ifdef LOG_ALL_TRAFFIC
00615 void _serialAndLog(const char *argstr, uint8 &b) { serialAdaptAndLog( argstr, b, uint8 ); }
00616 void _serialAndLog(const char *argstr, sint8 &b) { serialAdaptAndLog( argstr, b, sint8 ); }
00617 void _serialAndLog(const char *argstr, uint16 &b) { serialAdaptAndLog( argstr, b, uint16 ); }
00618 void _serialAndLog(const char *argstr, sint16 &b) { serialAdaptAndLog( argstr, b, sint16 ); }
00619 void _serialAndLog(const char *argstr, uint32 &b) { serialAdaptAndLog( argstr, b, uint32 ); }
00620 void _serialAndLog(const char *argstr, sint32 &b) { serialAdaptAndLog( argstr, b, sint32 ); }
00621 void _serialAndLog(const char *argstr, uint64 &b) { serialAdapt64AndLog( argstr, b ); }
00622 void _serialAndLog(const char *argstr, sint64 &b) { serialAdapt64AndLog( argstr, b ); }
00623 void _serialAndLog(const char *argstr, float &b);
00624 void _serialAndLog(const char *argstr, double &b) { serialAdapt64AndLog( argstr, b ); }
00625 void _serialAndLog(const char *argstr, bool &b) { _serialBitAndLog( argstr, b ); }
00626 #ifndef NL_OS_CYGWIN
00627 virtual void _serialAndLog(const char *argstr, char &b) { serialAdaptAndLog( argstr, b, char ); }
00628 #endif
00629 #endif
00630
00631 virtual void serial(uint8 &b) { serialAdapt( b, uint8 ); }
00632 virtual void serial(sint8 &b) { serialAdapt( b, sint8 ); }
00633 virtual void serial(uint16 &b) { serialAdapt( b, uint16 ); }
00634 virtual void serial(sint16 &b) { serialAdapt( b, sint16 ); }
00635 virtual void serial(uint32 &b) { serialAdapt( b, uint32 ); }
00636 virtual void serial(sint32 &b) { serialAdapt( b, sint32 ); }
00637 virtual void serial(uint64 &b) { serialAdapt64( b ); }
00638 virtual void serial(sint64 &b) { serialAdapt64( b ); }
00639 virtual void serial(float &b);
00640 virtual void serial(double &b) { serialAdapt64( b ); }
00641 virtual void serial(bool &b) { serialBit( b ); }
00642 #ifndef NL_OS_CYGWIN
00643 virtual void serial(char &b) { serialAdapt( b, char ); }
00644 #endif
00645
00646 virtual void serial(std::string &b);
00647 virtual void serial(ucstring &b);
00648
00649 virtual void serial(CBitMemStream &b) { serialMemStream(b); }
00650 virtual void serialMemStream(CBitMemStream &b);
00651
00652
00654
00656 virtual void serialCont(std::vector<uint8> &cont) { serialVector(cont); }
00658 virtual void serialCont(std::vector<sint8> &cont) { serialVector(cont); }
00660 virtual void serialCont(std::vector<bool> &cont);
00661
00662 protected:
00663
00667 void internalSerial( uint32& value, uint nbits, bool resetvalue=true );
00668
00672 void internalSerial( uint64& value, uint nbits )
00673 {
00674 if ( nbits > 32 )
00675 {
00676 if ( isReading() )
00677 {
00678
00679 uint32 msd = 0;
00680 internalSerial( msd, nbits-32 );
00681 value = (uint64)msd << 32;
00682
00683 internalSerial( (uint32&)value, 32 );
00684 }
00685 else
00686 {
00687
00688 uint32 msd = (uint32)(value >> 32);
00689 internalSerial( msd, nbits-32 );
00690
00691 internalSerial( (uint32&)value, 32 );
00692 }
00693 }
00694 else
00695 {
00696 if ( isReading() )
00697 {
00698
00699 value = 0;
00700 }
00701
00702 internalSerial( (uint32&)value, nbits );
00703 }
00704 }
00705
00716 void prepareNextByte()
00717 {
00718 pointNextByte();
00719 increaseBufferIfNecessary();
00720
00721 *(_Buffer.getBufferWrite().getPtr() + _Buffer.Pos) = 0;
00722 }
00723
00733 void pointNextByte()
00734 {
00735 #ifdef NL_DEBUG
00736 nlassert( !isReading() );
00737 #endif
00738 _FreeBits = 8;
00739
00740 ++_Buffer.Pos;
00741 }
00742
00754 void increaseBufferIfNecessary()
00755 {
00756 #ifdef NL_DEBUG
00757
00758 nlassert( (!isReading()) && (!_Buffer.getBuffer().empty()) );
00759
00760 nlassert( _Buffer.Pos <= _Buffer.getBuffer().size() );
00761 #endif
00762
00763
00764
00765 if ( _Buffer.Pos == _Buffer.getBuffer().size() )
00766 {
00767
00768 _Buffer.getBufferWrite().resize( _Buffer.Pos * 2 );
00769
00770 }
00771 }
00772
00777 void serialPoke( uint32 value, uint nbits );
00778
00780 uint _FreeBits;
00781
00783 CBMSDbgInfo _DbgInfo;
00784 };
00785
00786
00788 void displayBitStream( const CBitMemStream& msg, sint beginbitpos, sint endbitpos, NLMISC::CLog *log=NLMISC::DebugLog );
00789
00790
00791
00792
00793
00794 inline std::string CBMSDbgInfo::getEventLegendAtBitPos( CBitMemStream& bms, sint32 eventId )
00795 {
00796 #ifdef NL_DEBUG
00797 if ( eventId == -1 )
00798 {
00799 return std::string();
00800 }
00801 else
00802 {
00803 nlassert( eventId < (sint32)_DbgData->List.size() );
00804 TBMSSerialInfo& serialItem = _DbgData->List[eventId];
00805 return toString( "(%d) BitPos %3u Type %s BitSize %2u Value %s %s\n",
00806 eventId, serialItem.BitPos, SerialTypeToCStr[serialItem.Type], serialItem.BitSize,
00807 bms.getSerialItem( serialItem ).c_str(), (serialItem.Symbol!=NULL)?serialItem.Symbol:"" );
00808 }
00809 #else
00810 return std::string();
00811 #endif
00812 }
00813
00814
00815 }
00816
00817
00818 #endif // NL_BIT_MEM_STREAM_H
00819
00820