diff options
author | Mike Kaganski <mike.kaganski@collabora.com> | 2022-02-28 10:52:49 +0300 |
---|---|---|
committer | Mike Kaganski <mike.kaganski@collabora.com> | 2022-02-28 11:49:15 +0100 |
commit | 22de5757a2c7c6cd4544a4699e5d4c69969f5961 (patch) | |
tree | 6c799790e22cc9b3b3d2db97ff127737c0bcf2be /sal | |
parent | 9e8d8870890b0a60ef9acc4c43c67688b58a42a3 (diff) |
Deduplicate string buffer code
Change-Id: Ia23974ad3a827c84bb1a5d633a953625aea2576a
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130663
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Diffstat (limited to 'sal')
-rw-r--r-- | sal/rtl/strbuf.cxx | 121 | ||||
-rw-r--r-- | sal/rtl/string.cxx | 12 | ||||
-rw-r--r-- | sal/rtl/strtmpl.hxx | 153 | ||||
-rw-r--r-- | sal/rtl/ustrbuf.cxx | 165 | ||||
-rw-r--r-- | sal/rtl/ustring.cxx | 14 |
5 files changed, 162 insertions, 303 deletions
diff --git a/sal/rtl/strbuf.cxx b/sal/rtl/strbuf.cxx index b9f4cd688b05..7ba25ff4a31a 100644 --- a/sal/rtl/strbuf.cxx +++ b/sal/rtl/strbuf.cxx @@ -23,6 +23,12 @@ #include <rtl/strbuf.hxx> #include "strimp.hxx" +#if USE_SDT_PROBES +#define RTL_LOG_STRING_BITS 8 +#endif + +#include "strtmpl.hxx" + /************************************************************************* * rtl_stringbuffer_newFromStr_WithLength */ @@ -30,21 +36,7 @@ void SAL_CALL rtl_stringbuffer_newFromStr_WithLength( rtl_String ** newStr, const char * value, sal_Int32 count ) { - assert(newStr); - assert(count >= 0); - if (!value) - { - rtl_string_new_WithLength( newStr, 16 ); - return; - } - - // use raw alloc to avoid overwriting the buffer twice - if ( *newStr) - rtl_string_release( *newStr ); - *newStr = rtl_string_ImplAlloc( count + 16 ); - (*newStr)->length = count; - memcpy( (*newStr)->buffer, value, count ); - memset( (*newStr)->buffer + count, 0, 16 ); + rtl::str::stringbuffer_newFromStr_WithLength(newStr, value, count); } /************************************************************************* @@ -54,20 +46,7 @@ sal_Int32 SAL_CALL rtl_stringbuffer_newFromStringBuffer( rtl_String ** newStr, sal_Int32 capacity, rtl_String * oldStr ) { - assert(newStr); - assert(oldStr); - assert(capacity >= 0); - sal_Int32 newCapacity = capacity; - - if (newCapacity < oldStr->length) - newCapacity = oldStr->length; - - rtl_string_new_WithLength( newStr, newCapacity ); - if (oldStr->length > 0) { - (*newStr)->length = oldStr->length; - memcpy( (*newStr)->buffer, oldStr->buffer, oldStr->length ); - } - return newCapacity; + return rtl::str::stringbuffer_newFromStringBuffer(newStr, capacity, oldStr); } /************************************************************************* @@ -76,28 +55,7 @@ sal_Int32 SAL_CALL rtl_stringbuffer_newFromStringBuffer( rtl_String ** newStr, void SAL_CALL rtl_stringbuffer_ensureCapacity (rtl_String ** This, sal_Int32* capacity, sal_Int32 minimumCapacity) { - assert(This); -// assert(capacity && *capacity >= 0); -// assert(minimumCapacity >= 0); - if (minimumCapacity <= *capacity) - return; - - rtl_String * pTmp = *This; - rtl_String * pNew = nullptr; - auto nLength = (*This)->length; - *capacity = (nLength + 1) * 2; - if (minimumCapacity > *capacity) - /* still lower, set to the minimum capacity */ - *capacity = minimumCapacity; - - // use raw alloc to avoid overwriting the buffer twice - pNew = rtl_string_ImplAlloc( *capacity ); - pNew->length = nLength; - *This = pNew; - - memcpy( (*This)->buffer, pTmp->buffer, nLength ); - memset( (*This)->buffer + nLength, 0, *capacity - nLength ); - rtl_string_release( pTmp ); + rtl::str::stringbuffer_ensureCapacity(This, capacity, minimumCapacity); } /************************************************************************* @@ -109,41 +67,7 @@ void SAL_CALL rtl_stringbuffer_insert( rtl_String ** This, const char * str, sal_Int32 len ) { - assert(This); - assert(capacity && *capacity >= 0); - assert(offset >= 0 && offset <= (**This).length); - assert(len >= 0); - sal_Int32 nOldLen; - char * pBuf; - sal_Int32 n; - if( len == 0 ) - return; - - if (*capacity < (*This)->length + len) - rtl_stringbuffer_ensureCapacity( This, capacity, (*This)->length + len ); - - nOldLen = (*This)->length; - pBuf = (*This)->buffer; - - /* copy the tail */ - n = (nOldLen - offset); - if( n == 1 ) - /* optimized for 1 character */ - pBuf[offset + len] = pBuf[offset]; - else if( n > 1 ) - memmove( pBuf + offset + len, pBuf + offset, n * sizeof(char) ); - - /* insert the new characters */ - if( str != nullptr ) - { - if( len == 1 ) - /* optimized for 1 character */ - pBuf[offset] = *str; - else - memcpy( pBuf + offset, str, len * sizeof(char) ); - } - (*This)->length = nOldLen + len; - pBuf[ nOldLen + len ] = 0; + rtl::str::stringbuffer_insert(This, capacity, offset, str, len); } /************************************************************************* @@ -153,30 +77,7 @@ void SAL_CALL rtl_stringbuffer_remove( rtl_String ** This, sal_Int32 start, sal_Int32 len ) { - assert(This); - assert(start >= 0 && start <= (**This).length); - assert(len >= 0); - sal_Int32 nTailLen; - char * pBuf; - - if (len > (*This)->length - start) - len = (*This)->length - start; - - //remove nothing - if (!len) - return; - - pBuf = (*This)->buffer; - nTailLen = (*This)->length - ( start + len ); - - if (nTailLen) - { - /* move the tail */ - memmove(pBuf + start, pBuf + start + len, nTailLen * sizeof(char)); - } - - (*This)->length-=len; - pBuf[ (*This)->length ] = 0; + rtl::str::stringbuffer_remove(This, start, len); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/rtl/string.cxx b/sal/rtl/string.cxx index 7be5a6e17595..87c65f6069ce 100644 --- a/sal/rtl/string.cxx +++ b/sal/rtl/string.cxx @@ -47,18 +47,6 @@ static_assert(sizeof (rtl_String) == 12); #include "strtmpl.hxx" -/* static data to be referenced by all empty strings - * the refCount is predefined to 1 and must never become 0 ! - */ -template<> -rtl_String rtl::str::EmptyStringImpl<rtl_String>::data = -{ - SAL_STRING_STATIC_FLAG|1, - /* sal_Int32 refCount; */ - 0, /* sal_Int32 length; */ - { 0 } /* char buffer[1]; */ -}; - /* ======================================================================= */ sal_Int32 SAL_CALL rtl_str_valueOfFloat(char * pStr, float f) diff --git a/sal/rtl/strtmpl.hxx b/sal/rtl/strtmpl.hxx index f294c9c8b910..9d14fbf77f23 100644 --- a/sal/rtl/strtmpl.hxx +++ b/sal/rtl/strtmpl.hxx @@ -17,39 +17,43 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -/* ======================================================================= */ -/* Internal C-String help functions which could be used without the */ -/* String-Class */ -/* ======================================================================= */ - #pragma once #include <algorithm> #include <cassert> #include <cstdlib> +#include <cstring> +#include <cwchar> #include <limits> #include <string_view> #include <type_traits> -#include <cstring> -#include <wchar.h> +#include "strimp.hxx" + +#include <osl/diagnose.h> #include <sal/log.hxx> #include <rtl/character.hxx> +#include <rtl/math.h> #include <rtl/strbuf.h> #include <rtl/ustrbuf.h> #include <rtl/ustring.hxx> +void internRelease(rtl_uString*); + namespace rtl::str { template <typename C> auto IMPL_RTL_USTRCODE(C c) { return std::make_unsigned_t<C>(c); } -template <typename IMPL_RTL_STRCODE> -void Copy( IMPL_RTL_STRCODE* _pDest, - const IMPL_RTL_STRCODE* _pSrc, - sal_Int32 _nCount ) +template <typename C> void Copy(C* _pDest, const C* _pSrc, sal_Int32 _nCount) { // take advantage of builtin optimisations - memcpy( _pDest, _pSrc, _nCount * sizeof(IMPL_RTL_STRCODE)); + std::copy(_pSrc, _pSrc + _nCount, _pDest); +} + +template <typename C> void CopyBackward(C* _pDest, const C* _pSrc, sal_Int32 _nCount) +{ + // take advantage of builtin optimisations + std::copy_backward(_pSrc, _pSrc + _nCount, _pDest + _nCount); } inline void Copy(sal_Unicode* _pDest, const char* _pSrc, sal_Int32 _nCount) @@ -614,7 +618,7 @@ sal_Int32 trim_WithLength( IMPL_RTL_STRCODE* pStr, sal_Int32 nLen ) { nLen = static_cast<sal_Int32>(view.size()); if (view.data() != pStr) - memmove(pStr, view.data(), nLen * sizeof(IMPL_RTL_STRCODE)); + Copy(pStr, view.data(), nLen); *(pStr+nLen) = 0; } @@ -974,9 +978,26 @@ template <typename IMPL_RTL_STRINGDATA> void release( IMPL_RTL_STRINGDATA* pThis /* ----------------------------------------------------------------------- */ +/* static data to be referenced by all empty strings + * the refCount is predefined to 1 and must never become 0 ! + */ template <typename IMPL_RTL_STRINGDATA> struct EmptyStringImpl { - static IMPL_RTL_STRINGDATA data; // defined in respective units + static IMPL_RTL_STRINGDATA data; +}; + +template <> +inline rtl_uString EmptyStringImpl<rtl_uString>::data = { + sal_Int32(SAL_STRING_INTERN_FLAG | SAL_STRING_STATIC_FLAG | 1), /* sal_Int32 refCount; */ + 0, /* sal_Int32 length; */ + { 0 } /* sal_Unicode buffer[1]; */ +}; + +template <> +inline rtl_String EmptyStringImpl<rtl_String>::data = { + SAL_STRING_STATIC_FLAG | 1, /* sal_Int32 refCount; */ + 0, /* sal_Int32 length; */ + { 0 } /* char buffer[1]; */ }; template <typename IMPL_RTL_STRINGDATA> void new_( IMPL_RTL_STRINGDATA** ppThis ) @@ -1601,6 +1622,110 @@ sal_Int32 SAL_CALL valueOfFP(STRCODE<IMPL_RTL_STRINGDATA>* pStr, T f, return nLen; } +/* ======================================================================= */ +/* String buffer help functions */ +/* ======================================================================= */ + +template <class IMPL_RTL_STRINGDATA> +void stringbuffer_newFromStr_WithLength(IMPL_RTL_STRINGDATA** ppThis, + const STRCODE<IMPL_RTL_STRINGDATA>* pStr, sal_Int32 count) +{ + assert(ppThis); + assert(count >= 0); + if (!pStr) + count = 0; // Because old code didn't care about count when !pStr + + newFromStr_WithLength(ppThis, pStr, count, 16); +} + +template <class IMPL_RTL_STRINGDATA> +sal_Int32 stringbuffer_newFromStringBuffer(IMPL_RTL_STRINGDATA** ppThis, sal_Int32 capacity, + IMPL_RTL_STRINGDATA* pStr) +{ + assert(capacity >= 0); + assert(pStr); + + if (capacity < pStr->length) + capacity = pStr->length; + + newFromStr_WithLength(ppThis, pStr->buffer, pStr->length, capacity - pStr->length); + return capacity; +} + +template <class IMPL_RTL_STRINGDATA> +void stringbuffer_ensureCapacity(IMPL_RTL_STRINGDATA** ppThis, sal_Int32* capacity, + sal_Int32 minimumCapacity) +{ + assert(ppThis); + assert(capacity && *capacity >= 0); + // assert(minimumCapacity >= 0); // It was commented out in rtl_stringbuffer_ensureCapacity + if (minimumCapacity <= *capacity) + return; + + const auto nLength = (*ppThis)->length; + *capacity = (nLength + 1) * 2; + if (minimumCapacity > *capacity) + *capacity = minimumCapacity; + + newFromStr_WithLength(ppThis, (*ppThis)->buffer, nLength, *capacity - nLength); +} + +template <class IMPL_RTL_STRINGDATA, typename C> +void stringbuffer_insert(IMPL_RTL_STRINGDATA** ppThis, sal_Int32* capacity, sal_Int32 offset, + const C* pStr, sal_Int32 len) +{ + assert(ppThis); + assert(capacity && *capacity >= 0); + assert(offset >= 0 && offset <= (*ppThis)->length); + assert(len >= 0); + if (len == 0) + return; + + stringbuffer_ensureCapacity(ppThis, capacity, (*ppThis)->length + len); + + sal_Int32 nOldLen = (*ppThis)->length; + auto* pBuf = (*ppThis)->buffer; + + /* copy the tail */ + const sal_Int32 n = nOldLen - offset; + if (n > 0) + CopyBackward(pBuf + offset + len, pBuf + offset, n); + + /* insert the new characters */ + if (pStr != nullptr) + Copy(pBuf + offset, pStr, len); + + (*ppThis)->length = nOldLen + len; + pBuf[nOldLen + len] = 0; +} + +template <class IMPL_RTL_STRINGDATA> +void stringbuffer_remove(IMPL_RTL_STRINGDATA** ppThis, sal_Int32 start, sal_Int32 len) +{ + assert(ppThis); + assert(start >= 0 && start <= (*ppThis)->length); + assert(len >= 0); + + if (len > (*ppThis)->length - start) + len = (*ppThis)->length - start; + + //remove nothing + if (!len) + return; + + auto* pBuf = (*ppThis)->buffer; + const sal_Int32 nTailLen = (*ppThis)->length - (start + len); + + if (nTailLen) + { + /* move the tail */ + Copy(pBuf + start, pBuf + start + len, nTailLen); + } + + (*ppThis)->length -= len; + pBuf[(*ppThis)->length] = 0; +} + } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/rtl/ustrbuf.cxx b/sal/rtl/ustrbuf.cxx index 7c5b187edbcb..c91834cfa783 100644 --- a/sal/rtl/ustrbuf.cxx +++ b/sal/rtl/ustrbuf.cxx @@ -29,32 +29,19 @@ #define RTL_LOG_STRING_BITS 16 #endif +#include "strtmpl.hxx" + void SAL_CALL rtl_uStringbuffer_newFromStr_WithLength( rtl_uString ** newStr, const sal_Unicode * value, sal_Int32 count) { - assert(newStr); - assert(count >= 0); - if (!value) - { - rtl_uString_new_WithLength( newStr, 16 ); - return; - } - - // use raw alloc to avoid overwriting the buffer twice - if ( *newStr) - rtl_uString_release( *newStr ); - *newStr = rtl_uString_ImplAlloc( count + 16 ); - (*newStr)->length = count; - memcpy( (*newStr)->buffer, value, count * sizeof(sal_Unicode) ); - memset( (*newStr)->buffer + count, 0, 16 * sizeof(sal_Unicode) ); - RTL_LOG_STRING_NEW( *newStr ); + rtl::str::stringbuffer_newFromStr_WithLength(newStr, value, count); } rtl_uString * SAL_CALL rtl_uStringBuffer_refReturn( rtl_uString * pThis ) { RTL_LOG_STRING_NEW( pThis ); - rtl_uString_acquire( pThis ); + rtl::str::acquire( pThis ); return pThis; } @@ -67,7 +54,7 @@ rtl_uString * SAL_CALL rtl_uStringBuffer_makeStringAndClear( rtl_uString ** ppTh rtl_uString *pStr = *ppThis; *ppThis = nullptr; - rtl_uString_new (ppThis); + rtl::str::new_(ppThis); *nCapacity = 0; RTL_LOG_STRING_NEW( pStr ); @@ -79,51 +66,13 @@ sal_Int32 SAL_CALL rtl_uStringbuffer_newFromStringBuffer( rtl_uString ** newStr, sal_Int32 capacity, rtl_uString * oldStr ) { - assert(newStr); - assert(capacity >= 0); - assert(oldStr); - sal_Int32 newCapacity = capacity; - - if (newCapacity < oldStr->length) - newCapacity = oldStr->length; - - rtl_uString_new_WithLength( newStr, newCapacity ); - - if (oldStr->length > 0) { - (*newStr)->length = oldStr->length; - memcpy( (*newStr)->buffer, oldStr->buffer, oldStr->length * sizeof(sal_Unicode)); - } - RTL_LOG_STRING_NEW( *newStr ); - return newCapacity; + return rtl::str::stringbuffer_newFromStringBuffer(newStr, capacity, oldStr); } void SAL_CALL rtl_uStringbuffer_ensureCapacity (rtl_uString ** This, sal_Int32* capacity, sal_Int32 minimumCapacity) { - assert(This); - assert(capacity && *capacity >= 0); - assert(minimumCapacity >= 0); - if (minimumCapacity <= *capacity) - return; - - rtl_uString * pTmp = *This; - rtl_uString * pNew = nullptr; - auto nLength = (*This)->length; - *capacity = (nLength + 1) * 2; - if (minimumCapacity > *capacity) - /* still lower, set to the minimum capacity */ - *capacity = minimumCapacity; - - // use raw alloc to avoid overwriting the buffer twice - pNew = rtl_uString_ImplAlloc( *capacity ); - pNew->length = nLength; - *This = pNew; - - memcpy( (*This)->buffer, pTmp->buffer, nLength * sizeof(sal_Unicode) ); - memset( (*This)->buffer + nLength, 0, (*capacity - nLength) * sizeof(sal_Unicode) ); - - RTL_LOG_STRING_NEW( pTmp ); // with accurate contents - rtl_uString_release( pTmp ); + rtl::str::stringbuffer_ensureCapacity(This, capacity, minimumCapacity); } void SAL_CALL rtl_uStringbuffer_insert( rtl_uString ** This, @@ -132,41 +81,7 @@ void SAL_CALL rtl_uStringbuffer_insert( rtl_uString ** This, const sal_Unicode * str, sal_Int32 len) { - assert(This); - assert(capacity && *capacity >= 0); - assert(offset >= 0 && offset <= (**This).length); - assert(len >= 0); - sal_Int32 nOldLen; - sal_Unicode * pBuf; - sal_Int32 n; - if( len == 0 ) - return; - - if (*capacity < (*This)->length + len) - rtl_uStringbuffer_ensureCapacity( This, capacity, (*This)->length + len ); - - nOldLen = (*This)->length; - pBuf = (*This)->buffer; - - /* copy the tail */ - n = (nOldLen - offset); - if( n == 1 ) - /* optimized for 1 character */ - pBuf[offset + len] = pBuf[offset]; - else if( n > 1 ) - memmove( pBuf + offset + len, pBuf + offset, n * sizeof(sal_Unicode) ); - - /* insert the new characters */ - if( str != nullptr ) - { - if( len == 1 ) - /* optimized for 1 character */ - pBuf[offset] = *str; - else - memcpy( pBuf + offset, str, len * sizeof(sal_Unicode) ); - } - (*This)->length = nOldLen + len; - pBuf[ nOldLen + len ] = 0; + rtl::str::stringbuffer_insert(This, capacity, offset, str, len); } void rtl_uStringbuffer_insertUtf32( @@ -175,7 +90,7 @@ void rtl_uStringbuffer_insertUtf32( { sal_Unicode buf[2]; sal_Int32 len = rtl::splitSurrogates(c, buf); - rtl_uStringbuffer_insert(pThis, capacity, offset, buf, len); + rtl::str::stringbuffer_insert(pThis, capacity, offset, buf, len); } void SAL_CALL rtl_uStringbuffer_insert_ascii( /*inout*/rtl_uString ** This, @@ -184,42 +99,7 @@ void SAL_CALL rtl_uStringbuffer_insert_ascii( /*inout*/rtl_uString ** This, const char * str, sal_Int32 len) { - assert(This); - assert(capacity && *capacity >= 0); - assert(offset >= 0 && offset <= (**This).length); - assert(len == 0 || str != nullptr); - assert(len >= 0); - sal_Int32 nOldLen; - sal_Unicode * pBuf; - sal_Int32 n; - if( len == 0 ) - return; - - if (*capacity < (*This)->length + len) - rtl_uStringbuffer_ensureCapacity( This, capacity, (*This)->length + len ); - - nOldLen = (*This)->length; - pBuf = (*This)->buffer; - - /* copy the tail */ - n = (nOldLen - offset); - if( n == 1 ) - /* optimized for 1 character */ - pBuf[offset + len] = pBuf[offset]; - else if( n > 1 ) - memmove( pBuf + offset + len, pBuf + offset, n * sizeof(sal_Unicode) ); - - /* insert the new characters */ - for( n = 0; n < len; n++ ) - { - /* Check ASCII range */ - OSL_ENSURE( (*str & 0x80) == 0, "Found ASCII char > 127"); - - pBuf[offset + n] = static_cast<sal_Unicode>(*(str++)); - } - - (*This)->length = nOldLen + len; - pBuf[ nOldLen + len ] = 0; + rtl::str::stringbuffer_insert(This, capacity, offset, str, len); } /************************************************************************* @@ -229,30 +109,7 @@ void SAL_CALL rtl_uStringbuffer_remove( rtl_uString ** This, sal_Int32 start, sal_Int32 len ) { - assert(This); - assert(start >= 0 && start <= (**This).length); - assert(len >= 0); - sal_Int32 nTailLen; - sal_Unicode * pBuf; - - if (len > (*This)->length - start) - len = (*This)->length - start; - - //remove nothing - if (!len) - return; - - pBuf = (*This)->buffer; - nTailLen = (*This)->length - ( start + len ); - - if (nTailLen) - { - /* move the tail */ - memmove(pBuf + start, pBuf + start + len, nTailLen * sizeof(sal_Unicode)); - } - - (*This)->length-=len; - pBuf[ (*This)->length ] = 0; + rtl::str::stringbuffer_remove(This, start, len); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/rtl/ustring.cxx b/sal/rtl/ustring.cxx index cc3ca24be71d..62157a6bafca 100644 --- a/sal/rtl/ustring.cxx +++ b/sal/rtl/ustring.cxx @@ -57,17 +57,6 @@ static_assert(sizeof (rtl_uString) == 12); #include "strtmpl.hxx" -/* static data to be referenced by all empty strings - * the refCount is predefined to 1 and must never become 0 ! - */ -template<> -rtl_uString rtl::str::EmptyStringImpl<rtl_uString>::data = -{ - sal_Int32(SAL_STRING_INTERN_FLAG|SAL_STRING_STATIC_FLAG|1), /*sal_Int32 refCount; */ - 0, /*sal_Int32 length; */ - { 0 } /*sal_Unicode buffer[1];*/ -}; - /* ======================================================================= */ sal_Int32 rtl_ustr_indexOfAscii_WithLength( @@ -760,8 +749,7 @@ void SAL_CALL rtl_uString_internConvert( rtl_uString ** newStr, rtl_ustring_intern_internal( newStr, scratch, CAN_RETURN ); } -static void -internRelease (rtl_uString *pThis) +void internRelease (rtl_uString *pThis) { rtl_uString *pFree = nullptr; if ( SAL_STRING_REFCOUNT( |