Kaydet (Commit) b88a26f0 authored tarafından Luboš Luňák's avatar Luboš Luňák

rtl_(u)String_ensureCapacity

Ensure there will be enough extra space in a string, to be used for string
appending. A bit like rtl_(u)String_newConcat(), but without the function
actually appending anything. Unlike the stringbuffer variant this does
not allocate any extra.

Change-Id: Ic6f84bf014a713f9912c81d8f1405c593978822d
üst 5c61b8e8
......@@ -1313,6 +1313,24 @@ SAL_DLLPUBLIC sal_Bool SAL_CALL rtl_convertUStringToString(
sal_uInt32 nFlags)
SAL_THROW_EXTERN_C();
/** Ensure a string has enough space for a given number of characters.
If the given string is large enough and has refcount of 1, it is not altered in any way.
Otherwise it is replaced by a copy that has enough space for the given number of characters,
data from the source string is copied to the beginning of it, the content of the remaining
capacity undefined, the string has refcount of 1, and refcount of the original string is decreased.
@param str
pointer to the string. The pointed-to data must be a valid string.
@param size
the number of characters
@since LibreOffice 4.1
@internal
*/
SAL_DLLPUBLIC void SAL_CALL rtl_string_ensureCapacity( rtl_String ** str, sal_Int32 size ) SAL_THROW_EXTERN_C();
#ifdef __cplusplus
}
#endif
......
......@@ -1926,6 +1926,24 @@ SAL_DLLPUBLIC sal_Bool SAL_CALL rtl_convertStringToUString(
rtl_uString ** target, char const * source, sal_Int32 length,
rtl_TextEncoding encoding, sal_uInt32 flags) SAL_THROW_EXTERN_C();
/** Ensure a string has enough space for a given number of characters.
If the given string is large enough and has refcount of 1, it is not altered in any way.
Otherwise it is replaced by a copy that has enough space for the given number of characters,
data from the source string is copied to the beginning of it, the content of the remaining
capacity undefined, the string has refcount of 1, and refcount of the original string is decreased.
@param str
pointer to the string. The pointed-to data must be a valid string.
@param size
the number of characters
@since LibreOffice 4.1
@internal
*/
SAL_DLLPUBLIC void SAL_CALL rtl_uString_ensureCapacity( rtl_uString ** str, sal_Int32 size ) SAL_THROW_EXTERN_C();
#ifdef __cplusplus
}
#endif
......
......@@ -33,9 +33,11 @@ class StringConcat : public CppUnit::TestFixture
{
private:
void check();
void checkEnsureCapacity();
CPPUNIT_TEST_SUITE(StringConcat);
CPPUNIT_TEST(check);
CPPUNIT_TEST(checkEnsureCapacity);
CPPUNIT_TEST_SUITE_END();
};
......@@ -73,6 +75,44 @@ void test::ostring::StringConcat::check()
}
#undef typeid
void test::ostring::StringConcat::checkEnsureCapacity()
{
rtl_String* str = NULL;
rtl_string_newFromLiteral( &str, "test", strlen( "test" ), 0 );
CPPUNIT_ASSERT_EQUAL( sal_Int32( 4 ), str->length );
CPPUNIT_ASSERT_EQUAL( 1, str->refCount );
rtl_String* oldStr = str;
rtl_string_ensureCapacity( &str, 4 ); // should be no-op
CPPUNIT_ASSERT_EQUAL( sal_Int32( 4 ), str->length );
CPPUNIT_ASSERT_EQUAL( 1, str->refCount );
CPPUNIT_ASSERT( oldStr == str );
rtl_string_acquire( oldStr );
CPPUNIT_ASSERT_EQUAL( 2, str->refCount );
rtl_string_ensureCapacity( &str, 4 );
CPPUNIT_ASSERT_EQUAL( sal_Int32( 4 ), str->length );
CPPUNIT_ASSERT_EQUAL( 1, str->refCount );
// a copy was forced because of refcount
CPPUNIT_ASSERT( oldStr != str );
CPPUNIT_ASSERT( strcmp( oldStr->buffer, str->buffer ) == 0 );
CPPUNIT_ASSERT_EQUAL( 1, oldStr->refCount );
rtl_string_release( str );
str = oldStr;
rtl_string_acquire( oldStr );
rtl_string_ensureCapacity( &str, 1024 );
CPPUNIT_ASSERT_EQUAL( sal_Int32( 4 ), str->length ); // size is still 4
CPPUNIT_ASSERT_EQUAL( 1, str->refCount );
CPPUNIT_ASSERT( oldStr != str );
CPPUNIT_ASSERT( strcmp( oldStr->buffer, str->buffer ) == 0 );
CPPUNIT_ASSERT_EQUAL( 1, oldStr->refCount );
strcpy( str->buffer, "01234567890123456789" ); // but there should be extra capacity
str->length += 20;
rtl_string_release( str );
rtl_string_release( oldStr );
}
}} // namespace
CPPUNIT_TEST_SUITE_REGISTRATION(test::ostring::StringConcat);
......
......@@ -33,9 +33,11 @@ class StringConcat : public CppUnit::TestFixture
{
private:
void check();
void checkEnsureCapacity();
CPPUNIT_TEST_SUITE(StringConcat);
CPPUNIT_TEST(check);
CPPUNIT_TEST(checkEnsureCapacity);
CPPUNIT_TEST_SUITE_END();
};
......@@ -61,6 +63,49 @@ void test::oustring::StringConcat::check()
TYPES_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, const char[ 4 ] > )), typeid( OUString( "foo" ) + d1 ));
}
void test::oustring::StringConcat::checkEnsureCapacity()
{
rtl_uString* str = NULL;
rtl_uString_newFromLiteral( &str, "test", strlen( "test" ), 0 );
CPPUNIT_ASSERT_EQUAL( sal_Int32( 4 ), str->length );
CPPUNIT_ASSERT_EQUAL( 1, str->refCount );
rtl_uString* oldStr = str;
rtl_uString_ensureCapacity( &str, 4 ); // should be no-op
CPPUNIT_ASSERT_EQUAL( sal_Int32( 4 ), str->length );
CPPUNIT_ASSERT_EQUAL( 1, str->refCount );
CPPUNIT_ASSERT( oldStr == str );
rtl_uString_acquire( oldStr );
CPPUNIT_ASSERT_EQUAL( 2, str->refCount );
rtl_uString_ensureCapacity( &str, 4 );
CPPUNIT_ASSERT_EQUAL( sal_Int32( 4 ), str->length );
CPPUNIT_ASSERT_EQUAL( 1, str->refCount );
// a copy was forced because of refcount
CPPUNIT_ASSERT( oldStr != str );
CPPUNIT_ASSERT( rtl_ustr_compare( oldStr->buffer, str->buffer ) == 0 );
CPPUNIT_ASSERT_EQUAL( 1, oldStr->refCount );
rtl_uString_release( str );
str = oldStr;
rtl_uString_acquire( oldStr );
rtl_uString_ensureCapacity( &str, 1024 );
CPPUNIT_ASSERT_EQUAL( sal_Int32( 4 ), str->length ); // size is still 4
CPPUNIT_ASSERT_EQUAL( 1, str->refCount );
CPPUNIT_ASSERT( oldStr != str );
CPPUNIT_ASSERT( rtl_ustr_compare( oldStr->buffer, str->buffer ) == 0 );
CPPUNIT_ASSERT_EQUAL( 1, oldStr->refCount );
// but there should be extra capacity
for( int i = 0;
i < 20;
++i )
str->buffer[ str->length + i ] = '0';
str->length += 20;
rtl_uString_release( str );
rtl_uString_release( oldStr );
}
}} // namespace
CPPUNIT_TEST_SUITE_REGISTRATION(test::oustring::StringConcat);
......
......@@ -1318,6 +1318,29 @@ void SAL_CALL IMPL_RTL_STRINGNAME( newConcat )( IMPL_RTL_STRINGDATA** ppThis,
/* ----------------------------------------------------------------------- */
void SAL_CALL IMPL_RTL_STRINGNAME( ensureCapacity )( IMPL_RTL_STRINGDATA** ppThis,
sal_Int32 size )
SAL_THROW_EXTERN_C()
{
IMPL_RTL_STRINGDATA* const pOrg = *ppThis;
if ( pOrg->refCount == 1 && pOrg->length >= size )
return;
assert( pOrg->length <= size ); // do not truncate
IMPL_RTL_STRINGDATA* pTempStr = IMPL_RTL_STRINGNAME( ImplAlloc )( size );
rtl_str_ImplCopy( pTempStr->buffer, pOrg->buffer, pOrg->length );
// right now the length is still the same as of the original
pTempStr->length = pOrg->length;
pTempStr->buffer[ pOrg->length ] = '\0';
*ppThis = pTempStr;
RTL_LOG_STRING_NEW( *ppThis );
/* must be done last, if pStr == *ppThis */
if ( pOrg )
IMPL_RTL_STRINGNAME( release )( pOrg );
}
/* ----------------------------------------------------------------------- */
void SAL_CALL IMPL_RTL_STRINGNAME( newReplaceStrAt )( IMPL_RTL_STRINGDATA** ppThis,
IMPL_RTL_STRINGDATA* pStr,
sal_Int32 nIndex,
......
......@@ -652,6 +652,12 @@ LIBO_UDK_4.0 { # symbols available in >= LibO 4.0
rtl_uString_newReplaceAllFromIndex;
} LIBO_UDK_3.6;
LIBO_UDK_4.1 { # symbols available in >= LibO 4.1
global:
rtl_string_ensureCapacity;
rtl_uString_ensureCapacity;
} LIBO_UDK_4.0;
PRIVATE_1.0 {
global:
osl_detail_ObjectRegistry_storeAddresses;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment