Strings - Fixed appendNumeric(INT64_MIN)

Couldn't work as it was trying to store the absolute value in a signed
64-bit integer.
This commit is contained in:
Emmanuel BENOîT 2020-10-01 13:20:50 +02:00
parent 9a3d4ad4a7
commit db215e4baf
2 changed files with 52 additions and 58 deletions

View file

@ -1939,63 +1939,21 @@ T_StringBuilder& T_StringBuilder::append( T_Character character )
T_StringBuilder& T_StringBuilder::appendNumeric( int64_t value , int base , bool useSep , T_Character sep , T_StringBuilder& T_StringBuilder::appendNumeric( int64_t value , int base , bool useSep , T_Character sep ,
int sepEvery ) int sepEvery )
{ {
assert( base >= 2 && base <= 36 );
assert( sepEvery > 0 );
assert( sep.isValid( ) );
if ( value == 0 ) { if ( value == 0 ) {
return append( '0' ); return append( '0' );
} }
const bool neg{ value < 0 };
const bool neg = value < 0; uint64_t absValue{ [=]{
const uint32_t size = 64 + ( useSep ? ( 64 / sepEvery ) : 0 )
+ ( neg ? 1 : 0 );
uint32_t output[ size ];
uint32_t len = 0 , ecap = 0;
int sepl = 0;
if ( neg ) { if ( neg ) {
value = -value; return uint64_t( -value );
} else {
return uint64_t( value );
} }
}() };
while ( value != 0 ) {
const uint32_t mod = value % base;
output[ size - ( len + 1 ) ] = mod
+ ( mod < 10 ? '0' : ( 'A' - 10 ) );
len ++;
sepl ++;
ecap ++;
assert( len < size );
value = ( value - mod ) / base;
if ( useSep && sepl == sepEvery && value != 0 ) {
output[ size - ( len + 1 ) ] = sep;
len ++;
sepl = 0;
ecap += 4;
assert( len < size );
}
}
if ( neg ) { if ( neg ) {
output[ size - ( len + 1 ) ] = '-'; append( '-' );
len ++;
ecap ++;
assert( len < size );
} }
return appendNumeric( absValue , base , useSep , sep , sepEvery );
ensureCapacity( size_ + ecap );
ecap = 0;
char* ptr = data_ + size_;
for ( uint32_t i = size - len ; i < size ; i ++ ) {
const uint32_t wr = UTF8PutCodepoint( ptr , 4 , output[ i ] );
ptr += wr;
ecap += wr;
}
size_ += ecap;
length_ += len;
return *this;
} }
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/

View file

@ -39,7 +39,13 @@ class StringsBuilderTest : public CppUnit::TestFixture
CPPUNIT_TEST( testAppendChar ); CPPUNIT_TEST( testAppendChar );
CPPUNIT_TEST( testAppendUnicode ); CPPUNIT_TEST( testAppendUnicode );
CPPUNIT_TEST( testAppendNumSigned ); CPPUNIT_TEST( testAppendNumSignedZeroB10 );
CPPUNIT_TEST( testAppendNumSignedPositiveB10 );
CPPUNIT_TEST( testAppendNumSignedNegativeB10 );
CPPUNIT_TEST( testAppendNumSignedMinB10 );
CPPUNIT_TEST( testAppendNumSignedMaxB10 );
CPPUNIT_TEST( testAppendNumSignedRest );
CPPUNIT_TEST( testAppendNumUnsigned ); CPPUNIT_TEST( testAppendNumUnsigned );
CPPUNIT_TEST( testAppendNumFloat ); CPPUNIT_TEST( testAppendNumFloat );
@ -134,7 +140,13 @@ public:
void testAppendChar( ); void testAppendChar( );
void testAppendUnicode( ); void testAppendUnicode( );
void testAppendNumSigned( ); void testAppendNumSignedZeroB10( );
void testAppendNumSignedPositiveB10( );
void testAppendNumSignedNegativeB10( );
void testAppendNumSignedMinB10( );
void testAppendNumSignedMaxB10( );
void testAppendNumSignedRest( );
void testAppendNumUnsigned( ); void testAppendNumUnsigned( );
void testAppendNumFloat( ); void testAppendNumFloat( );
@ -546,15 +558,39 @@ void StringsBuilderTest::testAppendUnicode( )
CPPUNIT_ASSERT( !memcmp( sbo.data( ) , t , sz ) ); \ CPPUNIT_ASSERT( !memcmp( sbo.data( ) , t , sz ) ); \
} }
void StringsBuilderTest::testAppendNumSigned( ) void StringsBuilderTest::testAppendNumSignedZeroB10( )
{ {
T_StringBuilder sbo; T_StringBuilder sbo;
sbo.clear( ).appendNumeric( int64_t( 1 ) ); M_CHECK_( "1" );
sbo.clear( ).appendNumeric( int64_t( 0 ) ); M_CHECK_( "0" ); sbo.clear( ).appendNumeric( int64_t( 0 ) ); M_CHECK_( "0" );
sbo.clear( ).appendNumeric( int64_t( -1 ) ); M_CHECK_( "-1" ); }
sbo.clear( ).appendNumeric( int64_t( 1234 ) ); M_CHECK_( "1234" );
sbo.clear( ).appendNumeric( int64_t( -1234 ) ); M_CHECK_( "-1234" );
void StringsBuilderTest::testAppendNumSignedNegativeB10( )
{
T_StringBuilder sbo;
sbo.clear( ).appendNumeric( int64_t( -1234 ) ); M_CHECK_( "-1234" );
}
void StringsBuilderTest::testAppendNumSignedPositiveB10( )
{
T_StringBuilder sbo;
sbo.clear( ).appendNumeric( int64_t( 1234 ) ); M_CHECK_( "1234" );
}
void StringsBuilderTest::testAppendNumSignedMinB10( )
{
T_StringBuilder sbo;
sbo.clear( ).appendNumeric( int64_t( INT64_MIN ) ); M_CHECK_( "-9223372036854775808" );
}
void StringsBuilderTest::testAppendNumSignedMaxB10( )
{
T_StringBuilder sbo;
sbo.clear( ).appendNumeric( int64_t( INT64_MAX ) ); M_CHECK_( "9223372036854775807" );
}
void StringsBuilderTest::testAppendNumSignedRest( )
{
T_StringBuilder sbo;
sbo.clear( ).appendNumeric( int64_t( 129 ) , 2 ); sbo.clear( ).appendNumeric( int64_t( 129 ) , 2 );
M_CHECK_( "10000001" ); M_CHECK_( "10000001" );
sbo.clear( ).appendNumeric( int64_t( -129 ) , 2 ); sbo.clear( ).appendNumeric( int64_t( -129 ) , 2 );