1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2016 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
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/>.
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"
37 #ifdef LOG_ALL_TRAFFIC
38 bool VerboseAllTraffic
= false;
42 const char * SerialTypeToCStr
[ TBMSSerialInfo::NbSerialTypes
] = { "Bool ", "Ui32N", "Ui64N", "Float", "Btfld", "Buffr" };
48 CBitMemStream::CBitMemStream( bool inputStream
, uint32 defaultcapacity
) :
49 CMemStream( inputStream
, false, defaultcapacity
),
59 CBitMemStream::CBitMemStream( const CBitMemStream
& other
) :
61 _FreeBits( other
._FreeBits
),
62 _DbgInfo( other
._DbgInfo
)
69 void CBitMemStream::swap(CBitMemStream
&other
)
71 CMemStream::swap(other
);
72 std::swap(_FreeBits
, other
._FreeBits
);
73 _DbgInfo
.swap(other
._DbgInfo
);
80 void CBitMemStream::serialBuffer( uint8
*buf
, uint len
)
82 _DbgInfo
.addSerial( getPosInBit(), len
*8, TBMSSerialInfo::Buffer
);
87 for ( i
=0; i
!=len
; ++i
)
89 internalSerial( v
, 8 );
95 for ( i
=0; i
!=len
; ++i
)
98 internalSerial( v
, 8 );
107 void CBitMemStream::serialBit( bool& bit
)
109 _DbgInfo
.addSerial( getPosInBit(), 1, TBMSSerialInfo::B
);
113 internalSerial( ubit
, 1 );
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();
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", "" )
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");
177 * Serialize only the nbits lower bits of value
179 void CBitMemStream::internalSerial( uint32
& value
, uint nbits
, bool resetvalue
)
184 throw EMemStream (string("trying to serial ")+NLMISC::toString(nbits
)+string(" bits"));
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
);
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
));
212 uint readbits
= _FreeBits
;
213 //displayByteBits( *_BufPos, 8, readbits-1, false );
215 internalSerial( value
, nbits
- readbits
, false ); // read without resetting value
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 );
224 if ( _FreeBits
== 0 )
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
240 if ( nbits
!= 32 ) // arg of shl/sal/shr/sal ranges from 0 to 31
242 uint32 mask
= (1 << nbits
) - 1;
251 // Check that the current byte is prepared
252 nlassert( ! ((_FreeBits
== 8) && (*(buffer
+_Buffer
.Pos
) != 0)) );
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 );
266 internalSerial( v
, nbits
- filledbits
);
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 );
277 if ( _FreeBits
== 0 )
287 * Same as CMemStream::reserve()
289 sint32
CBitMemStream::reserve( uint byteLen
)
292 reserveBits( byteLen
* 8 );
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() );
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
)
325 if ( nbits
!= 32 ) // arg of shl/sal/shr/sal ranges from 0 to 31
327 uint32 mask
= (1 << nbits
) - 1;
335 uint8
*buffer
= _Buffer
.getBufferWrite().getPtr();
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
);
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 );
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.
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
)
381 nlassert( (nbits
<= 32) && (nbits
!= 0) );
382 nlassert( ! isReading() );
383 nlassert( bitpos
+nbits
<= (uint
)getPosInBit() );
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
;
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
)
413 nlassert( ! isReading() );
414 nlassert( bitpos
+bitfield
.size() <= (uint
)getPosInBit() );
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
;
427 _DbgInfo
.addPoke( bitpos
, bitfield
.size(), TBMSSerialInfo::BF
);
428 const vector
<uint32
>& uintVec
= bitfield
.getVector();
429 if ( ! uintVec
.empty() )
431 uint len
= bitfield
.size();
435 serialPoke( uintVec
[i
], 32 );
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
)
457 nlassert( isReading() );
459 uint len
= bitfield
.size();
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() );
471 //nldebug( "Bitfield: Read %u at %d", v, _BufPos-_Buffer.getPtr()-4 );
472 bitfield
.setUint( v
, i
);
477 //nldebug( "Bitfield: Read %u at %d", v, _BufPos-_Buffer.getPtr()-4 );
478 bitfield
.setUint( v
, i
);
486 void CBitMemStream::serial(float &b
)
488 _DbgInfo
.addSerial( getPosInBit(), sizeof(b
)*8, TBMSSerialInfo::F
);
492 internalSerial( uf
, sizeof(b
)*8 );
493 memcpy(&b
, &uf
, sizeof(b
));
497 memcpy(&uf
, &b
, sizeof(b
));
498 internalSerial( uf
, sizeof(b
)*8 );
506 void CBitMemStream::serial(std::string
&b
)
508 #ifdef LOG_ALL_TRAFFIC
509 sint32 bitpos
= getPosInBit();
518 if (len
> length()-(uint32
)getPos())
519 throw NLMISC::EInvalidDataStream( "BMS: Trying to read a string of %u bytes, past stream size", len
);
524 len
= (uint32
)b
.size();
526 throw NLMISC::EInvalidDataStream( "BMS: Trying to write a string of %u bytes", len
);
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
);
546 inline void CBitMemStream::serial(ucstring
&b
)
548 #ifdef LOG_ALL_TRAFFIC
549 sint32 bitpos
= getPosInBit();
555 // Read/Write the length.
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
);
565 len
= (uint32
)b
.size();
567 throw NLMISC::EInvalidDataStream( "BMS: Trying to write an ucstring of %u bytes", 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 );
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
);
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();
619 // fill b with data from this
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
);
629 // fill this with data from b
631 // Accept to write a big sized BMS
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
);
644 * Specialisation of serialCont() for vector<bool>
646 void CBitMemStream::serialCont(std::vector
<bool> &cont
)
648 #ifdef LOG_ALL_TRAFFIC
649 sint32 bitpos
= getPosInBit();
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.
664 for(sint i
=0;i
<len
;i
++)
668 cont
.insert(cont
.end(), v
);
673 len
= (sint32
)cont
.size();
676 std::vector
<bool>::iterator it
= cont
.begin();
677 for(sint i
=0;i
<len
;i
++, it
++)
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
);
693 * Display the bits of the stream just before the current pos
695 void CBitMemStream::displayLastBits( sint nbits
, sint bitpos
, NLMISC::CLog
*log
)
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
);
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
) + ": ";
735 // if ( _BufPos == _Buffer.getPtr() )
736 if ( _Buffer
.Pos
== 0 )
738 log
->displayNL( (s
+ "Empty").c_str() );
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() );
747 // Display bitstream (output: until _BufPos/_FreeBits; input: whole buffer)
748 _DbgInfo
.beginEventBrowsing();
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
)
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
);
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() );
776 if ( bitpos
% 64 != 0 )
777 log
->displayRawNL( s
.c_str() );
778 _DbgInfo
.endEventBrowsing();
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() );
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;;
810 setInOut( true ); // lighter than invert()
814 // Read and format string
816 if ( getPosInBit() + serialItem
.BitSize
> lengthR() * 8 )
818 s
= "<Stream Overflow>";
822 switch ( serialItem
.Type
)
824 case TBMSSerialInfo::B
:
828 s
= NLMISC::toString( "%s", b
?"TRUE":"FALSE" );
831 case TBMSSerialInfo::U
: // no distinction with signed int!
834 serial( u
, serialItem
.BitSize
);
835 s
= NLMISC::toString( "%u", u
);
838 case TBMSSerialInfo::U64
: // no distinction with signed int64!
841 serial( u
, serialItem
.BitSize
);
842 s
= NLMISC::toString( "%" NL_I64
"u", u
);
845 case TBMSSerialInfo::F
: // what about double?
849 s
= NLMISC::toString( "%g", f
);
852 case TBMSSerialInfo::BF
:
855 bs
.resize( serialItem
.BitSize
);
860 case TBMSSerialInfo::Buffer
:
862 uint32 len
= serialItem
.BitSize
/ 8;
866 serialBuffer( &((uint8
&)(s
[1])), len
);
868 for ( p
=1; p
!=len
+1; ++p
)
870 if ( ! isalnum(s
[p
]) )
871 s
[p
] = '?'; // remove end-of-c_string
883 // Restore the current pointers
889 _FreeBits
= savedFreeBits
;
890 // _BufPos = savedBufPos;
891 _Buffer
.Pos
= savedBufPos
;