diff options
Diffstat (limited to 'i18npool/source/transliteration/transliteration_body.cxx')
-rw-r--r-- | i18npool/source/transliteration/transliteration_body.cxx | 98 |
1 files changed, 36 insertions, 62 deletions
diff --git a/i18npool/source/transliteration/transliteration_body.cxx b/i18npool/source/transliteration/transliteration_body.cxx index 6d6c710b57c2..b168a5e37b3a 100644 --- a/i18npool/source/transliteration/transliteration_body.cxx +++ b/i18npool/source/transliteration/transliteration_body.cxx @@ -23,11 +23,13 @@ #include <com/sun/star/i18n/MultipleCharsOutputException.hpp> #include <com/sun/star/i18n/TransliterationType.hpp> #include <comphelper/processfactory.hxx> +#include <comphelper/sequence.hxx> #include <characterclassificationImpl.hxx> #include <transliteration_body.hxx> #include <memory> +#include <numeric> using namespace ::com::sun::star::uno; using namespace ::com::sun::star::i18n; @@ -92,80 +94,59 @@ Transliteration_body::transliterateImpl( { const sal_Unicode *in = inStr.getStr() + startPos; - // Two different blocks to eliminate the if(useOffset) condition inside the - // inner k loop. Yes, on massive use even such small things do count. - if ( useOffset ) + // We could assume that most calls result in identical string lengths, + // thus using a preallocated OUStringBuffer could be an easy way + // to assemble the return string without too much hassle. However, + // for single characters the OUStringBuffer::append() method is quite + // expensive compared to a simple array operation, so it pays here + // to copy the final result instead. + + // Allocate the max possible buffer. Try to use stack instead of heap, + // which would have to be reallocated most times anyways. + constexpr sal_Int32 nLocalBuf = 2048; + sal_Unicode aLocalBuf[ nLocalBuf * NMAPPINGMAX ], *out = aLocalBuf; + std::unique_ptr<sal_Unicode[]> pHeapBuf; + if (nCount > nLocalBuf) { - sal_Int32 nOffCount = 0, i; - for (i = 0; i < nCount; i++) - { - // take care of TOGGLE_CASE transliteration: - MappingType nTmpMappingType = lcl_getMappingTypeForToggleCase( nMappingType, in[i] ); - - const i18nutil::Mapping &map = i18nutil::casefolding::getValue( in, i, nCount, aLocale, nTmpMappingType ); - nOffCount += map.nmap; - } - rtl_uString* pStr = rtl_uString_alloc(nOffCount); - sal_Unicode* out = pStr->buffer; + pHeapBuf.reset(new sal_Unicode[ nCount * NMAPPINGMAX ]); + out = pHeapBuf.get(); + } - if ( nOffCount != offset.getLength() ) - offset.realloc( nOffCount ); + sal_Int32 j = 0; + // Two different blocks to eliminate the if(useOffset) condition inside the loop. + // Yes, on massive use even such small things do count. + if ( useOffset ) + { + std::vector<sal_Int32> aVec; + aVec.reserve(std::max<sal_Int32>(nLocalBuf, nCount) * NMAPPINGMAX); - sal_Int32 j = 0; - sal_Int32 * pArr = offset.getArray(); - for (i = 0; i < nCount; i++) + for (sal_Int32 i = 0; i < nCount; i++) { // take care of TOGGLE_CASE transliteration: MappingType nTmpMappingType = lcl_getMappingTypeForToggleCase( nMappingType, in[i] ); const i18nutil::Mapping &map = i18nutil::casefolding::getValue( in, i, nCount, aLocale, nTmpMappingType ); - for (sal_Int32 k = 0; k < map.nmap; k++) - { - pArr[j] = i + startPos; - out[j++] = map.map[k]; - } + std::fill_n(std::back_inserter(aVec), map.nmap, i + startPos); + std::copy_n(map.map, map.nmap, out + j); + j += map.nmap; } - out[j] = 0; - return OUString( pStr, SAL_NO_ACQUIRE ); + offset = comphelper::containerToSequence(aVec); } else { - // In the simple case of no offset sequence used we can eliminate the - // first getValue() loop. We could also assume that most calls result - // in identical string lengths, thus using a preallocated - // OUStringBuffer could be an easy way to assemble the return string - // without too much hassle. However, for single characters the - // OUStringBuffer::append() method is quite expensive compared to a - // simple array operation, so it pays here to copy the final result - // instead. - - // Allocate the max possible buffer. Try to use stack instead of heap, - // which would have to be reallocated most times anyways. - const sal_Int32 nLocalBuf = 2048; - sal_Unicode aLocalBuf[ nLocalBuf * NMAPPINGMAX ], *out = aLocalBuf; - std::unique_ptr<sal_Unicode[]> pHeapBuf; - if ( nCount > nLocalBuf ) { - pHeapBuf.reset(new sal_Unicode[ nCount * NMAPPINGMAX ]); - out = pHeapBuf.get(); - } - - sal_Int32 j = 0; for ( sal_Int32 i = 0; i < nCount; i++) { // take care of TOGGLE_CASE transliteration: MappingType nTmpMappingType = lcl_getMappingTypeForToggleCase( nMappingType, in[i] ); const i18nutil::Mapping &map = i18nutil::casefolding::getValue( in, i, nCount, aLocale, nTmpMappingType ); - for (sal_Int32 k = 0; k < map.nmap; k++) - { - out[j++] = map.map[k]; - } + std::copy_n(map.map, map.nmap, out + j); + j += map.nmap; } - - OUString aRet( out, j ); - return aRet; } + + return OUString(out, j); } OUString SAL_CALL @@ -279,15 +260,8 @@ static OUString transliterate_titlecase_Impl( aRes += xCharClassImpl->toLower( aText, 1, aText.getLength() - 1, rLocale ); offset.realloc( aRes.getLength() ); - sal_Int32 *pOffset = offset.getArray(); - sal_Int32 nLen = offset.getLength(); - for (sal_Int32 i = 0; i < nLen; ++i) - { - sal_Int32 nIdx = 0; - if (i >= nResolvedLen) - nIdx = i - nResolvedLen + 1; - pOffset[i] = nIdx; - } + sal_Int32* pOffset = std::fill_n(offset.begin(), nResolvedLen, 0); + std::iota(pOffset, offset.end(), 1); } return aRes; } |