support O(U)String::number() for fast string concatenation

When I did the fast string concatenation, I didn't add any support
for number(), which simply returned a O(U)String, and so it did
the extra allocation/deallocation, although that could be avoided.
In order to support this, number() now returns a special temporary
return type, similarly to O(U)StringConcat, which allows delaying
the concatenation the same way.
Also similarly, the change of the return type in some cases requires
explicit cast to the actual string type. Usage of OString::getStr()
is so extensive in the codebase that I actually added it to the helper
class, after that it's only relatively few cases.

Change-Id: Iba6e158010e1e458089698c426803052b6f46031
Reviewed-on: https://gerrit.libreoffice.org/78873
Tested-by: Jenkins
Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
This commit is contained in:
Luboš Luňák 2019-09-13 15:13:55 +02:00
parent a7d40f5754
commit 2f5f45921b
36 changed files with 483 additions and 76 deletions

View File

@ -50,7 +50,7 @@
else \
{ \
OString sTestFileName = OUStringToOString(getTestFileName(), RTL_TEXTENCODING_UTF8); \
CPPUNIT_ASSERT_EQUAL_MESSAGE(OString("Failing test file is: " + sTestFileName).getStr(), readExpected(#aActual), OUString::number(aActual)); \
CPPUNIT_ASSERT_EQUAL_MESSAGE(OString("Failing test file is: " + sTestFileName).getStr(), readExpected(#aActual), OUString(OUString::number(aActual))); \
}
#define CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aActual, EPS_) \

View File

@ -87,6 +87,10 @@ bool StringConcatAuto::checkDecl( const DeclaratorDecl* decl, QualType type, con
typeString = "OUString";
else if( tc.Struct("OStringConcat").Namespace("rtl").GlobalNamespace())
typeString = "OString";
else if( tc.Struct("OUStringNumber").Namespace("rtl").GlobalNamespace())
typeString = "OUString";
else if( tc.Struct("OStringNumber").Namespace("rtl").GlobalNamespace())
typeString = "OString";
else
return true;
report( DiagnosticsEngine::Warning,

View File

@ -23,10 +23,14 @@ void foo()
const auto str4 = "str4" + OString::number( 40 );
// expected-error-re@-1 {{creating a variable of type 'const rtl::OStringConcat<{{.*}}>' will make it reference temporaries}}
// expected-note@-2 {{use OString instead}}
auto str5 = OUString::number( 50 );
// expected-error-re@-1 {{creating a variable of type 'rtl::OUStringNumber<{{.*}}>' will make it reference temporaries}}
// expected-note@-2 {{use OUString instead}}
(void) str1;
(void) str2;
(void) str3;
(void) str4;
(void) str5;
}
struct A
@ -37,6 +41,12 @@ struct A
{
return "bar" + OString::number( 110 );
}
auto baz()
// expected-error-re@-1 {{returning a variable of type 'rtl::OStringNumber<{{.*}}>' will make it reference temporaries}}
// expected-note@-2 {{use OString instead}}
{
return OString::number( 120 );
}
};
template< typename T >

View File

@ -155,19 +155,19 @@ void writeValueContent_(TempFile &handle, sal_Bool value) {
}
void writeValueContent_(TempFile &handle, sal_Int16 value) {
handle.writeString(OString::number(value));
handle.writeString(OString(OString::number(value)));
}
void writeValueContent_(TempFile &handle, sal_Int32 value) {
handle.writeString(OString::number(value));
handle.writeString(OString(OString::number(value)));
}
void writeValueContent_(TempFile &handle, sal_Int64 value) {
handle.writeString(OString::number(value));
handle.writeString(OString(OString::number(value)));
}
void writeValueContent_(TempFile &handle, double value) {
handle.writeString(OString::number(value));
handle.writeString(OString(OString::number(value)));
}
void writeValueContent_(TempFile &handle, const OUString& value) {
@ -530,7 +530,7 @@ void writeValueContent(TempFile &handle, std::u16string_view value) {
{
handle.writeString(convertToUtf8(value.substr(i, j - i)));
handle.writeString("<unicode oor:scalar=\"");
handle.writeString(OString::number(c));
handle.writeString(OString(OString::number(c)));
handle.writeString("\"/>");
i = j + 1;
} else if (c == '\x0D') {

View File

@ -103,7 +103,7 @@ ORowSetValue OOp_Locate::operate(const std::vector<ORowSetValue>& lhs) const
return ORowSetValue();
if ( lhs.size() == 2 )
return OUString::number(lhs[0].getString().indexOf(lhs[1].getString())+1);
return OUString(OUString::number(lhs[0].getString().indexOf(lhs[1].getString())+1));
else if ( lhs.size() != 3 )
return ORowSetValue();

View File

@ -681,7 +681,7 @@ bool OFlatTable::fetchRow(OValueRefRow& _rRow, const OSQLColumns & _rCols, bool
// #99178# OJ
if ( DataType::DECIMAL == nType || DataType::NUMERIC == nType )
*(_rRow->get())[i] = OUString::number(nVal);
*(_rRow->get())[i] = OUString(OUString::number(nVal));
else
*(_rRow->get())[i] = nVal;
} break;

View File

@ -873,7 +873,7 @@ IMPL_LINK(SvxCharacterMap, CharClickHdl, SvxCharView*, rView, void)
OUString charValue = rView->GetText();
sal_Int32 tmp = 1;
sal_UCS4 cChar = charValue.iterateCodePoints(&tmp, -1);
OUString aHexText = OUString::number(cChar, 16).toAsciiUpperCase();
OUString aHexText = OUString(OUString::number(cChar, 16)).toAsciiUpperCase();
// Get the decimal code
OUString aDecimalText = OUString::number(cChar);
@ -961,7 +961,7 @@ IMPL_LINK_NOARG(SvxCharacterMap, CharHighlightHdl, SvxShowCharSet*, void)
// using the new UCS4 constructor
aText = OUString( &cChar, 1 );
// Get the hexadecimal code
aHexText = OUString::number(cChar, 16).toAsciiUpperCase();
aHexText = OUString(OUString::number(cChar, 16)).toAsciiUpperCase();
// Get the decimal code
aDecimalText = OUString::number(cChar);
setCharName(cChar);
@ -1001,7 +1001,7 @@ IMPL_LINK_NOARG(SvxCharacterMap, SearchCharHighlightHdl, SvxShowCharSet*, void)
{
aText = OUString( &cChar, 1 );
// Get the hexadecimal code
aHexText = OUString::number(cChar, 16).toAsciiUpperCase();
aHexText = OUString(OUString::number(cChar, 16)).toAsciiUpperCase();
// Get the decimal code
aDecimalText = OUString::number(cChar);
setCharName(cChar);

View File

@ -5162,7 +5162,8 @@ static void lo_status_indicator_callback(void *data, comphelper::LibreOfficeKit:
pLib->mpCallback(LOK_CALLBACK_STATUS_INDICATOR_START, nullptr, pLib->mpCallbackData);
break;
case comphelper::LibreOfficeKit::statusIndicatorCallbackType::SetValue:
pLib->mpCallback(LOK_CALLBACK_STATUS_INDICATOR_SET_VALUE, OUString::number(percent).toUtf8().getStr(), pLib->mpCallbackData);
pLib->mpCallback(LOK_CALLBACK_STATUS_INDICATOR_SET_VALUE,
OUString(OUString::number(percent)).toUtf8().getStr(), pLib->mpCallbackData);
break;
case comphelper::LibreOfficeKit::statusIndicatorCallbackType::Finish:
pLib->mpCallback(LOK_CALLBACK_STATUS_INDICATOR_FINISH, nullptr, pLib->mpCallbackData);

View File

@ -701,16 +701,16 @@ void SvxNumRule::Store( SvStream &rStream )
void SvxNumRule::dumpAsXml(xmlTextWriterPtr pWriter) const
{
xmlTextWriterStartElement(pWriter, BAD_CAST("SvxNumRule"));
xmlTextWriterWriteAttribute(pWriter, BAD_CAST("levelCount"), BAD_CAST(OUString::number(nLevelCount).getStr()));
xmlTextWriterWriteAttribute(pWriter, BAD_CAST("continuousNumbering"), BAD_CAST(OUString::boolean(bContinuousNumbering).getStr()));
xmlTextWriterWriteAttribute(pWriter, BAD_CAST("numberingType"), BAD_CAST(OUString::number(static_cast<int>(eNumberingType)).getStr()));
xmlTextWriterWriteAttribute(pWriter, BAD_CAST("featureFlags"), BAD_CAST(OUString::number(static_cast<int>(nFeatureFlags)).getStr()));
xmlTextWriterWriteAttribute(pWriter, BAD_CAST("levelCount"), BAD_CAST(OString::number(nLevelCount).getStr()));
xmlTextWriterWriteAttribute(pWriter, BAD_CAST("continuousNumbering"), BAD_CAST(OString::boolean(bContinuousNumbering).getStr()));
xmlTextWriterWriteAttribute(pWriter, BAD_CAST("numberingType"), BAD_CAST(OString::number(static_cast<int>(eNumberingType)).getStr()));
xmlTextWriterWriteAttribute(pWriter, BAD_CAST("featureFlags"), BAD_CAST(OString::number(static_cast<int>(nFeatureFlags)).getStr()));
for(sal_uInt16 i = 0; i < SVX_MAX_NUM; i++)
{
if(aFmts[i])
{
xmlTextWriterStartElement(pWriter, BAD_CAST("aFmts"));
xmlTextWriterWriteAttribute(pWriter, BAD_CAST("i"), BAD_CAST(OUString::number(i).getStr()));
xmlTextWriterWriteAttribute(pWriter, BAD_CAST("i"), BAD_CAST(OString::number(i).getStr()));
xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", aFmts[i].get());
xmlTextWriterEndElement(pWriter);
}

View File

@ -299,8 +299,8 @@ void SpinfieldToolbarController::executeControlCommand( const css::frame::Contro
double fValue;
bool bFloat( false );
if ( impl_getValue( rControlCommand.Arguments[i].Value, nValue, fValue, bFloat ))
aStep = bFloat ? OUString::number( fValue ) :
OUString::number( nValue );
aStep = bFloat ? OUString( OUString::number( fValue )) :
OUString( OUString::number( nValue ));
break;
}
}
@ -317,7 +317,8 @@ void SpinfieldToolbarController::executeControlCommand( const css::frame::Contro
if ( impl_getValue( rControlCommand.Arguments[i].Value, nValue, fValue, bFloat ))
{
aValue = bFloat ? OUString::number( fValue ) : OUString::number( nValue );
aValue = bFloat ? OUString( OUString::number( fValue )) :
OUString( OUString::number( nValue ));
bFloatValue = bFloat;
}
break;
@ -337,18 +338,19 @@ void SpinfieldToolbarController::executeControlCommand( const css::frame::Contro
{
if ( aName == "Value" )
{
aValue = bFloat ? OUString::number( fValue ) : OUString::number( nValue );
aValue = bFloat ? OUString( OUString::number( fValue )) :
OUString( OUString::number( nValue ));
bFloatValue = bFloat;
}
else if ( aName == "Step" )
aStep = bFloat ? OUString::number( fValue ) :
OUString::number( nValue );
aStep = bFloat ? OUString( OUString::number( fValue )) :
OUString( OUString::number( nValue ));
else if ( aName == "LowerLimit" )
aMin = bFloat ? OUString::number( fValue ) :
OUString::number( nValue );
aMin = bFloat ? OUString( OUString::number( fValue )) :
OUString( OUString::number( nValue ));
else if ( aName == "UpperLimit" )
aMax = bFloat ? OUString::number( fValue ) :
OUString::number( nValue );
aMax = bFloat ? OUString( OUString::number( fValue )) :
OUString( OUString::number( nValue ));
}
else if ( aName == "OutputFormat" )
rControlCommand.Arguments[i].Value >>= m_aOutFormat;
@ -364,8 +366,8 @@ void SpinfieldToolbarController::executeControlCommand( const css::frame::Contro
double fValue;
bool bFloat( false );
if ( impl_getValue( rControlCommand.Arguments[i].Value, nValue, fValue, bFloat ))
aMin = bFloat ? OUString::number( fValue ) :
OUString::number( nValue );
aMin = bFloat ? OUString( OUString::number( fValue )) :
OUString( OUString::number( nValue ));
break;
}
}
@ -380,8 +382,8 @@ void SpinfieldToolbarController::executeControlCommand( const css::frame::Contro
double fValue;
bool bFloat( false );
if ( impl_getValue( rControlCommand.Arguments[i].Value, nValue, fValue, bFloat ))
aMax = bFloat ? OUString::number( fValue ) :
OUString::number( nValue );
aMax = bFloat ? OUString( OUString::number( fValue )) :
OUString( OUString::number( nValue ));
break;
}
}

View File

@ -249,6 +249,14 @@ template<typename T1, typename T2>
Any toAny(rtl::OUStringConcat<T1, T2> && value)
{ return makeAny(std::move(value)); }
template<typename T>
Any makeAny(rtl::OUStringNumber<T> && value)
{ return Any(OUString(std::move(value))); }
template<typename T>
Any toAny(rtl::OUStringNumber<T> && value)
{ return makeAny(std::move(value)); }
template<typename T> bool fromAny(Any const & any, T * value) {
assert(value != nullptr);
return any >>= *value;
@ -295,6 +303,17 @@ inline void SAL_CALL operator <<= ( Any & rAny, rtl::OUStringConcat< C1, C2 >&&
}
template<typename T1, typename T2>
void operator <<=(Any &, rtl::OUStringConcat<T1, T2> const &) = delete;
template< class C >
inline void SAL_CALL operator <<= ( Any & rAny, rtl::OUStringNumber< C >&& value )
{
const rtl::OUString str( std::move(value) );
const Type & rType = ::cppu::getTypeFavourUnsigned(&str);
::uno_type_any_assign(
&rAny, const_cast< rtl::OUString * >( &str ), rType.getTypeLibType(),
cpp_acquire, cpp_release );
}
template<typename T>
void operator <<=(Any &, rtl::OUStringNumber<T> const &) = delete;
#endif
#if defined LIBO_INTERNAL_ONLY

View File

@ -222,6 +222,15 @@ public:
*end = '\0';
pData->length = l;
}
/**
@overload
@internal
*/
template< typename T >
OStringBuffer( OStringNumber< T >&& n )
: OStringBuffer( OString( n ))
{}
#endif
/** Assign to this a copy of value.
@ -287,6 +296,13 @@ public:
pData->length = n;
return *this;
}
/** @overload @internal */
template<typename T>
OStringBuffer & operator =(OStringNumber<T> && n)
{
return *this = OStringBuffer( std::move ( n ));
}
#endif
/**
@ -560,6 +576,17 @@ public:
pData->length = l;
return *this;
}
/**
@overload
@internal
*/
template< typename T >
OStringBuffer& append( OStringNumber< T >&& c )
{
return append( c.buf, c.length );
}
#endif
/**

View File

@ -280,6 +280,15 @@ public:
*end = '\0';
}
}
/**
@overload
@internal
*/
template< typename T >
OString( OStringNumber< T >&& n )
: OString( n.buf, n.length )
{}
#endif
#ifdef LIBO_INTERNAL_ONLY
@ -383,6 +392,25 @@ public:
}
template<typename T1, typename T2> void operator +=(
OStringConcat<T1, T2> &&) && = delete;
/**
@overload
@internal
*/
template< typename T >
OString& operator+=( OStringNumber< T >&& n ) & {
sal_Int32 l = n.length;
if( l == 0 )
return *this;
l += pData->length;
rtl_string_ensureCapacity( &pData, l );
char* end = addDataHelper( pData->buffer + pData->length, n.buf, n.length );
*end = '\0';
pData->length = l;
return *this;
}
template<typename T> void operator +=(
OStringNumber<T> &&) && = delete;
#endif
/**
@ -1602,6 +1630,41 @@ public:
return rtl_str_toDouble( pData->buffer );
}
#ifdef LIBO_INTERNAL_ONLY // "RTL_FAST_STRING"
static OStringNumber< int > number( int i, sal_Int16 radix = 10 )
{
return OStringNumber< int >( i, radix );
}
static OStringNumber< long long > number( long long ll, sal_Int16 radix = 10 )
{
return OStringNumber< long long >( ll, radix );
}
static OStringNumber< unsigned long long > number( unsigned long long ll, sal_Int16 radix = 10 )
{
return OStringNumber< unsigned long long >( ll, radix );
}
static OStringNumber< unsigned long long > number( unsigned int i, sal_Int16 radix = 10 )
{
return number( static_cast< unsigned long long >( i ), radix );
}
static OStringNumber< long long > number( long i, sal_Int16 radix = 10)
{
return number( static_cast< long long >( i ), radix );
}
static OStringNumber< unsigned long long > number( unsigned long i, sal_Int16 radix = 10 )
{
return number( static_cast< unsigned long long >( i ), radix );
}
static OStringNumber< float > number( float f )
{
return OStringNumber< float >( f );
}
static OStringNumber< double > number( double d )
{
return OStringNumber< double >( d );
}
#else
/**
Returns the string representation of the integer argument.
@ -1686,6 +1749,7 @@ public:
rtl_string_newFromStr_WithLength( &pNewData, aBuf, rtl_str_valueOfDouble( aBuf, d ) );
return OString( pNewData, SAL_NO_ACQUIRE );
}
#endif
/**
Returns the string representation of the sal_Bool argument.

View File

@ -11,6 +11,8 @@
#define INCLUDED_RTL_STRINGCONCAT_HXX
#include "rtl/stringutils.hxx"
#include "rtl/string.h"
#include "rtl/ustring.h"
#include <cstddef>
#include <string.h>
@ -168,6 +170,9 @@ template<> struct ToStringHelper<OUStringLiteral1_> {
Objects returned by operator+, instead of OString. These objects (possibly recursively) keep a representation of the whole
concatenation operation.
If you get a build error related to this class, you most probably need to explicitly convert the result of a string
concatenation to OString.
*/
template< typename T1, typename T2 >
struct OStringConcat
@ -189,6 +194,9 @@ struct OStringConcat
Objects returned by operator+, instead of OUString. These objects (possibly recursively) keep a representation of the whole
concatenation operation.
If you get a build error related to this class, you most probably need to explicitly convert the result of a string
concatenation to OUString.
*/
template< typename T1, typename T2 >
struct OUStringConcat
@ -302,6 +310,156 @@ int operator+( const StringConcatInvalid&, const T& )
}
#endif
/**
@internal
Objects returned by OString::number(), instead of OString. These objects keep a representation of the number() operation.
If you get a build error related to this class, you most probably need to explicitly convert the result of calling
OString::number() to OString.
*/
template< typename T >
struct OStringNumber;
template<>
struct OStringNumber< int >
{
OStringNumber( int i, sal_Int16 radix )
: length( rtl_str_valueOfInt32( buf, i, radix ))
{}
// OString::number(value).getStr() is very common (writing xml code, ...),
// so implement that one also here, to avoid having to explicitly to convert
// to OString in all such places
const char * getStr() const SAL_RETURNS_NONNULL { return buf; }
char buf[RTL_STR_MAX_VALUEOFINT32];
const sal_Int32 length;
};
template<>
struct OStringNumber< long long >
{
OStringNumber( long long ll, sal_Int16 radix )
: length( rtl_str_valueOfInt64( buf, ll, radix ))
{}
const char * getStr() const SAL_RETURNS_NONNULL { return buf; }
char buf[RTL_STR_MAX_VALUEOFINT64];
const sal_Int32 length;
};
template<>
struct OStringNumber< unsigned long long >
{
OStringNumber( unsigned long long ll, sal_Int16 radix )
: length( rtl_str_valueOfUInt64( buf, ll, radix ))
{}
const char * getStr() const SAL_RETURNS_NONNULL { return buf; }
char buf[RTL_STR_MAX_VALUEOFUINT64];
const sal_Int32 length;
};
template<>
struct OStringNumber< float >
{
OStringNumber( float f )
: length( rtl_str_valueOfFloat( buf, f ))
{}
const char * getStr() const SAL_RETURNS_NONNULL { return buf; }
char buf[RTL_STR_MAX_VALUEOFFLOAT];
const sal_Int32 length;
};
template<>
struct OStringNumber< double >
{
OStringNumber( double d )
: length( rtl_str_valueOfDouble( buf, d ))
{}
const char * getStr() const SAL_RETURNS_NONNULL { return buf; }
char buf[RTL_STR_MAX_VALUEOFDOUBLE];
const sal_Int32 length;
};
template< typename T >
struct ToStringHelper< OStringNumber< T > >
{
static int length( const OStringNumber< T >& n ) { return n.length; }
static char* addData( char* buffer, const OStringNumber< T >& n ) SAL_RETURNS_NONNULL { return addDataHelper( buffer, n.buf, n.length ); }
static const bool allowOStringConcat = true;
static const bool allowOUStringConcat = false;
};
/**
@internal
Objects returned by OUString::number(), instead of OUString. These objects keep a representation of the number() operation.
If you get a build error related to this class, you most probably need to explicitly convert the result of calling
OUString::number() to OUString.
*/
template< typename T >
struct OUStringNumber;
template<>
struct OUStringNumber< int >
{
OUStringNumber( int i, sal_Int16 radix )
: length( rtl_ustr_valueOfInt32( buf, i, radix ))
{}
sal_Unicode buf[RTL_USTR_MAX_VALUEOFINT32];
const sal_Int32 length;
};
template<>
struct OUStringNumber< long long >
{
OUStringNumber( long long ll, sal_Int16 radix )
: length( rtl_ustr_valueOfInt64( buf, ll, radix ))
{}
sal_Unicode buf[RTL_USTR_MAX_VALUEOFINT64];
const sal_Int32 length;
};
template<>
struct OUStringNumber< unsigned long long >
{
OUStringNumber( unsigned long long ll, sal_Int16 radix )
: length( rtl_ustr_valueOfUInt64( buf, ll, radix ))
{}
sal_Unicode buf[RTL_USTR_MAX_VALUEOFUINT64];
const sal_Int32 length;
};
template<>
struct OUStringNumber< float >
{
OUStringNumber( float f )
: length( rtl_ustr_valueOfFloat( buf, f ))
{}
sal_Unicode buf[RTL_USTR_MAX_VALUEOFFLOAT];
const sal_Int32 length;
};
template<>
struct OUStringNumber< double >
{
OUStringNumber( double d )
: length( rtl_ustr_valueOfDouble( buf, d ))
{}
sal_Unicode buf[RTL_USTR_MAX_VALUEOFDOUBLE];
const sal_Int32 length;
};
template< typename T >
struct ToStringHelper< OUStringNumber< T > >
{
static int length( const OUStringNumber< T >& n ) { return n.length; }
static sal_Unicode* addData( sal_Unicode* buffer, const OUStringNumber< T >& n ) SAL_RETURNS_NONNULL { return addDataHelper( buffer, n.buf, n.length ); }
static const bool allowOStringConcat = false;
static const bool allowOUStringConcat = true;
};
} // namespace
#endif

View File

@ -224,6 +224,18 @@ public:
pData->length = l;
// TODO realloc in case pData->>length is noticeably smaller than l ?
}
/**
@overload
@internal
*/
template< typename T >
OUStringBuffer( OUStringNumber< T >&& n )
: pData(NULL)
, nCapacity( n.length + 16 )
{
rtl_uStringbuffer_newFromStr_WithLength( &pData, n.buf, n.length );
}
#endif
/** Assign to this a copy of value.
*/
@ -328,6 +340,13 @@ public:
pData->length = n;
return *this;
}
/** @overload @internal */
template<typename T>
OUStringBuffer & operator =(OUStringNumber<T> && n)
{
return *this = OUStringBuffer( std::move( n ));
}
#endif
/**
@ -658,6 +677,16 @@ public:
pData->length = l;
return *this;
}
/**
@overload
@internal
*/
template< typename T >
OUStringBuffer& append( OUStringNumber< T >&& c )
{
return append( c.buf, c.length );
}
#endif
/**

View File

@ -1000,7 +1000,7 @@ SAL_DLLPUBLIC sal_Int32 SAL_CALL rtl_ustr_valueOfInt64(
*/
SAL_DLLPUBLIC sal_Int32 SAL_CALL rtl_ustr_valueOfUInt64(
sal_Unicode * str, sal_uInt64 l, sal_Int16 radix ) SAL_THROW_EXTERN_C();
#define RTL_USTR_MAX_VALUEOFINT64 RTL_STR_MAX_VALUEOFINT64
#define RTL_USTR_MAX_VALUEOFUINT64 RTL_STR_MAX_VALUEOFUINT64
/** Create the string representation of a float.

View File

@ -409,6 +409,15 @@ public:
// TODO realloc in case pData->length is noticeably smaller than l?
}
}
/**
@overload
@internal
*/
template< typename T >
OUString( OUStringNumber< T >&& n )
: OUString( n.buf, n.length )
{}
#endif
#if defined LIBO_INTERNAL_ONLY
@ -632,6 +641,25 @@ public:
}
template<typename T1, typename T2> void operator +=(
OUStringConcat<T1, T2> &&) && = delete;
/**
@overload
@internal
*/
template< typename T >
OUString& operator+=( OUStringNumber< T >&& n ) & {
sal_Int32 l = n.length;
if( l == 0 )
return *this;
l += pData->length;
rtl_uString_ensureCapacity( &pData, l );
sal_Unicode* end = addDataHelper( pData->buffer + pData->length, n.buf, n.length );
*end = '\0';
pData->length = l;
return *this;
}
template<typename T> void operator +=(
OUStringNumber<T> &&) && = delete;
#endif
/**
@ -3345,6 +3373,41 @@ public:
return aTarget;
}
#ifdef LIBO_INTERNAL_ONLY // "RTL_FAST_STRING"
static OUStringNumber< int > number( int i, sal_Int16 radix = 10 )
{
return OUStringNumber< int >( i, radix );
}
static OUStringNumber< long long > number( long long ll, sal_Int16 radix = 10 )
{
return OUStringNumber< long long >( ll, radix );
}
static OUStringNumber< unsigned long long > number( unsigned long long ll, sal_Int16 radix = 10 )
{
return OUStringNumber< unsigned long long >( ll, radix );
}
static OUStringNumber< unsigned long long > number( unsigned int i, sal_Int16 radix = 10 )
{
return number( static_cast< unsigned long long >( i ), radix );
}
static OUStringNumber< long long > number( long i, sal_Int16 radix = 10)
{
return number( static_cast< long long >( i ), radix );
}
static OUStringNumber< unsigned long long > number( unsigned long i, sal_Int16 radix = 10 )
{
return number( static_cast< unsigned long long >( i ), radix );
}
static OUStringNumber< float > number( float f )
{
return OUStringNumber< float >( f );
}
static OUStringNumber< double > number( double d )
{
return OUStringNumber< double >( d );
}
#else
/**
Returns the string representation of the integer argument.
@ -3432,6 +3495,7 @@ public:
rtl_uString_newFromStr_WithLength( &pNewData, aBuf, rtl_ustr_valueOfDouble( aBuf, d ) );
return OUString( pNewData, SAL_NO_ACQUIRE );
}
#endif
/**
Returns the string representation of the sal_Bool argument.

View File

@ -3137,7 +3137,7 @@ void writeLabelProperties( const FSHelperPtr& pFS, ChartExport* pChartExport,
{
pFS->startElement(FSNS(XML_a, XML_solidFill));
OString aStr = OString::number(nLabelBorderColor, 16).toAsciiUpperCase();
OString aStr = OString(OString::number(nLabelBorderColor, 16)).toAsciiUpperCase();
pFS->singleElement(FSNS(XML_a, XML_srgbClr), XML_val, aStr);
pFS->endElement(FSNS(XML_a, XML_solidFill));

View File

@ -896,11 +896,11 @@ public:
std::unique_ptr<OUString[]> pStrs(new OUString[nSequence]);
for (i = 0; i < nSequence; i++)
{
pStrs[i] = OUString::number( sqrt( static_cast<double>(i) ) ).intern();
pStrs[i] = OUString( OUString::number( sqrt( static_cast<double>(i) ) ) ).intern();
}
for (i = 0; i < nSequence; i++)
{
OUString aNew = OUString::number( sqrt( static_cast<double>(i) ) ).intern();
OUString aNew = OUString( OUString::number( sqrt( static_cast<double>(i) ) ) ).intern();
CPPUNIT_ASSERT_EQUAL_MESSAGE("double intern failed",
pStrs[i].pData, aNew.pData);
}

View File

@ -81,6 +81,19 @@ void test::ostring::StringConcat::checkConcat()
CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, const char* > )), typeid( OString( "foo" ) + d3 ));
CPPUNIT_ASSERT_EQUAL( OString( "fooabc" ), OString( OString( "foo" ) + d4 ));
CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, char* > )), typeid( OString( "foo" ) + d4 ));
CPPUNIT_ASSERT_EQUAL( OString( "fooabc" ), OString( OString( "foo" ) + d4 ));
CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, char* > )), typeid( OString( "foo" ) + d4 ));
CPPUNIT_ASSERT_EQUAL( OString( "num10" ), OString( OString( "num" ) + OString::number( 10 )));
CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, OStringNumber< int > > )), typeid( OString( "num" ) + OString::number( 10 )));
CPPUNIT_ASSERT_EQUAL( OString( "num10" ), OString( OString( "num" ) + OString::number( 10L )));
CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, OStringNumber< long long > > )), typeid( OString( "num" ) + OString::number( 10L )));
CPPUNIT_ASSERT_EQUAL( OString( "num10" ), OString( OString( "num" ) + OString::number( 10ULL )));
CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, OStringNumber< unsigned long long > > )), typeid( OString( "num" ) + OString::number( 10ULL )));
CPPUNIT_ASSERT_EQUAL( OString( "num10.5" ), OString( OString( "num" ) + OString::number( 10.5f )));
CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, OStringNumber< float > > )), typeid( OString( "num" ) + OString::number( 10.5f )));
CPPUNIT_ASSERT_EQUAL( OString( "num10.5" ), OString( OString( "num" ) + OString::number( 10.5 )));
CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, OStringNumber< double > > )), typeid( OString( "num" ) + OString::number( 10.5 )));
}
void test::ostring::StringConcat::checkEnsureCapacity()
@ -149,6 +162,8 @@ void test::ostring::StringConcat::checkInvalid()
rtl_uString* rus = nullptr;
CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "b" ) + rs ));
CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "b" ) + rus ));
CPPUNIT_ASSERT( INVALID_CONCAT( OString( "a" ) + OUString::number( 10 )));
CPPUNIT_ASSERT( INVALID_CONCAT( OString::number( 0 ) + OUString::number( 10 )));
#if 0
// Should fail to compile, to avoid use of OStringConcat lvalues that

View File

@ -71,6 +71,17 @@ void test::oustring::StringConcat::checkConcat()
const char d1[] = "xyz";
CPPUNIT_ASSERT_EQUAL( OUString( "fooxyz" ), OUString( OUString( "foo" ) + d1 ));
CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, const char[ 4 ] > )), typeid( OUString( "foo" ) + d1 ));
CPPUNIT_ASSERT_EQUAL( OUString( "num10" ), OUString( OUString( "num" ) + OUString::number( 10 )));
CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, OUStringNumber< int > > )), typeid( OUString( "num" ) + OUString::number( 10 )));
CPPUNIT_ASSERT_EQUAL( OUString( "num10" ), OUString( OUString( "num" ) + OUString::number( 10L )));
CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, OUStringNumber< long long > > )), typeid( OUString( "num" ) + OUString::number( 10L )));
CPPUNIT_ASSERT_EQUAL( OUString( "num10" ), OUString( OUString( "num" ) + OUString::number( 10ULL )));
CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, OUStringNumber< unsigned long long > > )), typeid( OUString( "num" ) + OUString::number( 10ULL )));
CPPUNIT_ASSERT_EQUAL( OUString( "num10.5" ), OUString( OUString( "num" ) + OUString::number( 10.5f )));
CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, OUStringNumber< float > > )), typeid( OUString( "num" ) + OUString::number( 10.5f )));
CPPUNIT_ASSERT_EQUAL( OUString( "num10.5" ), OUString( OUString( "num" ) + OUString::number( 10.5 )));
CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, OUStringNumber< double > > )), typeid( OUString( "num" ) + OUString::number( 10.5 )));
}
void test::oustring::StringConcat::checkConcatAsciiL()
@ -159,6 +170,8 @@ void test::oustring::StringConcat::checkInvalid()
rtl_uString* rus = nullptr;
CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "b" ) + rs ));
CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "b" ) + rus ));
CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "a" ) + OString::number( 10 )));
CPPUNIT_ASSERT( INVALID_CONCAT( OUString::number( 0 ) + OString::number( 10 )));
#if 0
// Should fail to compile, to avoid use of OUStringConcat lvalues that

View File

@ -58,30 +58,30 @@ void test::strings::valueX::testOUBoolean() {
template< typename T >
static void testInt() {
CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T::number( 30039062 ));
CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( 30039062 )));
// test the overloading resolution
CPPUNIT_ASSERT_EQUAL( T( "30" ), T::number( static_cast< signed char >( 30 )));
CPPUNIT_ASSERT_EQUAL( T( "30" ), T::number( static_cast< unsigned char >( 30 )));
CPPUNIT_ASSERT_EQUAL( T( "30039" ), T::number( static_cast< short >( 30039 )));
CPPUNIT_ASSERT_EQUAL( T( "30039" ), T::number( static_cast< unsigned short >( 30039 )));
CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T::number( static_cast< int >( 30039062 )));
CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T::number( static_cast< unsigned int >( 30039062 )));
CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T::number( static_cast< long >( 30039062 )));
CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T::number( static_cast< unsigned long >( 30039062 )));
CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T::number( static_cast< long long >( 30039062 )));
CPPUNIT_ASSERT_EQUAL( T( "30" ), T( T::number( static_cast< signed char >( 30 ))));
CPPUNIT_ASSERT_EQUAL( T( "30" ), T( T::number( static_cast< unsigned char >( 30 ))));
CPPUNIT_ASSERT_EQUAL( T( "30039" ), T( T::number( static_cast< short >( 30039 ))));
CPPUNIT_ASSERT_EQUAL( T( "30039" ), T( T::number( static_cast< unsigned short >( 30039 ))));
CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< int >( 30039062 ))));
CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< unsigned int >( 30039062 ))));
CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< long >( 30039062 ))));
CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< unsigned long >( 30039062 ))));
CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< long long >( 30039062 ))));
// The highest bit set in unsigned long long may not actually work.
CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T::number( static_cast< unsigned long long >( 30039062 )));
CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< unsigned long long >( 30039062 ))));
CPPUNIT_ASSERT_EQUAL( T( "30" ), T::number( static_cast< sal_Int8 >( 30 )));
CPPUNIT_ASSERT_EQUAL( T( "30" ), T::number( static_cast< sal_uInt8 >( 30 )));
CPPUNIT_ASSERT_EQUAL( T( "30039" ), T::number( static_cast< sal_Int16 >( 30039 )));
CPPUNIT_ASSERT_EQUAL( T( "30039" ), T::number( static_cast< sal_uInt16 >( 30039 )));
CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T::number( static_cast< sal_Int32 >( 30039062 )));
CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T::number( static_cast< sal_uInt32 >( 30039062 )));
CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T::number( static_cast< sal_Int64 >( 30039062 )));
CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T::number( static_cast< sal_uInt64 >( 30039062 )));
CPPUNIT_ASSERT_EQUAL( T( "30" ), T( T::number( static_cast< sal_Int8 >( 30 ))));
CPPUNIT_ASSERT_EQUAL( T( "30" ), T( T::number( static_cast< sal_uInt8 >( 30 ))));
CPPUNIT_ASSERT_EQUAL( T( "30039" ), T( T::number( static_cast< sal_Int16 >( 30039 ))));
CPPUNIT_ASSERT_EQUAL( T( "30039" ), T( T::number( static_cast< sal_uInt16 >( 30039 ))));
CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< sal_Int32 >( 30039062 ))));
CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< sal_uInt32 >( 30039062 ))));
CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< sal_Int64 >( 30039062 ))));
CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< sal_uInt64 >( 30039062 ))));
// The implementation internally uses sal_Int64 etc. types, so check ranges.
assert( sizeof( int ) <= sizeof( sal_Int32 ));
@ -100,8 +100,8 @@ void test::strings::valueX::testOInt() {
template< typename T >
static void testFloat() {
CPPUNIT_ASSERT_EQUAL( T( "39062.2" ), T::number( 39062.2f ));
CPPUNIT_ASSERT_EQUAL( T( "30039062.2" ), T::number( 30039062.2 ));
CPPUNIT_ASSERT_EQUAL( T( "39062.2" ), T( T::number( 39062.2f )));
CPPUNIT_ASSERT_EQUAL( T( "30039062.2" ), T( T::number( 30039062.2 )));
// long double not supported
}

View File

@ -437,7 +437,7 @@ void ScInterpreter::ScEncodeURL()
else
{
aUrlBuf.append( '%' );
OString convertedChar = OString::number( static_cast<unsigned char>( c ), 16 ).toAsciiUpperCase();
OString convertedChar = OString( OString::number( static_cast<unsigned char>( c ), 16 )).toAsciiUpperCase();
// RFC 3986 indicates:
// "A percent-encoded octet is encoded as a character triplet,
// consisting of the percent character "%" followed by the two hexadecimal digits

View File

@ -95,8 +95,8 @@ void XclExpSetup::SaveXml( XclExpXmlStream& rStrm )
}
else
{
pAttrList->add( XML_paperWidth, OString::number( mrData.mnPaperWidth ).concat("mm").getStr() );
pAttrList->add( XML_paperHeight, OString::number( mrData.mnPaperHeight ).concat("mm").getStr() );
pAttrList->add( XML_paperWidth, OString(OString::number( mrData.mnPaperWidth ) + "mm").getStr() );
pAttrList->add( XML_paperHeight, OString(OString::number( mrData.mnPaperHeight ) + "mm").getStr() );
// pAttrList->add( XML_paperUnits, "mm" );
}
pAttrList->add( XML_scale, OString::number( mrData.mnScaling ).getStr() );

View File

@ -287,12 +287,12 @@ public:
sax_fastparser::FSHelperPtr GetStreamForPath( const OUString& rPath );
template <typename Str, typename... Args>
void WriteAttributes(sal_Int32 nAttribute, const Str& value, Args... rest)
void WriteAttributes(sal_Int32 nAttribute, Str&& value, Args&&... rest)
{
WriteAttribute(nAttribute, value);
WriteAttribute(nAttribute, std::forward<Str>(value));
// coverity[stray_semicolon : FALSE] - coverity parse error
if constexpr(sizeof...(rest) > 0)
WriteAttributes(rest...);
WriteAttributes(std::forward<Args>(rest)...);
}
sax_fastparser::FSHelperPtr CreateOutputStream (

View File

@ -709,7 +709,7 @@ OUString ConvertFromDec( double fNum, double fMin, double fMax, sal_uInt16 nBase
if( bNeg )
nNum = sal_Int64( pow( double( nBase ), double( nMaxPlaces ) ) ) + nNum;
OUString aRet( OUString::number( nNum, nBase ).toAsciiUpperCase() );
OUString aRet( OUString( OUString::number( nNum, nBase )).toAsciiUpperCase() );
if( bUsePlaces )

View File

@ -2405,7 +2405,7 @@ OUString SdXImpressDocument::getPostIts()
aAnnotation.put("dateTime", utl::toISO8601(xAnnotation->getDateTime()));
uno::Reference<text::XText> xText(xAnnotation->getTextRange());
aAnnotation.put("text", xText->getString());
aAnnotation.put("parthash", OUString::number(pPage->GetHashCode()));
aAnnotation.put("parthash", OUString(OUString::number(pPage->GetHashCode())));
aAnnotations.push_back(std::make_pair("", aAnnotation));
}

View File

@ -430,7 +430,7 @@ void SvFileObject::SendStateChg_Impl( sfx2::LinkManager::LinkState nState )
if( !bStateChangeCalled && HasDataLinks() )
{
DataChanged( SotExchange::GetFormatName(
sfx2::LinkManager::RegisterStatusInfoId()), css::uno::Any(OUString::number( nState )) );
sfx2::LinkManager::RegisterStatusInfoId()), css::uno::makeAny(OUString::number( nState )) );
bStateChangeCalled = true;
}
}

View File

@ -1584,7 +1584,7 @@ IMPL_LINK_NOARG(SmSymDefineDialog, CharHighlightHdl, SvxShowCharSet*, void)
UpdateButtons();
// display Unicode position as symbol name while iterating over characters
const OUString aHex(OUString::number(cChar, 16 ).toAsciiUpperCase());
const OUString aHex(OUString(OUString::number(cChar, 16 )).toAsciiUpperCase());
const OUString aPattern( (aHex.getLength() > 4) ? OUString("Ux000000") : OUString("Ux0000") );
OUString aUnicodePos( aPattern.copy( 0, aPattern.getLength() - aHex.getLength() ) );
aUnicodePos += aHex;

View File

@ -4210,7 +4210,7 @@ OUString NfCurrencyEntry::BuildSymbolString(bool bBank,
if ( !bWithoutExtension && eLanguage != LANGUAGE_DONTKNOW && eLanguage != LANGUAGE_SYSTEM )
{
sal_Int32 nLang = static_cast<sal_uInt16>(eLanguage);
aBuf.append('-').append( OUString::number(nLang, 16).toAsciiUpperCase());
aBuf.append('-').append( OUString( OUString::number(nLang, 16)).toAsciiUpperCase());
}
}
aBuf.append(']');

View File

@ -1165,7 +1165,7 @@ SvNumberformat::SvNumberformat(OUString& rString,
((eLanguage = MsLangId::getRealLanguage( eLan)) == LANGUAGE_THAI) &&
NumFor[nIndex].GetNatNum().GetLang() == LANGUAGE_DONTKNOW)
{
sStr = "[$-" + OUString::number( sal_uInt16(eLanguage), 16 ).toAsciiUpperCase() + "]" + sStr;
sStr = "[$-" + OUString(OUString::number( sal_uInt16(eLanguage), 16 )).toAsciiUpperCase() + "]" + sStr;
NumFor[nIndex].SetNatNumLang( eLanguage);
}
sBuff.remove(nPosOld, nPos - nPosOld);
@ -5085,7 +5085,7 @@ static void lcl_insertLCID( OUStringBuffer& rFormatStr, sal_uInt32 nLCID, sal_In
// No format code, no locale.
return;
OUStringBuffer aLCIDString = OUString::number( nLCID , 16 ).toAsciiUpperCase();
OUStringBuffer aLCIDString = OUString(OUString::number( nLCID , 16 )).toAsciiUpperCase();
// Search for only last DBNum which is the last element before insertion position
if ( bDBNumInserted && nPosInsertLCID >= 8
&& aLCIDString.getLength() > 4

View File

@ -53,7 +53,8 @@ void XmlWalkerTest::testReadXML()
{
nNumberOfChildNodes++;
CPPUNIT_ASSERT_EQUAL(OString::number(nNumberOfChildNodes), aWalker.attribute("number"));
CPPUNIT_ASSERT_EQUAL(OString(OString::number(nNumberOfChildNodes)),
aWalker.attribute("number"));
if (nNumberOfChildNodes == 1) // only the first node has the attribute
CPPUNIT_ASSERT_EQUAL(OString("123"), aWalker.attribute("attribute"));

View File

@ -245,7 +245,7 @@ ALNUM {DIGIT}|{ALPHA}
yyextra->errorMessage = c >= ' ' && c <= '~'
? OUString("invalid character \"" + OUStringLiteral1(c) + "\"")
: OUString(
"invalid byte x" + OUString::number(c, 16).toAsciiUpperCase());
"invalid byte x" + OUString(OUString::number(c, 16)).toAsciiUpperCase());
return TOK_ERROR;
}

View File

@ -814,12 +814,12 @@ namespace
OUStringBuffer aBuf;
sal_Int32 nTextLen;
nTextLen = OUString::number(rFormatter.GetMin()).getLength();
nTextLen = OUString(OUString::number(rFormatter.GetMin())).getLength();
string::padToLength(aBuf, nTextLen, '9');
Size aMinTextSize = rSpinField.CalcMinimumSizeForText(
rFormatter.CreateFieldText(aBuf.makeStringAndClear().toInt64()));
nTextLen = OUString::number(rFormatter.GetMax()).getLength();
nTextLen = OUString(OUString::number(rFormatter.GetMax())).getLength();
string::padToLength(aBuf, nTextLen, '9');
Size aMaxTextSize = rSpinField.CalcMinimumSizeForText(
rFormatter.CreateFieldText(aBuf.makeStringAndClear().toInt64()));

View File

@ -170,7 +170,7 @@ STDMETHODIMP CAccTextBase::get_attributes(long offset, long * startOffset, long
unsigned long nColor;
pValue.Value >>= nColor;
strAttrs.append('#');
auto const hex = OUString::number(nColor, 16).toAsciiUpperCase();
auto const hex = OUString(OUString::number(nColor, 16)).toAsciiUpperCase();
for (sal_Int32 j = hex.getLength(); j < 8; ++j) {
strAttrs.append('0');
}

View File

@ -1474,7 +1474,7 @@ SvXMLNumFormatContext::SvXMLNumFormatContext( SvXMLImport& rImport,
{
aFormatCode.append( "][$-" );
// language code in upper hex:
aFormatCode.append(OUString::number(static_cast<sal_uInt16>(eLang), 16).toAsciiUpperCase());
aFormatCode.append(OUString(OUString::number(static_cast<sal_uInt16>(eLang), 16)).toAsciiUpperCase());
}
aFormatCode.append( ']' );
}
@ -2029,7 +2029,7 @@ void SvXMLNumFormatContext::AddCurrency( const OUString& rContent, LanguageType
if ( nLang != LANGUAGE_SYSTEM )
{
// '-' sign and language code in hex:
aFormatCode.append("-").append(OUString::number(sal_uInt16(nLang), 16).toAsciiUpperCase());
aFormatCode.append("-").append(OUString(OUString::number(sal_uInt16(nLang), 16)).toAsciiUpperCase());
}
aFormatCode.append( ']' ); // end of "new" currency symbol