Linux multi-monitor fullscreen support
[ryzomcore.git] / nel / src / misc / bit_mem_stream.cpp
blob687fabbecbad4dac6f3d807969a74aea16cb472c
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2016 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "stdmisc.h"
22 #include "nel/misc/bit_mem_stream.h"
23 #include "nel/misc/bit_set.h"
25 #ifdef LOG_ALL_TRAFFIC
26 #include "nel/misc/command.h"
27 #endif
29 using namespace std;
31 #ifdef DEBUG_NEW
32 #define new DEBUG_NEW
33 #endif
35 namespace NLMISC {
37 #ifdef LOG_ALL_TRAFFIC
38 bool VerboseAllTraffic = false;
39 #endif
42 const char * SerialTypeToCStr [ TBMSSerialInfo::NbSerialTypes ] = { "Bool ", "Ui32N", "Ui64N", "Float", "Btfld", "Buffr" };
46 * Constructor
48 CBitMemStream::CBitMemStream( bool inputStream, uint32 defaultcapacity ) :
49 CMemStream( inputStream, false, defaultcapacity ),
50 _FreeBits( 0 )
52 resetBufPos();
57 * Copy constructor
59 CBitMemStream::CBitMemStream( const CBitMemStream& other ) :
60 CMemStream( other ),
61 _FreeBits( other._FreeBits ),
62 _DbgInfo( other._DbgInfo )
67 * Exchange
69 void CBitMemStream::swap(CBitMemStream &other)
71 CMemStream::swap(other);
72 std::swap(_FreeBits, other._FreeBits);
73 _DbgInfo.swap(other._DbgInfo);
78 * Serialize a buffer
80 void CBitMemStream::serialBuffer( uint8 *buf, uint len )
82 _DbgInfo.addSerial( getPosInBit(), len*8, TBMSSerialInfo::Buffer );
83 uint i;
84 uint32 v;
85 if ( isReading() )
87 for ( i=0; i!=len; ++i )
89 internalSerial( v, 8 );
90 buf[i] = (uint8)v;
93 else
95 for ( i=0; i!=len; ++i )
97 v = (uint32)buf[i];
98 internalSerial( v, 8 );
105 * Serialize one bit
107 void CBitMemStream::serialBit( bool& bit )
109 _DbgInfo.addSerial( getPosInBit(), 1, TBMSSerialInfo::B );
110 uint32 ubit=0;
111 if ( isReading() )
113 internalSerial( ubit, 1 );
114 bit = ( ubit!=0 );
116 else
118 ubit = bit;
119 internalSerial( ubit, 1 );
124 //sint32 CBitMemStream::getPosInBit ()
127 #ifdef LOG_ALL_TRAFFIC
129 void CBitMemStream::_serialAndLog( const char *argstr, uint32& value, uint nbits )
131 _DbgInfo.setSymbolOfNextSerialEvent( argstr );
132 sint32 bitpos = getPosInBit();
133 serial( value, nbits );
134 if ( VerboseAllTraffic )
135 nldebug( "TRAFFIC/%p/%s: %s: %u bits at bitpos %d (%u)", this, isReading()?"I":"O", argstr, nbits, bitpos, value );
138 void CBitMemStream::_serialAndLog( const char *argstr, uint64& value, uint nbits )
140 _DbgInfo.setSymbolOfNextSerialEvent( argstr );
141 sint32 bitpos = getPosInBit();
142 serial( value, nbits );
143 if ( VerboseAllTraffic )
144 nldebug( "TRAFFIC/%p/%s: %s: %u bits at bitpos %d (%u)", this, isReading()?"I":"O", argstr, nbits, bitpos, value );
147 void CBitMemStream::_serialBitAndLog( const char *argstr, bool& bit )
149 _DbgInfo.setSymbolOfNextSerialEvent( argstr );
150 sint32 bitpos = getPosInBit();
151 serialBit( bit );
152 if ( VerboseAllTraffic )
153 nldebug( "TRAFFIC/%p/%s: %s: 1 bit at bitpos %d (%hu)", this, isReading()?"I":"O", argstr, bitpos, (uint16)bit );
156 NLMISC_CATEGORISED_COMMAND(nel, verboseAllTraffic, "Verbose the all-traffic logs", "" )
158 if(args.size()>1)
159 return false;
161 if(args.size()==1)
163 if(args[0]==string("on")||args[0]==string("ON")||args[0]==string("true")||args[0]==string("TRUE")||args[0]==string("1"))
164 VerboseAllTraffic=true;
165 else if(args[0]==string("off")||args[0]==string("OFF")||args[0]==string("false")||args[0]==string("FALSE")||args[0]==string("0"))
166 VerboseAllTraffic=false;
169 nlinfo("BMS: verboseAllTraffic is %s",VerboseAllTraffic?"ON":"OFF");
170 return true;
173 #endif
177 * Serialize only the nbits lower bits of value
179 void CBitMemStream::internalSerial( uint32& value, uint nbits, bool resetvalue )
181 if ( nbits == 0 )
182 return;
183 if ( nbits > 32 )
184 throw EMemStream (string("trying to serial ")+NLMISC::toString(nbits)+string(" bits"));
186 if ( isReading() )
188 const uint8 *buffer = _Buffer.getBuffer().getPtr();
189 // Check that we don't read more than there is to read
190 uint32 pib = getPosInBit();
191 uint32 len = ((uint32)lengthR());
192 if ( pib + nbits > len * 8 )
194 //displayStream( "Stream Overflow" );
195 throw EStreamOverflow( "CBitMemStream overflow: Read past %u bytes", len );
198 if ( resetvalue )
200 value = 0;
203 // Clear high-order bits after _FreeBits
204 uint8 v = *(buffer + _Buffer.Pos) & ((1 << _FreeBits) - 1);
206 if ( nbits > _FreeBits )
208 //nldebug( "Reading byte %u from %u free bits (%u remaining bits)", lengthS(), _FreeBits, nbits );
209 value |= (v << (nbits-_FreeBits));
210 // ++_BufPos;
211 ++_Buffer.Pos;
212 uint readbits = _FreeBits;
213 //displayByteBits( *_BufPos, 8, readbits-1, false );
214 _FreeBits = 8;
215 internalSerial( value, nbits - readbits, false ); // read without resetting value
217 else
219 //nlinfo( "Reading last byte %u from %u free bits (%u remaining bits)", lengthS(), _FreeBits, nbits );
220 //displayByteBits( *_BufPos, 8, _FreeBits-1, false );
221 value |= (v >> (_FreeBits-nbits));
222 //displayByteBits( *_BufPos, 8, _FreeBits-1, false );
223 _FreeBits -= nbits;
224 if ( _FreeBits == 0 )
226 _FreeBits = 8;
227 // ++_BufPos;
228 ++_Buffer.Pos;
232 else
234 uint8 *buffer = _Buffer.getBufferWrite().getPtr();
235 // Clear high-order bits after nbits
236 //displayDwordBits( value, 32, nbits-1, false );
238 //uint32 mask = (-1 >> (32-nbits)); // does not work
239 uint32 v;
240 if ( nbits != 32 ) // arg of shl/sal/shr/sal ranges from 0 to 31
242 uint32 mask = (1 << nbits) - 1;
243 v = value & mask;
245 else
247 v = value;
250 #ifdef NL_DEBUG
251 // Check that the current byte is prepared
252 nlassert( ! ((_FreeBits == 8) && (*(buffer+_Buffer.Pos) != 0)) );
253 #endif
255 // Set
256 if ( nbits > _FreeBits )
258 // Longer than the room in the current byte
259 //nldebug( "Writing byte %u into %u free bits (%u remaining bits)", lengthS(), _FreeBits, nbits );
260 //displayDwordBits( value, 32, nbits-1, false );
261 // *_BufPos |= (v >> (nbits - _FreeBits));
262 *(buffer+_Buffer.Pos) |= (v >> (nbits - _FreeBits));
263 uint filledbits = _FreeBits;
264 //displayByteBits( *_BufPos, 8, filledbits-1, false );
265 prepareNextByte();
266 internalSerial( v, nbits - filledbits );
268 else
270 // Shorter or equal
271 //nldebug( "Writing last byte %u into %u free bits (%u remaining bits)", lengthS(), _FreeBits, nbits );
272 //displayByteBits( *_BufPos, 8, 7, false );
273 // *_BufPos |= (v << (_FreeBits-nbits));
274 *(buffer+_Buffer.Pos) |= (v << (_FreeBits-nbits));
275 //displayByteBits( *_BufPos, 8, _FreeBits-1, false );
276 _FreeBits -= nbits;
277 if ( _FreeBits == 0 )
279 prepareNextByte();
287 * Same as CMemStream::reserve()
289 sint32 CBitMemStream::reserve( uint byteLen )
291 sint32 p = getPos();
292 reserveBits( byteLen * 8 );
293 return p;
298 * In a output bit stream, serialize nbits bits (no matter their value).
299 * Works even if the number of bits to add is larger than 64. See also poke() and pokeBits().
301 void CBitMemStream::reserveBits( uint nbits )
303 #ifdef LOG_ALL_TRAFFIC
304 if ( VerboseAllTraffic )
305 nldebug( "TRAFFIC/%p/%s: Reserving %u bits at bitpos %d", this, isReading()?"I":"O", nbits, getPosInBit() );
306 #endif
308 uint32 v = 0;
309 while ( nbits > 32 )
311 serial( v, 32 );
312 nbits -= 32;
314 if ( nbits != 0 )
315 serial( v, nbits );
320 * Helper for poke(), to write a value inside an output stream (works because reserveBits sets to 0)
322 void CBitMemStream::serialPoke( uint32 value, uint nbits )
324 uint32 v;
325 if ( nbits != 32 ) // arg of shl/sal/shr/sal ranges from 0 to 31
327 uint32 mask = (1 << nbits) - 1;
328 v = value & mask;
330 else
332 v = value;
335 uint8 *buffer = _Buffer.getBufferWrite().getPtr();
337 // Set
338 if ( nbits > _FreeBits )
340 // Longer than the room in the current byte
341 //nldebug( "Writing byte %u into %u free bits (%u remaining bits)", lengthS(), _FreeBits, nbits );
342 //displayDwordBits( value, 32, nbits-1, false );
343 // *_BufPos |= (v >> (nbits - _FreeBits));
344 *(buffer + _Buffer.Pos) |= (v >> (nbits - _FreeBits));
345 uint filledbits = _FreeBits;
346 //displayByteBits( *_BufPos, 8, filledbits-1, false );
347 pointNextByte(); // do not set next byte to 0!
348 // nlassert( _BufPos < _Buffer.getPtr() + _Buffer.size() );
349 nlassert( _Buffer.Pos < _Buffer.getBuffer().size() );
350 serialPoke( v, nbits - filledbits );
352 else
354 // Shorter or equal
355 //nldebug( "Writing last byte %u into %u free bits (%u remaining bits)", lengthS(), _FreeBits, nbits );
356 //displayByteBits( *_BufPos, 8, 7, false );
357 // *_BufPos |= (v << (_FreeBits-nbits));
358 *(buffer + _Buffer.Pos) |= (v << (_FreeBits-nbits));
359 //displayByteBits( *_BufPos, 8, _FreeBits-1, false );
360 _FreeBits -= nbits;
361 if ( _FreeBits == 0 )
363 pointNextByte(); // do not set next byte to 0!
364 // nlassert( _BufPos < _Buffer.getPtr() + _Buffer.size() );
365 nlassert( _Buffer.Pos < _Buffer.getBuffer().size() );
372 * Rewrite the nbbits lowest bits of a value at the specified position bitpos of the current output bit stream.
374 * Preconditions:
375 * - bitpos+nbbits <= the current length in bit of the stream.
376 * - The bits poked must have been reserved by reserve() (i.e. set to 0)
378 void CBitMemStream::poke( uint32 value, uint bitpos, uint nbits )
380 #ifdef NL_DEBUG
381 nlassert( (nbits <= 32) && (nbits != 0) );
382 nlassert( ! isReading() );
383 nlassert( bitpos+nbits <= (uint)getPosInBit() );
384 #endif
386 // Save the current pointers of the stream, and make them point to the required position
387 uint savedFreeBits = _FreeBits;
388 uint bytepos = bitpos >> 3;
389 _FreeBits = 8 - (bitpos - (bytepos << 3));
390 // uint8 *savedBufPos = _BufPos;
391 uint32 savedBufPos = _Buffer.Pos;
392 // _BufPos = _Buffer.getPtr() + bytepos;
393 _Buffer.Pos = bytepos;
395 // Serial
396 _DbgInfo.addPoke( bitpos, nbits, TBMSSerialInfo::U );
397 serialPoke( value, nbits );
399 // Restore the current pointers
400 _FreeBits = savedFreeBits;
401 // _BufPos = savedBufPos;
402 _Buffer.Pos = savedBufPos;
406 /* Rewrite the bitfield at the specified position bitpos of the current output bit stream.
407 * The size of the bitfield is *not* written into stream (unlike serialCont()).
408 * Precondition: bitpos+bitfield.size() <= the current length in bit of the stream. See also reserveBits().
410 void CBitMemStream::pokeBits( const CBitSet& bitfield, uint bitpos )
412 #ifdef NL_DEBUG
413 nlassert( ! isReading() );
414 nlassert( bitpos+bitfield.size() <= (uint)getPosInBit() );
415 #endif
417 // Save the current pointers of the stream, and make them point to the required position
418 uint savedFreeBits = _FreeBits;
419 uint bytepos = bitpos >> 3;
420 _FreeBits = 8 - (bitpos - (bytepos << 3));
421 // uint8 *savedBufPos = _BufPos;
422 uint32 savedBufPos = _Buffer.Pos;
423 // _BufPos = _Buffer.getPtr() + bytepos;
424 _Buffer.Pos = bytepos;
426 // Serial
427 _DbgInfo.addPoke( bitpos, bitfield.size(), TBMSSerialInfo::BF );
428 const vector<uint32>& uintVec = bitfield.getVector();
429 if ( ! uintVec.empty() )
431 uint len = bitfield.size();
432 uint i = 0;
433 while ( len > 32 )
435 serialPoke( uintVec[i], 32 );
436 len -= 32;
437 ++i;
439 if ( len != 0 )
440 serialPoke( uintVec[i], len );
443 // Restore the current pointers
444 _FreeBits = savedFreeBits;
445 // _BufPos = savedBufPos;
446 _Buffer.Pos = savedBufPos;
451 * Read bitfield.size() bits from the input stream to fill the bitfield.
452 * It means you have to know the size and to resize the bitfield yourself.
454 void CBitMemStream::readBits( NLMISC::CBitSet& bitfield )
456 #ifdef NL_DEBUG
457 nlassert( isReading() );
458 #endif
459 uint len = bitfield.size();
460 if ( len != 0 )
462 #ifdef LOG_ALL_TRAFFIC
463 if ( VerboseAllTraffic )
464 nldebug( "TRAFFIC/%p/%s: Reading %u bits bitfield at bitpos %d", this, isReading()?"I":"O", len, getPosInBit() );
465 #endif
466 uint i = 0;
467 uint32 v;
468 while ( len > 32 )
470 serial( v, 32 );
471 //nldebug( "Bitfield: Read %u at %d", v, _BufPos-_Buffer.getPtr()-4 );
472 bitfield.setUint( v, i );
473 len -= 32;
474 ++i;
476 serial( v, len );
477 //nldebug( "Bitfield: Read %u at %d", v, _BufPos-_Buffer.getPtr()-4 );
478 bitfield.setUint( v, i );
484 * Serial float
486 void CBitMemStream::serial(float &b)
488 _DbgInfo.addSerial( getPosInBit(), sizeof(b)*8, TBMSSerialInfo::F );
489 uint32 uf=0;
490 if ( isReading() )
492 internalSerial( uf, sizeof(b)*8 );
493 memcpy(&b, &uf, sizeof(b));
495 else
497 memcpy(&uf, &b, sizeof(b));
498 internalSerial( uf, sizeof(b)*8 );
504 * Serial string
506 void CBitMemStream::serial(std::string &b)
508 #ifdef LOG_ALL_TRAFFIC
509 sint32 bitpos = getPosInBit();
510 #endif
512 uint32 len=0;
514 // Serialize length
515 if ( isReading() )
517 serial( len );
518 if (len > length()-(uint32)getPos())
519 throw NLMISC::EInvalidDataStream( "BMS: Trying to read a string of %u bytes, past stream size", len );
520 b.resize( len );
522 else
524 len = (uint32)b.size();
525 if (len>1000000)
526 throw NLMISC::EInvalidDataStream( "BMS: Trying to write a string of %u bytes", len );
527 serial( len );
530 // Serialize buffer
531 if ( len != 0 )
533 serialBuffer( (uint8*)(&*b.begin()), len );
536 #ifdef LOG_ALL_TRAFFIC
537 if ( VerboseAllTraffic )
538 nldebug( "TRAFFIC/%p/%s: String (size 32+%u*8 bits) at bitpos %d", this, isReading()?"I":"O", len, bitpos );
539 #endif
544 * Serial string
546 inline void CBitMemStream::serial(ucstring &b)
548 #ifdef LOG_ALL_TRAFFIC
549 sint32 bitpos = getPosInBit();
550 #endif
552 if ( _StringMode )
554 uint32 len=0;
555 // Read/Write the length.
556 if(isReading())
558 serial(len);
559 if (len > (uint32)(sint32(length())-sint32(getPos())))
560 throw NLMISC::EInvalidDataStream( "BMS: Trying to read an ucstring of %u bytes, past stream size", len );
561 b.resize(len);
563 else
565 len= (uint32)b.size();
566 if (len>1000000)
567 throw NLMISC::EInvalidDataStream( "BMS: Trying to write an ucstring of %u bytes", len );
568 serial(len);
570 // Read/Write the string.
571 for(uint i=0;i!=len;++i)
572 serialBuffer( (uint8*)&b[i], sizeof(b[i]) );
574 char sep = SEPARATOR;
575 serialBuffer( (uint8*)&sep, 1 );
577 else
579 IStream::serial( b );
582 #ifdef LOG_ALL_TRAFFIC
583 if ( VerboseAllTraffic )
584 nldebug( "TRAFFIC/%p/%s: Ucstring at bitpos %d", this, isReading()?"I":"O", bitpos );
585 #endif
591 * Append the contents of a bitmemstream at the end of our bitmemstream
593 void CBitMemStream::append( const CBitMemStream& newBits )
595 nlassert ( !isReading() );
596 serialBuffer( const_cast<uint8*>(newBits.buffer()), newBits.getPos() );
598 uint nbRemainingBits = 8 - newBits._FreeBits;
599 _DbgInfo.addSerial( getPosInBit(), nbRemainingBits, TBMSSerialInfo::Buffer );
600 uint32 lastByte = (uint32)(*(newBits.buffer() + newBits.getPos())) >> newBits._FreeBits;
601 internalSerial( lastByte, nbRemainingBits );
606 * Serial bitmemstream
608 void CBitMemStream::serialMemStream(CMemStream &b)
610 #ifdef LOG_ALL_TRAFFIC
611 sint32 bitpos = getPosInBit();
612 #endif
614 uint32 len=0;
616 // Serialize length
617 if ( isReading() )
619 // fill b with data from this
620 serial (len);
621 if (len > length()-getPos())
622 throw NLMISC::EInvalidDataStream( "BMS: Trying to read a BMS of %u bytes, past stream size", len );
624 serialBuffer (b.bufferToFill (len), len);
625 b.resetBufPos ();
627 else
629 // fill this with data from b
630 len = b.length();
631 // Accept to write a big sized BMS
633 serial( len );
634 serialBuffer( (uint8*) b.buffer (), len );
637 #ifdef LOG_ALL_TRAFFIC
638 if ( VerboseAllTraffic )
639 nldebug( "TRAFFIC/%p/%s: Sub-bitmemstream (size 32+%u*8 bits) at bitpos %d", this, isReading()?"I":"O", len, bitpos );
640 #endif
644 * Specialisation of serialCont() for vector<bool>
646 void CBitMemStream::serialCont(std::vector<bool> &cont)
648 #ifdef LOG_ALL_TRAFFIC
649 sint32 bitpos = getPosInBit();
650 #endif
652 sint32 len=0;
653 if(isReading())
655 serial(len);
656 if (len/8 > (sint32)(length()-getPos()))
658 throw NLMISC::EInvalidDataStream( "BMS: Trying to read a vec<bool> of %u bytes, past stream size", len/8 );
660 // special version for vector: adjust good size.
661 contReset(cont);
662 cont.reserve(len);
664 for(sint i=0;i<len;i++)
666 bool v;
667 serialBit(v);
668 cont.insert(cont.end(), v);
671 else
673 len= (sint32)cont.size();
674 serial(len);
676 std::vector<bool>::iterator it= cont.begin();
677 for(sint i=0;i<len;i++, it++)
679 bool b = *it;
680 serialBit( b );
684 #ifdef LOG_ALL_TRAFFIC
685 if ( VerboseAllTraffic )
686 nldebug( "TRAFFIC/%p/%s: Container (header: 32 bits) at bitpos %d", this, isReading()?"I":"O", bitpos );
687 #endif
693 * Display the bits of the stream just before the current pos
695 void CBitMemStream::displayLastBits( sint nbits, sint bitpos, NLMISC::CLog *log )
697 if ( bitpos == -1 )
698 bitpos = getPosInBit();
699 displayBitStream( *this, max(bitpos-nbits, 0), bitpos-1, log );
704 * Display a part of a bitmemstream
706 void displayBitStream( const CBitMemStream& msg, sint beginbitpos, sint endbitpos, NLMISC::CLog *log )
708 sint beginpos = beginbitpos/8;
709 sint endpos = endbitpos/8;
710 nlinfo( "BMS: beginpos %d endpos %d beginbitpos %d endbitpos %d", beginpos, endpos, beginbitpos, endbitpos );
711 displayByteBits( *(msg.buffer()+beginpos), 8, 8-(beginbitpos-beginpos*8), true, log );
712 const uint8 *p;
713 for ( p=msg.buffer()+beginpos+1; p<msg.buffer()+endpos-1; ++p )
715 displayByteBits( *p, 8, 0, false, log );
717 if ( endpos > beginpos )
719 displayByteBits( *(msg.buffer()+endpos), 8, 0, false, log );
725 * Returns the stream as a string with 0 and 1.
727 void CBitMemStream::displayStream( const char *title, CLog *log )
729 // nlassert( (_BufPos >= _Buffer.getPtr()) && (_BufPos <= _Buffer.getPtr() + _Buffer.size()) );
730 nlassert( _Buffer.Pos <= _Buffer.getBuffer().size() );
732 // Display title and information
733 string s = (isReading()?string("I"):string("O")) + string("BMS ") + string(title) + ": ";
734 string sLegend;
735 // if ( _BufPos == _Buffer.getPtr() )
736 if ( _Buffer.Pos == 0 )
738 log->displayNL( (s + "Empty").c_str() );
739 return;
742 // s += NLMISC::toString( "BitPos=%d Pos=%u FreeBits=%u Size=%u ", getPosInBit(), (uint32)(_BufPos-_Buffer.getPtr()), _FreeBits, _Buffer.size() );
743 s += NLMISC::toString( "BitPos=%d Pos=%u FreeBits=%u Size=%u ", getPosInBit(), _Buffer.Pos, _FreeBits, _Buffer.getBuffer().size() );
744 log->displayNL( s.c_str() );
745 s.clear();
747 // Display bitstream (output: until _BufPos/_FreeBits; input: whole buffer)
748 _DbgInfo.beginEventBrowsing();
749 sint32 eventId;
750 uint32 bitpos = 0;
751 const uint8 *p;
752 // uint8 *endPos = isReading() ? (_Buffer.getPtr() + _Buffer.size()) : (_BufPos+1);
753 const uint8 *endPos = isReading() ? (_Buffer.getBuffer().getPtr() + _Buffer.getBuffer().size()) : (_Buffer.getBuffer().getPtr() + _Buffer.Pos+1);
754 // for ( p=_Buffer.getPtr(); p!=endPos; ++p )
755 for ( p=_Buffer.getBuffer().getPtr(); p!=endPos; ++p )
757 sint i;
758 for ( i=7; i!=-1; --i )
760 //bitpos = (p-_Buffer.getPtr())*8 + (7-i);
761 if ( bitpos == (uint32)getPosInBit() )
762 s += "<P>"; // display the current position
763 s += _DbgInfo.getEventIdAtBitPos( bitpos, &eventId );
764 s += ( ((*p) >> i) & 1 ) ? '1' : '0';
765 sLegend += _DbgInfo.getEventLegendAtBitPos( *this, eventId );
766 ++bitpos;
769 s += ' '; // a blank char between each byte
770 if ( bitpos % 64 == 0 ) // limit to 8 bytes per line
772 log->displayRawNL( s.c_str() );
773 s.clear();
776 if ( bitpos % 64 != 0 )
777 log->displayRawNL( s.c_str() );
778 _DbgInfo.endEventBrowsing();
780 // Display legend
781 string::size_type lineStart = 0;
782 string::size_type crp = sLegend.find( '\n', lineStart );
783 while ( crp != string::npos )
785 log->displayRawNL( sLegend.substr( lineStart, crp-lineStart ).c_str() );
786 lineStart = crp + 1;
787 crp = sLegend.find( '\n', lineStart );
789 // sLegend ends with a '\n'
794 * Return a string showing the serial item
796 std::string CBitMemStream::getSerialItem( const TBMSSerialInfo& serialItem )
798 // Save the current pointers of the stream, and make them point to the required position
799 uint savedFreeBits = _FreeBits;
800 uint bytepos = serialItem.BitPos >> 3;
801 _FreeBits = 8 - (serialItem.BitPos - (bytepos << 3));
802 // uint8 *savedBufPos = _BufPos;
803 uint32 savedBufPos = _Buffer.Pos;
804 // _BufPos = _Buffer.getPtr() + bytepos;
805 _Buffer.Pos = bytepos;
807 bool wasOutput = false;;
808 if ( ! isReading() )
810 setInOut( true ); // lighter than invert()
811 wasOutput = true;
814 // Read and format string
815 string s;
816 if ( getPosInBit() + serialItem.BitSize > lengthR() * 8 )
818 s = "<Stream Overflow>";
820 else
822 switch ( serialItem.Type )
824 case TBMSSerialInfo::B:
826 bool b;
827 serialBit( b );
828 s = NLMISC::toString( "%s", b?"TRUE":"FALSE" );
829 break;
831 case TBMSSerialInfo::U: // no distinction with signed int!
833 uint32 u;
834 serial( u, serialItem.BitSize );
835 s = NLMISC::toString( "%u", u );
836 break;
838 case TBMSSerialInfo::U64: // no distinction with signed int64!
840 uint64 u;
841 serial( u, serialItem.BitSize );
842 s = NLMISC::toString( "%" NL_I64 "u", u );
843 break;
845 case TBMSSerialInfo::F: // what about double?
847 float f;
848 serial( f );
849 s = NLMISC::toString( "%g", f );
850 break;
852 case TBMSSerialInfo::BF:
854 CBitSet bs;
855 bs.resize( serialItem.BitSize );
856 readBits( bs );
857 s = bs.toString();
858 break;
860 case TBMSSerialInfo::Buffer:
862 uint32 len = serialItem.BitSize / 8;
863 s.resize( len + 2 );
864 if ( len != 0 )
866 serialBuffer( &((uint8&)(s[1])), len );
867 string::size_type p;
868 for ( p=1; p!=len+1; ++p )
870 if ( ! isalnum(s[p]) )
871 s[p] = '?'; // remove end-of-c_string
874 s[0] = '[';
875 s[len+1] = ']';
876 break;
878 default:
879 break;
883 // Restore the current pointers
884 if ( wasOutput )
886 setInOut( false );
889 _FreeBits = savedFreeBits;
890 // _BufPos = savedBufPos;
891 _Buffer.Pos = savedBufPos;
893 return s;
897 } // NLMISC