    /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
    /*
     * This file is part of the LibreOffice project.
     *
     * This Source Code Form is subject to the terms of the Mozilla Public
     * License, v. 2.0. If a copy of the MPL was not distributed with this
     * file, You can obtain one at http://mozilla.org/MPL/2.0/.
     *
     * This file incorporates work covered by the following license notice:
     *
     *   Licensed to the Apache Software Foundation (ASF) under one or more
     *   contributor license agreements. See the NOTICE file distributed
     *   with this work for additional information regarding copyright
     *   ownership. The ASF licenses this file to you under the Apache
     *   License, Version 2.0 (the "License"); you may not use this file
     *   except in compliance with the License. You may obtain a copy of
     *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
     */

    /* ======================================================================= */
    /* Internal C-String help functions which could be used without the        */
    /* String-Class                                                            */
    /* ======================================================================= */

    #include <algorithm>
    #include <cassert>
    #include <limits>

    #include <cstring>
    #include <wchar.h>
    #include <sal/log.hxx>
    #include <rtl/character.hxx>

    /*
    inline void rtl_str_ImplCopy( IMPL_RTL_STRCODE* pDest,
                                  const IMPL_RTL_STRCODE* pSrc,
                                  sal_Int32 nCount )
    {
        while ( nCount > 0 )
        {
            *pDest = *pSrc;
            pDest++;
            pSrc++;
            nCount--;
        }
    }
    */

    static inline void rtl_str_ImplCopy( IMPL_RTL_STRCODE* _pDest,
                                         const IMPL_RTL_STRCODE* _pSrc,
                                         sal_Int32 _nCount )
    {
        // take advantage of builtin optimisations
        memcpy( _pDest, _pSrc, _nCount * sizeof(IMPL_RTL_STRCODE));
    }

    /* ======================================================================= */
    /* C-String functions which could be used without the String-Class         */
    /* ======================================================================= */

    sal_Int32 SAL_CALL IMPL_RTL_STRNAME( getLength )( const IMPL_RTL_STRCODE* pStr )
        SAL_THROW_EXTERN_C()
    {
        assert(pStr);
    #if !IMPL_RTL_IS_USTRING
        // take advantage of builtin optimisations
        return strlen( pStr);
    #else
        if (sizeof(IMPL_RTL_STRCODE) == sizeof(wchar_t))
        {
            // take advantage of builtin optimisations
            return wcslen(reinterpret_cast<wchar_t const *>(pStr));
        }
        else
        {
            const IMPL_RTL_STRCODE* pTempStr = pStr;
            while( *pTempStr )
                pTempStr++;
            return pTempStr-pStr;
        }
    #endif
    }

    /* ----------------------------------------------------------------------- */

    sal_Int32 SAL_CALL IMPL_RTL_STRNAME( compare )( const IMPL_RTL_STRCODE* pStr1,
                                                    const IMPL_RTL_STRCODE* pStr2 )
        SAL_THROW_EXTERN_C()
    {
        assert(pStr1);
        assert(pStr2);
    #if !IMPL_RTL_IS_USTRING
        // take advantage of builtin optimisations
        return strcmp( pStr1, pStr2);
    #else
        if (sizeof(IMPL_RTL_STRCODE) == sizeof(wchar_t))
        {
            // take advantage of builtin optimisations
            return wcscmp(reinterpret_cast<wchar_t const *>(pStr1), reinterpret_cast<wchar_t const *>(pStr2));
        }
        else
        {
            sal_Int32 nRet;
            while ( ((nRet = static_cast<sal_Int32>(IMPL_RTL_USTRCODE(*pStr1))-
                             static_cast<sal_Int32>(IMPL_RTL_USTRCODE(*pStr2))) == 0) &&
                    *pStr2 )
            {
                pStr1++;
                pStr2++;
            }

            return nRet;
        }
    #endif
    }

    /* ----------------------------------------------------------------------- */

    sal_Int32 SAL_CALL IMPL_RTL_STRNAME( compare_WithLength )( const IMPL_RTL_STRCODE* pStr1,
                                                               sal_Int32 nStr1Len,
                                                               const IMPL_RTL_STRCODE* pStr2,
                                                               sal_Int32 nStr2Len )
        SAL_THROW_EXTERN_C()
    {
        assert(nStr1Len >= 0);
        assert(nStr2Len >= 0);
    #if !IMPL_RTL_IS_USTRING
        // take advantage of builtin optimisations
        sal_Int32 nMin = std::min(nStr1Len, nStr2Len);
        sal_Int32 nRet = memcmp(pStr1, pStr2, nMin);
        return nRet == 0 ? nStr1Len - nStr2Len : nRet;
    #else
        if (sizeof(IMPL_RTL_STRCODE) == sizeof(wchar_t))
        {
            // take advantage of builtin optimisations
            sal_Int32 nMin = std::min(nStr1Len, nStr2Len);
            sal_Int32 nRet = wmemcmp(reinterpret_cast<wchar_t const *>(pStr1),
                    reinterpret_cast<wchar_t const *>(pStr2), nMin);
            return nRet == 0 ? nStr1Len - nStr2Len : nRet;
        }
        else
        {
            sal_Int32 nRet = nStr1Len - nStr2Len;
            int nCount = (nRet <= 0) ? nStr1Len : nStr2Len;

            --pStr1;
            --pStr2;
            while( (--nCount >= 0) && (*++pStr1 == *++pStr2) ) ;

            if( nCount >= 0 )
                nRet = static_cast<sal_Int32>(IMPL_RTL_USTRCODE( *pStr1 ))
                     - static_cast<sal_Int32>(IMPL_RTL_USTRCODE( *pStr2 ));

            return nRet;
        }
    #endif
    }

    /* ----------------------------------------------------------------------- */

    sal_Int32 SAL_CALL IMPL_RTL_STRNAME( shortenedCompare_WithLength )( const IMPL_RTL_STRCODE* pStr1,
                                                                        sal_Int32 nStr1Len,
                                                                        const IMPL_RTL_STRCODE* pStr2,
                                                                        sal_Int32 nStr2Len,
                                                                        sal_Int32 nShortenedLength )
        SAL_THROW_EXTERN_C()
    {
        assert(nStr1Len >= 0);
        assert(nStr2Len >= 0);
        assert(nShortenedLength >= 0);
    #if !IMPL_RTL_IS_USTRING
        // take advantage of builtin optimisations
        sal_Int32 nMin = std::min(std::min(nStr1Len, nStr2Len), nShortenedLength);
        sal_Int32 nRet = memcmp(pStr1, pStr2, nMin);
        if (nRet == 0 && nShortenedLength > std::min(nStr1Len, nStr2Len))
            return nStr1Len - nStr2Len;
        return nRet;
    #else
        if (sizeof(IMPL_RTL_STRCODE) == sizeof(wchar_t))
        {
            // take advantage of builtin optimisations
            sal_Int32 nMin = std::min(std::min(nStr1Len, nStr2Len), nShortenedLength);
            sal_Int32 nRet = wmemcmp(reinterpret_cast<wchar_t const *>(pStr1), reinterpret_cast<wchar_t const *>(pStr2), nMin);
            if (nRet == 0 && nShortenedLength > std::min(nStr1Len, nStr2Len))
                return nStr1Len - nStr2Len;
            return nRet;
        }
        else
        {
            const IMPL_RTL_STRCODE* pStr1End = pStr1 + nStr1Len;
            const IMPL_RTL_STRCODE* pStr2End = pStr2 + nStr2Len;
            sal_Int32               nRet;
            while ( (nShortenedLength > 0) &&
                    (pStr1 < pStr1End) && (pStr2 < pStr2End) )
            {
                nRet = static_cast<sal_Int32>(IMPL_RTL_USTRCODE( *pStr1 ))-
                       static_cast<sal_Int32>(IMPL_RTL_USTRCODE( *pStr2 ));
                if ( nRet )
                    return nRet;

                nShortenedLength--;
                pStr1++;
                pStr2++;
            }

            if ( nShortenedLength <= 0 )
                return 0;
            return nStr1Len - nStr2Len;
        }
    #endif
    }

    /* ----------------------------------------------------------------------- */

    sal_Int32 SAL_CALL IMPL_RTL_STRNAME( reverseCompare_WithLength )( const IMPL_RTL_STRCODE* pStr1,
                                                                      sal_Int32 nStr1Len,
                                                                      const IMPL_RTL_STRCODE* pStr2,
                                                                      sal_Int32 nStr2Len )
        SAL_THROW_EXTERN_C()
    {
        assert(nStr1Len >= 0);
        assert(nStr2Len >= 0);
        const IMPL_RTL_STRCODE* pStr1Run = pStr1+nStr1Len;
        const IMPL_RTL_STRCODE* pStr2Run = pStr2+nStr2Len;
        sal_Int32               nRet;
        while ( (pStr1 < pStr1Run) && (pStr2 < pStr2Run) )
        {
            pStr1Run--;
            pStr2Run--;
            nRet = static_cast<sal_Int32>(IMPL_RTL_USTRCODE( *pStr1Run ))-
                   static_cast<sal_Int32>(IMPL_RTL_USTRCODE( *pStr2Run ));
            if ( nRet )
                return nRet;
        }

        return nStr1Len - nStr2Len;
    }

    /* ----------------------------------------------------------------------- */

    sal_Int32 SAL_CALL IMPL_RTL_STRNAME( compareIgnoreAsciiCase )( const IMPL_RTL_STRCODE* pStr1,
                                                                   const IMPL_RTL_STRCODE* pStr2 )
        SAL_THROW_EXTERN_C()
    {
        assert(pStr1);
        assert(pStr2);
        sal_uInt32 c1;
        do
        {
            c1 = IMPL_RTL_USTRCODE(*pStr1);
            sal_Int32 nRet = rtl::compareIgnoreAsciiCase(
                c1, IMPL_RTL_USTRCODE(*pStr2));
            if ( nRet != 0 )
                return nRet;

            pStr1++;
            pStr2++;
        }
        while (c1);

        return 0;
    }

    /* ----------------------------------------------------------------------- */

    sal_Int32 SAL_CALL IMPL_RTL_STRNAME( compareIgnoreAsciiCase_WithLength )( const IMPL_RTL_STRCODE* pStr1,
                                                                              sal_Int32 nStr1Len,
                                                                              const IMPL_RTL_STRCODE* pStr2,
                                                                              sal_Int32 nStr2Len )
        SAL_THROW_EXTERN_C()
    {
        assert(nStr1Len >= 0);
        assert(nStr2Len >= 0);
        const IMPL_RTL_STRCODE* pStr1End = pStr1 + nStr1Len;
        const IMPL_RTL_STRCODE* pStr2End = pStr2 + nStr2Len;
        while ( (pStr1 < pStr1End) && (pStr2 < pStr2End) )
        {
            sal_Int32 nRet = rtl::compareIgnoreAsciiCase(
                IMPL_RTL_USTRCODE(*pStr1), IMPL_RTL_USTRCODE(*pStr2));
            if ( nRet != 0 )
                return nRet;

            pStr1++;
            pStr2++;
        }

        return nStr1Len - nStr2Len;
    }

    /* ----------------------------------------------------------------------- */

    sal_Int32 SAL_CALL IMPL_RTL_STRNAME( shortenedCompareIgnoreAsciiCase_WithLength )( const IMPL_RTL_STRCODE* pStr1,
                                                                                       sal_Int32 nStr1Len,
                                                                                       const IMPL_RTL_STRCODE* pStr2,
                                                                                       sal_Int32 nStr2Len,
                                                                                       sal_Int32 nShortenedLength )
        SAL_THROW_EXTERN_C()
    {
        assert(nStr1Len >= 0);
        assert(nStr2Len >= 0);
        assert(nShortenedLength >= 0);
        const IMPL_RTL_STRCODE* pStr1End = pStr1 + nStr1Len;
        const IMPL_RTL_STRCODE* pStr2End = pStr2 + nStr2Len;
        while ( (nShortenedLength > 0) &&
                (pStr1 < pStr1End) && (pStr2 < pStr2End) )
        {
            sal_Int32 nRet = rtl::compareIgnoreAsciiCase(
                IMPL_RTL_USTRCODE(*pStr1), IMPL_RTL_USTRCODE(*pStr2));
            if ( nRet != 0 )
                return nRet;

            nShortenedLength--;
            pStr1++;
            pStr2++;
        }

        if ( nShortenedLength <= 0 )
            return 0;
        return nStr1Len - nStr2Len;
    }

    /* ----------------------------------------------------------------------- */

    sal_Int32 SAL_CALL IMPL_RTL_STRNAME( hashCode )( const IMPL_RTL_STRCODE* pStr )
        SAL_THROW_EXTERN_C()
    {
        return IMPL_RTL_STRNAME( hashCode_WithLength )( pStr, IMPL_RTL_STRNAME( getLength )( pStr ) );
    }

    /* ----------------------------------------------------------------------- */

    sal_Int32 SAL_CALL IMPL_RTL_STRNAME( hashCode_WithLength )( const IMPL_RTL_STRCODE* pStr,
                                                                sal_Int32 nLen )
        SAL_THROW_EXTERN_C()
    {
        assert(nLen >= 0);
        sal_uInt32 h = static_cast<sal_uInt32>(nLen);
        while ( nLen > 0 )
        {
            h = (h*37U) + IMPL_RTL_USTRCODE( *pStr );
            pStr++;
            nLen--;
        }
        return static_cast<sal_Int32>(h);
    }

    /* ----------------------------------------------------------------------- */

    sal_Int32 SAL_CALL IMPL_RTL_STRNAME( indexOfChar )( const IMPL_RTL_STRCODE* pStr,
                                                        IMPL_RTL_STRCODE c )
        SAL_THROW_EXTERN_C()
    {
        assert(pStr);
    #if !IMPL_RTL_IS_USTRING
        // take advantage of builtin optimisations
        const IMPL_RTL_STRCODE* p = strchr(pStr, c);
        return p ? p - pStr : -1;
    #else
        if (sizeof(IMPL_RTL_STRCODE) == sizeof(wchar_t))
        {
            // take advantage of builtin optimisations
            wchar_t const * p = wcschr(reinterpret_cast<wchar_t const *>(pStr), static_cast<wchar_t>(c));
            return p ? p - reinterpret_cast<wchar_t const *>(pStr) : -1;
        }
        else
        {
            const IMPL_RTL_STRCODE* pTempStr = pStr;
            while ( *pTempStr )
            {
                if ( *pTempStr == c )
                    return pTempStr-pStr;

                pTempStr++;
            }

            return -1;
        }
    #endif
    }

    /* ----------------------------------------------------------------------- */

    sal_Int32 SAL_CALL IMPL_RTL_STRNAME( indexOfChar_WithLength )( const IMPL_RTL_STRCODE* pStr,
                                                                   sal_Int32 nLen,
                                                                   IMPL_RTL_STRCODE c )
        SAL_THROW_EXTERN_C()
    {
    //    assert(nLen >= 0);
    #if !IMPL_RTL_IS_USTRING
        // take advantage of builtin optimisations
        IMPL_RTL_STRCODE* p = static_cast<IMPL_RTL_STRCODE*>(std::memchr(const_cast<IMPL_RTL_STRCODE *>(pStr), c, nLen));
        return p ? p - pStr : -1;
    #else
        const IMPL_RTL_STRCODE* pTempStr = pStr;
        while ( nLen > 0 )
        {
            if ( *pTempStr == c )
                return pTempStr-pStr;

            pTempStr++;
            nLen--;
        }

        return -1;
    #endif
    }

    /* ----------------------------------------------------------------------- */

    sal_Int32 SAL_CALL IMPL_RTL_STRNAME( lastIndexOfChar )( const IMPL_RTL_STRCODE* pStr,
                                                            IMPL_RTL_STRCODE c )
        SAL_THROW_EXTERN_C()
    {
        assert(pStr);
    #if !IMPL_RTL_IS_USTRING
        // take advantage of builtin optimisations
        const IMPL_RTL_STRCODE* p = strrchr(pStr, c);
        return p ? p - pStr : -1;
    #else
        if (sizeof(IMPL_RTL_STRCODE) == sizeof(wchar_t))
        {
            // take advantage of builtin optimisations
            wchar_t const * p = wcsrchr(reinterpret_cast<wchar_t const *>(pStr), static_cast<wchar_t>(c));
            return p ? p - reinterpret_cast<wchar_t const *>(pStr) : -1;
        }
        else
        {
            return IMPL_RTL_STRNAME( lastIndexOfChar_WithLength )( pStr, IMPL_RTL_STRNAME( getLength )( pStr ), c );
        }
    #endif
    }

    /* ----------------------------------------------------------------------- */

    sal_Int32 SAL_CALL IMPL_RTL_STRNAME( lastIndexOfChar_WithLength )( const IMPL_RTL_STRCODE* pStr,
                                                                       sal_Int32 nLen,
                                                                       IMPL_RTL_STRCODE c )
        SAL_THROW_EXTERN_C()
    {
        assert(nLen >= 0);
        pStr += nLen;
        while ( nLen > 0 )
        {
            nLen--;
            pStr--;

            if ( *pStr == c )
                return nLen;
        }

        return -1;
    }

    /* ----------------------------------------------------------------------- */

    sal_Int32 SAL_CALL IMPL_RTL_STRNAME( indexOfStr )( const IMPL_RTL_STRCODE* pStr,
                                                       const IMPL_RTL_STRCODE* pSubStr )
        SAL_THROW_EXTERN_C()
    {
        assert(pStr);
        assert(pSubStr);
    #if !IMPL_RTL_IS_USTRING
        // take advantage of builtin optimisations
        const IMPL_RTL_STRCODE* p = strstr(pStr, pSubStr);
        return p ? p - pStr : -1;
    #else
        if (sizeof(IMPL_RTL_STRCODE) == sizeof(wchar_t))
        {
            // take advantage of builtin optimisations
            wchar_t const * p = wcsstr(reinterpret_cast<wchar_t const *>(pStr), reinterpret_cast<wchar_t const *>(pSubStr));
            return p ? p - reinterpret_cast<wchar_t const *>(pStr) : -1;
        }
        else
        {
           return IMPL_RTL_STRNAME( indexOfStr_WithLength )( pStr, IMPL_RTL_STRNAME( getLength )( pStr ),
                                                             pSubStr, IMPL_RTL_STRNAME( getLength )( pSubStr ) );
        }
    #endif
    }

    /* ----------------------------------------------------------------------- */

    sal_Int32 SAL_CALL IMPL_RTL_STRNAME( indexOfStr_WithLength )( const IMPL_RTL_STRCODE* pStr,
                                                                  sal_Int32 nStrLen,
                                                                  const  IMPL_RTL_STRCODE* pSubStr,
                                                                  sal_Int32 nSubLen )
        SAL_THROW_EXTERN_C()
    {
        assert(nStrLen >= 0);
        assert(nSubLen >= 0);
        /* faster search for a single character */
        if ( nSubLen < 2 )
        {
            /* an empty SubString is always not findable */
            if ( nSubLen == 1 )
            {
                IMPL_RTL_STRCODE        c = *pSubStr;
                const IMPL_RTL_STRCODE* pTempStr = pStr;
                while ( nStrLen > 0 )
                {
                    if ( *pTempStr == c )
                        return pTempStr-pStr;

                    pTempStr++;
                    nStrLen--;
                }
            }
        }
        else
        {
            const IMPL_RTL_STRCODE* pTempStr = pStr;
            while ( nStrLen > 0 )
            {
                if ( *pTempStr == *pSubStr )
                {
                    /* Compare SubString */
                    if ( nSubLen <= nStrLen )
                    {
                        const IMPL_RTL_STRCODE* pTempStr1 = pTempStr;
                        const IMPL_RTL_STRCODE* pTempStr2 = pSubStr;
                        sal_Int32               nTempLen = nSubLen;
                        while ( nTempLen )
                        {
                            if ( *pTempStr1 != *pTempStr2 )
                                break;

                            pTempStr1++;
                            pTempStr2++;
                            nTempLen--;
                        }

                        if ( !nTempLen )
                            return pTempStr-pStr;
                    }
                    else
                        break;
                }

                nStrLen--;
                pTempStr++;
            }
        }

        return -1;
    }

    /* ----------------------------------------------------------------------- */

    sal_Int32 SAL_CALL IMPL_RTL_STRNAME( lastIndexOfStr )( const IMPL_RTL_STRCODE* pStr,
                                                           const IMPL_RTL_STRCODE* pSubStr )
        SAL_THROW_EXTERN_C()
    {
        return IMPL_RTL_STRNAME( lastIndexOfStr_WithLength )( pStr, IMPL_RTL_STRNAME( getLength )( pStr ),
                                                              pSubStr, IMPL_RTL_STRNAME( getLength )( pSubStr ) );
    }

    /* ----------------------------------------------------------------------- */

    sal_Int32 SAL_CALL IMPL_RTL_STRNAME( lastIndexOfStr_WithLength )( const IMPL_RTL_STRCODE* pStr,
                                                                      sal_Int32 nStrLen,
                                                                      const IMPL_RTL_STRCODE* pSubStr,
                                                                      sal_Int32 nSubLen )
        SAL_THROW_EXTERN_C()
    {
        assert(nStrLen >= 0);
        assert(nSubLen >= 0);
        /* faster search for a single character */
        if ( nSubLen < 2 )
        {
            /* an empty SubString is always not findable */
            if ( nSubLen == 1 )
            {
                IMPL_RTL_STRCODE c = *pSubStr;
                pStr += nStrLen;
                while ( nStrLen > 0 )
                {
                    nStrLen--;
                    pStr--;

                    if ( *pStr == c )
                        return nStrLen;
                }
            }
        }
        else
        {
            pStr += nStrLen;
            nStrLen -= nSubLen;
            pStr -= nSubLen;
            while ( nStrLen >= 0 )
            {
                const IMPL_RTL_STRCODE* pTempStr1 = pStr;
                const IMPL_RTL_STRCODE* pTempStr2 = pSubStr;
                sal_Int32               nTempLen = nSubLen;
                while ( nTempLen )
                {
                    if ( *pTempStr1 != *pTempStr2 )
                        break;

                    pTempStr1++;
                    pTempStr2++;
                    nTempLen--;
                }

                if ( !nTempLen )
                    return nStrLen;

                nStrLen--;
                pStr--;
            }
        }

        return -1;
    }

    /* ----------------------------------------------------------------------- */

    void SAL_CALL IMPL_RTL_STRNAME( replaceChar )( IMPL_RTL_STRCODE* pStr,
                                                   IMPL_RTL_STRCODE cOld,
                                                   IMPL_RTL_STRCODE cNew )
        SAL_THROW_EXTERN_C()
    {
        assert(pStr);
        while ( *pStr )
        {
            if ( *pStr == cOld )
                *pStr = cNew;

            pStr++;
        }
    }

    /* ----------------------------------------------------------------------- */

    void SAL_CALL IMPL_RTL_STRNAME( replaceChar_WithLength )( IMPL_RTL_STRCODE* pStr,
                                                              sal_Int32 nLen,
                                                              IMPL_RTL_STRCODE cOld,
                                                              IMPL_RTL_STRCODE cNew )
        SAL_THROW_EXTERN_C()
    {
        assert(nLen >= 0);
        while ( nLen > 0 )
        {
            if ( *pStr == cOld )
                *pStr = cNew;

            pStr++;
            nLen--;
        }
    }

    /* ----------------------------------------------------------------------- */

    void SAL_CALL IMPL_RTL_STRNAME( toAsciiLowerCase )( IMPL_RTL_STRCODE* pStr )
        SAL_THROW_EXTERN_C()
    {
        assert(pStr);
        while ( *pStr )
        {
            *pStr = rtl::toAsciiLowerCase(IMPL_RTL_USTRCODE(*pStr));

            pStr++;
        }
    }

    /* ----------------------------------------------------------------------- */

    void SAL_CALL IMPL_RTL_STRNAME( toAsciiLowerCase_WithLength )( IMPL_RTL_STRCODE* pStr,
                                                                   sal_Int32 nLen )
        SAL_THROW_EXTERN_C()
    {
        assert(nLen >= 0);
        while ( nLen > 0 )
        {
            *pStr = rtl::toAsciiLowerCase(IMPL_RTL_USTRCODE(*pStr));

            pStr++;
            nLen--;
        }
    }

    /* ----------------------------------------------------------------------- */

    void SAL_CALL IMPL_RTL_STRNAME( toAsciiUpperCase )( IMPL_RTL_STRCODE* pStr )
        SAL_THROW_EXTERN_C()
    {
        assert(pStr);
        while ( *pStr )
        {
            *pStr = rtl::toAsciiUpperCase(IMPL_RTL_USTRCODE(*pStr));

            pStr++;
        }
    }

    /* ----------------------------------------------------------------------- */

    void SAL_CALL IMPL_RTL_STRNAME( toAsciiUpperCase_WithLength )( IMPL_RTL_STRCODE* pStr,
                                                                   sal_Int32 nLen )
        SAL_THROW_EXTERN_C()
    {
        assert(nLen >= 0);
        while ( nLen > 0 )
        {
            *pStr = rtl::toAsciiUpperCase(IMPL_RTL_USTRCODE(*pStr));

            pStr++;
            nLen--;
        }
    }

    /* ----------------------------------------------------------------------- */

    sal_Int32 SAL_CALL IMPL_RTL_STRNAME( trim )( IMPL_RTL_STRCODE* pStr )
        SAL_THROW_EXTERN_C()
    {
        return IMPL_RTL_STRNAME( trim_WithLength )( pStr, IMPL_RTL_STRNAME( getLength )( pStr ) );
    }

    /* ----------------------------------------------------------------------- */

    sal_Int32 SAL_CALL IMPL_RTL_STRNAME( trim_WithLength )( IMPL_RTL_STRCODE* pStr, sal_Int32 nLen )
        SAL_THROW_EXTERN_C()
    {
        assert(nLen >= 0);
        sal_Int32 nPreSpaces    = 0;
        sal_Int32 nPostSpaces   = 0;
        sal_Int32 nIndex        = nLen-1;

        while ( (nPreSpaces < nLen) && rtl_ImplIsWhitespace( IMPL_RTL_USTRCODE(*(pStr+nPreSpaces)) ) )
            nPreSpaces++;

        while ( (nIndex > nPreSpaces) && rtl_ImplIsWhitespace( IMPL_RTL_USTRCODE(*(pStr+nIndex)) ) )
        {
            nPostSpaces++;
            nIndex--;
        }

        if ( nPostSpaces )
        {
            nLen -= nPostSpaces;
            *(pStr+nLen) = 0;
        }

        if ( nPreSpaces )
        {
            nLen -= nPreSpaces;
            memmove(pStr, pStr + nPreSpaces, nLen * sizeof(IMPL_RTL_STRCODE));
            pStr += nLen;
            *pStr = 0;
        }

        return nLen;
    }

    /* ----------------------------------------------------------------------- */

    sal_Int32 SAL_CALL IMPL_RTL_STRNAME( valueOfBoolean )( IMPL_RTL_STRCODE* pStr, sal_Bool b )
        SAL_THROW_EXTERN_C()
    {
        assert(pStr);
        if ( b )
        {
            *pStr = 't';
            pStr++;
            *pStr = 'r';
            pStr++;
            *pStr = 'u';
            pStr++;
            *pStr = 'e';
            pStr++;
            *pStr = 0;
            return 4;
        }
        else
        {
            *pStr = 'f';
            pStr++;
            *pStr = 'a';
            pStr++;
            *pStr = 'l';
            pStr++;
            *pStr = 's';
            pStr++;
            *pStr = 'e';
            pStr++;
            *pStr = 0;
            return 5;
        }
    }

    /* ----------------------------------------------------------------------- */

    sal_Int32 SAL_CALL IMPL_RTL_STRNAME( valueOfChar )( IMPL_RTL_STRCODE* pStr,
                                                        IMPL_RTL_STRCODE c )
        SAL_THROW_EXTERN_C()
    {
        assert(pStr);
        *pStr++ = c;
        *pStr = 0;
        return 1;
    }

    /* ----------------------------------------------------------------------- */

    sal_Int32 SAL_CALL IMPL_RTL_STRNAME( valueOfInt32 )( IMPL_RTL_STRCODE* pStr,
                                                         sal_Int32 n,
                                                         sal_Int16 nRadix )
        SAL_THROW_EXTERN_C()
    {
        assert(pStr);
        assert( nRadix >= RTL_STR_MIN_RADIX && nRadix <= RTL_STR_MAX_RADIX );
        sal_Char    aBuf[RTL_STR_MAX_VALUEOFINT32];
        sal_Char*   pBuf = aBuf;
        sal_Int32   nLen = 0;
        sal_uInt32  nValue;

        /* Radix must be valid */
        if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
            nRadix = 10;

        /* is value negative */
        if ( n < 0 )
        {
            *pStr = '-';
            pStr++;
            nLen++;
            nValue = n == SAL_MIN_INT32 ? static_cast<sal_uInt32>(n) : -n;
        }
        else
            nValue = n;

        /* create a recursive buffer with all values, except the last one */
        do
        {
            sal_Char nDigit = static_cast<sal_Char>(nValue % nRadix);
            nValue /= nRadix;
            if ( nDigit > 9 )
                *pBuf = (nDigit-10) + 'a';
            else
                *pBuf = (nDigit + '0' );
            pBuf++;
        }
        while ( nValue > 0 );

        /* copy the values in the right direction into the destination buffer */
        do
        {
            pBuf--;
            *pStr = *pBuf;
            pStr++;
            nLen++;
        }
        while ( pBuf != aBuf );
        *pStr = 0;

        return nLen;
    }

    /* ----------------------------------------------------------------------- */

    sal_Int32 SAL_CALL IMPL_RTL_STRNAME( valueOfInt64 )( IMPL_RTL_STRCODE* pStr,
                                                         sal_Int64 n,
                                                         sal_Int16 nRadix )
        SAL_THROW_EXTERN_C()
    {
        assert(pStr);
        assert( nRadix >= RTL_STR_MIN_RADIX && nRadix <= RTL_STR_MAX_RADIX );
        sal_Char    aBuf[RTL_STR_MAX_VALUEOFINT64];
        sal_Char*   pBuf = aBuf;
        sal_Int32   nLen = 0;
        sal_uInt64  nValue;

        /* Radix must be valid */
        if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
            nRadix = 10;

        /* is value negative */
        if ( n < 0 )
        {
            *pStr = '-';
            pStr++;
            nLen++;
            nValue = n == SAL_MIN_INT64 ? static_cast<sal_uInt64>(n) : -n;
        }
        else
            nValue = n;

        /* create a recursive buffer with all values, except the last one */
        do
        {
            sal_Char nDigit = static_cast<sal_Char>(nValue % nRadix);
            nValue /= nRadix;
            if ( nDigit > 9 )
                *pBuf = (nDigit-10) + 'a';
            else
                *pBuf = (nDigit + '0' );
            pBuf++;
        }
        while ( nValue > 0 );

        /* copy the values in the right direction into the destination buffer */
        do
        {
            pBuf--;
            *pStr = *pBuf;
            pStr++;
            nLen++;
        }
        while ( pBuf != aBuf );
        *pStr = 0;

        return nLen;
    }

    /* ----------------------------------------------------------------------- */

    sal_Int32 SAL_CALL IMPL_RTL_STRNAME( valueOfUInt64 )( IMPL_RTL_STRCODE* pStr,
                                                          sal_uInt64 n,
                                                          sal_Int16 nRadix )
        SAL_THROW_EXTERN_C()
    {
        assert(pStr);
        assert( nRadix >= RTL_STR_MIN_RADIX && nRadix <= RTL_STR_MAX_RADIX );
        sal_Char    aBuf[RTL_STR_MAX_VALUEOFUINT64];
        sal_Char*   pBuf = aBuf;
        sal_Int32   nLen = 0;
        sal_uInt64  nValue;

        /* Radix must be valid */
        if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
            nRadix = 10;

        nValue = n;

        /* create a recursive buffer with all values, except the last one */
        do
        {
            sal_Char nDigit = static_cast<sal_Char>(nValue % nRadix);
            nValue /= nRadix;
            if ( nDigit > 9 )
                *pBuf = (nDigit-10) + 'a';
            else
                *pBuf = (nDigit + '0' );
            pBuf++;
        }
        while ( nValue > 0 );

        /* copy the values in the right direction into the destination buffer */
        do
        {
            pBuf--;
            *pStr = *pBuf;
            pStr++;
            nLen++;
        }
        while ( pBuf != aBuf );
        *pStr = 0;

        return nLen;
    }

    /* ----------------------------------------------------------------------- */

    sal_Bool SAL_CALL IMPL_RTL_STRNAME( toBoolean )( const IMPL_RTL_STRCODE* pStr )
        SAL_THROW_EXTERN_C()
    {
        assert(pStr);
        if ( *pStr == '1' )
            return true;

        if ( (*pStr == 'T') || (*pStr == 't') )
        {
            pStr++;
            if ( (*pStr == 'R') || (*pStr == 'r') )
            {
                pStr++;
                if ( (*pStr == 'U') || (*pStr == 'u') )
                {
                    pStr++;
                    if ( (*pStr == 'E') || (*pStr == 'e') )
                        return true;
                }
            }
        }

        return false;
    }

    /* ----------------------------------------------------------------------- */
    namespace {
        template<typename T, typename U> inline T IMPL_RTL_STRNAME( toInt )( const IMPL_RTL_STRCODE* pStr,
                                                                         sal_Int16 nRadix )
        {
            static_assert(std::numeric_limits<T>::is_signed, "is signed");
            assert( nRadix >= RTL_STR_MIN_RADIX && nRadix <= RTL_STR_MAX_RADIX );
            bool    bNeg;
            sal_Int16   nDigit;
            U           n = 0;

            if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
                nRadix = 10;

            /* Skip whitespaces */
            while ( *pStr && rtl_ImplIsWhitespace( IMPL_RTL_USTRCODE( *pStr ) ) )
                pStr++;

            if ( *pStr == '-' )
            {
                bNeg = true;
                pStr++;
            }
            else
            {
                if ( *pStr == '+' )
                    pStr++;
                bNeg = false;
            }

            T nDiv;
            sal_Int16 nMod;
            if ( bNeg )
            {
                nDiv = std::numeric_limits<T>::min() / nRadix;
                nMod = std::numeric_limits<T>::min() % nRadix;
                // Cater for C++03 implementations that round the quotient down
                // instead of truncating towards zero as mandated by C++11:
                if ( nMod > 0 )
                {
                    --nDiv;
                    nMod -= nRadix;
                }
                nDiv = -nDiv;
                nMod = -nMod;
            }
            else
            {
                nDiv = std::numeric_limits<T>::max() / nRadix;
                nMod = std::numeric_limits<T>::max() % nRadix;
            }

            while ( *pStr )
            {
                nDigit = rtl_ImplGetDigit( IMPL_RTL_USTRCODE( *pStr ), nRadix );
                if ( nDigit < 0 )
                    break;
                assert(nDiv > 0);
                if( static_cast<U>( nMod < nDigit ? nDiv-1 : nDiv ) < n )
                    return 0;

                n *= nRadix;
                n += nDigit;

                pStr++;
            }

            if ( bNeg )
                return n == static_cast<U>(std::numeric_limits<T>::min())
                    ? std::numeric_limits<T>::min() : -static_cast<T>(n);
            else
                return static_cast<T>(n);
        }
    }

    sal_Int32 SAL_CALL IMPL_RTL_STRNAME( toInt32 )( const IMPL_RTL_STRCODE* pStr,
                                                    sal_Int16 nRadix )
        SAL_THROW_EXTERN_C()
    {
        assert(pStr);
        return IMPL_RTL_STRNAME( toInt )<sal_Int32, sal_uInt32>(pStr, nRadix);
    }

    sal_Int64 SAL_CALL IMPL_RTL_STRNAME( toInt64 )( const IMPL_RTL_STRCODE* pStr,
                                                    sal_Int16 nRadix )
        SAL_THROW_EXTERN_C()
    {
        assert(pStr);
        return IMPL_RTL_STRNAME( toInt )<sal_Int64, sal_uInt64>(pStr, nRadix);
    }

    /* ----------------------------------------------------------------------- */
    namespace {
        template <typename T> inline T IMPL_RTL_STRNAME( toUInt )( const IMPL_RTL_STRCODE* pStr,
                                                                          sal_Int16 nRadix )
        {
            static_assert(!std::numeric_limits<T>::is_signed, "is not signed");
            assert( nRadix >= RTL_STR_MIN_RADIX && nRadix <= RTL_STR_MAX_RADIX );
            sal_Int16   nDigit;
            T           n = 0;

            if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
                nRadix = 10;

            /* Skip whitespaces */
            while ( *pStr && rtl_ImplIsWhitespace( IMPL_RTL_USTRCODE( *pStr ) ) )
                ++pStr;

            // skip optional explicit sign
            if ( *pStr == '+' )
                ++pStr;

            T nDiv = std::numeric_limits<T>::max() / nRadix;
            sal_Int16 nMod = std::numeric_limits<T>::max() % nRadix;
            while ( *pStr )
            {
                nDigit = rtl_ImplGetDigit( IMPL_RTL_USTRCODE( *pStr ), nRadix );
                if ( nDigit < 0 )
                    break;
                if( ( nMod < nDigit ? nDiv-1 : nDiv ) < n )
                    return 0;

                n *= nRadix;
                n += nDigit;

                ++pStr;
            }

            return n;
        }
    }

    sal_uInt32 SAL_CALL IMPL_RTL_STRNAME( toUInt32 )( const IMPL_RTL_STRCODE* pStr,
                                                      sal_Int16 nRadix )
        SAL_THROW_EXTERN_C()
    {
        assert(pStr);
        return IMPL_RTL_STRNAME( toUInt )<sal_uInt32>(pStr, nRadix);
    }

    sal_uInt64 SAL_CALL IMPL_RTL_STRNAME( toUInt64 )( const IMPL_RTL_STRCODE* pStr,
                                                      sal_Int16 nRadix )
        SAL_THROW_EXTERN_C()
    {
        assert(pStr);
        return IMPL_RTL_STRNAME( toUInt )<sal_uInt64>(pStr, nRadix);
    }

    /* ======================================================================= */
    /* Internal String-Class help functions                                    */
    /* ======================================================================= */

    IMPL_RTL_STRINGDATA* IMPL_RTL_STRINGNAME( ImplAlloc )( sal_Int32 nLen )
    {
        IMPL_RTL_STRINGDATA * pData
            = (sal::static_int_cast< sal_uInt32 >(nLen)
               <= ((SAL_MAX_UINT32 - sizeof (IMPL_RTL_STRINGDATA))
                   / sizeof (IMPL_RTL_STRCODE)))
            ? static_cast<IMPL_RTL_STRINGDATA *>(rtl_allocateString(
                sizeof (IMPL_RTL_STRINGDATA) + nLen * sizeof (IMPL_RTL_STRCODE)))
            : nullptr;
        if (pData != nullptr) {
            pData->refCount = 1;
            pData->length = nLen;
            pData->buffer[nLen] = 0;
        }
        return pData;
    }

    /* ----------------------------------------------------------------------- */

    static IMPL_RTL_STRCODE* IMPL_RTL_STRINGNAME( ImplNewCopy )( IMPL_RTL_STRINGDATA** ppThis,
                                                                 IMPL_RTL_STRINGDATA* pStr,
                                                                 sal_Int32 nCount )
    {
        assert(nCount >= 0);
        IMPL_RTL_STRCODE*       pDest;
        const IMPL_RTL_STRCODE* pSrc;
        IMPL_RTL_STRINGDATA*    pData = IMPL_RTL_STRINGNAME( ImplAlloc )( pStr->length );
        OSL_ASSERT(pData != nullptr);

        pDest   = pData->buffer;
        pSrc    = pStr->buffer;

        memcpy( pDest, pSrc, nCount * sizeof(IMPL_RTL_STRCODE));

        *ppThis = pData;

        RTL_LOG_STRING_NEW( pData );
        return pDest + nCount;
    }

    /* ======================================================================= */
    /* String-Class functions                                                  */
    /* ======================================================================= */

    namespace {

    void IMPL_RTL_ACQUIRE(IMPL_RTL_STRINGDATA * pThis)
    {
        if (!SAL_STRING_IS_STATIC (pThis))
            osl_atomic_increment( &((pThis)->refCount) );
    }

    }

    /* ----------------------------------------------------------------------- */

    void SAL_CALL IMPL_RTL_STRINGNAME( acquire )( IMPL_RTL_STRINGDATA* pThis )
        SAL_THROW_EXTERN_C()
    {
        IMPL_RTL_ACQUIRE( pThis );
    }

    /* ----------------------------------------------------------------------- */

    void SAL_CALL IMPL_RTL_STRINGNAME( release )( IMPL_RTL_STRINGDATA* pThis )
        SAL_THROW_EXTERN_C()
    {
        if (SAL_UNLIKELY(SAL_STRING_IS_STATIC (pThis)))
            return;

    /* OString doesn't have an 'intern' */
    #if IMPL_RTL_IS_USTRING
        if (SAL_STRING_IS_INTERN (pThis))
        {
            internRelease (pThis);
            return;
        }
    #endif

        if ( !osl_atomic_decrement( &(pThis->refCount) ) )
        {
            RTL_LOG_STRING_DELETE( pThis );
            rtl_freeString( pThis );
        }
    }

    /* ----------------------------------------------------------------------- */

    void SAL_CALL IMPL_RTL_STRINGNAME( new )( IMPL_RTL_STRINGDATA** ppThis )
        SAL_THROW_EXTERN_C()
    {
        assert(ppThis);
        if ( *ppThis)
            IMPL_RTL_STRINGNAME( release )( *ppThis );

        *ppThis = const_cast<IMPL_RTL_STRINGDATA*>(&IMPL_RTL_EMPTYSTRING);
    }

    /* ----------------------------------------------------------------------- */

    IMPL_RTL_STRINGDATA* SAL_CALL IMPL_RTL_STRINGNAME( alloc )( sal_Int32 nLen )
        SAL_THROW_EXTERN_C()
    {
        assert(nLen >= 0);
        return IMPL_RTL_STRINGNAME( ImplAlloc )( nLen );
    }

    /* ----------------------------------------------------------------------- */

    void SAL_CALL IMPL_RTL_STRINGNAME( new_WithLength )( IMPL_RTL_STRINGDATA** ppThis, sal_Int32 nLen )
        SAL_THROW_EXTERN_C()
    {
        assert(ppThis);
        assert(nLen >= 0);
        if ( nLen <= 0 )
            IMPL_RTL_STRINGNAME( new )( ppThis );
        else
        {
            if ( *ppThis)
                IMPL_RTL_STRINGNAME( release )( *ppThis );

            *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( nLen );
            OSL_ASSERT(*ppThis != nullptr);
            (*ppThis)->length   = 0;

            IMPL_RTL_STRCODE* pTempStr = (*ppThis)->buffer;
            memset(pTempStr, 0, nLen*sizeof(IMPL_RTL_STRCODE));
        }
    }

    /* ----------------------------------------------------------------------- */

    void SAL_CALL IMPL_RTL_STRINGNAME( newFromString )( IMPL_RTL_STRINGDATA** ppThis,
                                                        const IMPL_RTL_STRINGDATA* pStr )
        SAL_THROW_EXTERN_C()
    {
        assert(ppThis);
        assert(pStr);
        IMPL_RTL_STRINGDATA* pOrg;

        if ( !pStr->length )
        {
            IMPL_RTL_STRINGNAME( new )( ppThis );
            return;
        }

        pOrg = *ppThis;
        *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( pStr->length );
        OSL_ASSERT(*ppThis != nullptr);
        rtl_str_ImplCopy( (*ppThis)->buffer, pStr->buffer, pStr->length );
        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( newFromStr )( IMPL_RTL_STRINGDATA** ppThis,
                                                     const IMPL_RTL_STRCODE* pCharStr )
        SAL_THROW_EXTERN_C()
    {
        assert(ppThis);
        IMPL_RTL_STRINGDATA*    pOrg;
        sal_Int32               nLen;

        if ( pCharStr )
        {
            nLen = IMPL_RTL_STRNAME( getLength )( pCharStr );
        }
        else
            nLen = 0;

        if ( !nLen )
        {
            IMPL_RTL_STRINGNAME( new )( ppThis );
            return;
        }

        pOrg = *ppThis;
        *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( nLen );
        OSL_ASSERT(*ppThis != nullptr);
        rtl_str_ImplCopy( (*ppThis)->buffer, pCharStr, nLen );
        RTL_LOG_STRING_NEW( *ppThis );

        /* must be done last, if pCharStr == *ppThis */
        if ( pOrg )
            IMPL_RTL_STRINGNAME( release )( pOrg );
    }

    /* ----------------------------------------------------------------------- */

    void SAL_CALL IMPL_RTL_STRINGNAME( newFromStr_WithLength )( IMPL_RTL_STRINGDATA** ppThis,
                                                                const IMPL_RTL_STRCODE* pCharStr,
                                                                sal_Int32 nLen )
        SAL_THROW_EXTERN_C()
    {
        assert(ppThis);
        assert(nLen >= 0);
        IMPL_RTL_STRINGDATA* pOrg;

        if ( !pCharStr || (nLen <= 0) )
        {
            IMPL_RTL_STRINGNAME( new )( ppThis );
            return;
        }

        pOrg = *ppThis;
        *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( nLen );
        OSL_ASSERT(*ppThis != nullptr);
        rtl_str_ImplCopy( (*ppThis)->buffer, pCharStr, nLen );

        RTL_LOG_STRING_NEW( *ppThis );

        /* must be done last, if pCharStr == *ppThis */
        if ( pOrg )
            IMPL_RTL_STRINGNAME( release )( pOrg );
    }

    /* ----------------------------------------------------------------------- */

    void SAL_CALL IMPL_RTL_STRINGNAME( newFromSubString )( IMPL_RTL_STRINGDATA** ppThis,
                                                           const IMPL_RTL_STRINGDATA* pFrom,
                                                           sal_Int32 beginIndex,
                                                           sal_Int32 count )
        SAL_THROW_EXTERN_C()
    {
        assert(ppThis);
        if ( beginIndex == 0 && count == pFrom->length )
        {
            IMPL_RTL_STRINGNAME( assign )( ppThis, const_cast< IMPL_RTL_STRINGDATA * >( pFrom ) );
            return;
        }
        if ( count < 0 || beginIndex < 0 || beginIndex + count > pFrom->length )
        {
            assert(false); // fail fast at least in debug builds
            IMPL_RTL_STRINGNAME( newFromLiteral )( ppThis, "!!br0ken!!", 10, 0 );
            return;
        }

        IMPL_RTL_STRINGNAME( newFromStr_WithLength )( ppThis, pFrom->buffer + beginIndex, count );
    }

    /* ----------------------------------------------------------------------- */

    // Used when creating from string literals.
    void SAL_CALL IMPL_RTL_STRINGNAME( newFromLiteral )( IMPL_RTL_STRINGDATA** ppThis,
                                                         const sal_Char* pCharStr,
                                                         sal_Int32 nLen,
                                                         sal_Int32 allocExtra )
        SAL_THROW_EXTERN_C()
    {
        assert(ppThis);
        assert(nLen >= 0);
        assert(allocExtra >= 0);
        if ( nLen + allocExtra == 0 )
        {
            IMPL_RTL_STRINGNAME( new )( ppThis );
            return;
        }

        if ( *ppThis )
            IMPL_RTL_STRINGNAME( release )( *ppThis );

        *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( nLen + allocExtra );
        assert( *ppThis != nullptr );

        (*ppThis)->length = nLen; // fix after possible allocExtra != 0
        (*ppThis)->buffer[nLen] = 0;
        IMPL_RTL_STRCODE* pBuffer = (*ppThis)->buffer;
        sal_Int32 nCount;
        for( nCount = nLen; nCount > 0; --nCount )
        {
    #if IMPL_RTL_IS_USTRING
            assert(static_cast<unsigned char>(*pCharStr) < 0x80); // ASCII range
    #endif
            SAL_WARN_IF( (static_cast<unsigned char>(*pCharStr)) == '\0', "rtl.string",
                        "rtl_uString_newFromLiteral - Found embedded \\0 character" );

            *pBuffer = *pCharStr;
            pBuffer++;
            pCharStr++;
        }

        RTL_LOG_STRING_NEW( *ppThis );
    }

    /* ----------------------------------------------------------------------- */

    void SAL_CALL IMPL_RTL_STRINGNAME( assign )( IMPL_RTL_STRINGDATA** ppThis,
                                                 IMPL_RTL_STRINGDATA* pStr )
        SAL_THROW_EXTERN_C()
    {
        assert(ppThis);
        /* must be done at first, if pStr == *ppThis */
        IMPL_RTL_ACQUIRE( pStr );

        if ( *ppThis )
            IMPL_RTL_STRINGNAME( release )( *ppThis );

        *ppThis = pStr;
    }

    /* ----------------------------------------------------------------------- */

    sal_Int32 SAL_CALL IMPL_RTL_STRINGNAME( getLength )( const IMPL_RTL_STRINGDATA* pThis )
        SAL_THROW_EXTERN_C()
    {
        assert(pThis);
        return pThis->length;
    }

    /* ----------------------------------------------------------------------- */

    IMPL_RTL_STRCODE* SAL_CALL IMPL_RTL_STRINGNAME( getStr )( IMPL_RTL_STRINGDATA * pThis )
        SAL_THROW_EXTERN_C()
    {
        assert(pThis);
        return pThis->buffer;
    }

    /* ----------------------------------------------------------------------- */

    void SAL_CALL IMPL_RTL_STRINGNAME( newConcat )( IMPL_RTL_STRINGDATA** ppThis,
                                                    IMPL_RTL_STRINGDATA* pLeft,
                                                    IMPL_RTL_STRINGDATA* pRight )
        SAL_THROW_EXTERN_C()
    {
        assert(ppThis);
        IMPL_RTL_STRINGDATA* pOrg = *ppThis;

        /* Test for 0-Pointer - if not, change newReplaceStrAt! */
        if ( !pRight || !pRight->length )
        {
            *ppThis = pLeft;
            IMPL_RTL_ACQUIRE( pLeft );
        }
        else if ( !pLeft || !pLeft->length )
        {
            *ppThis = pRight;
            IMPL_RTL_ACQUIRE( pRight );
        }
        else if (pLeft->length
                 > std::numeric_limits<sal_Int32>::max() - pRight->length)
        {
            *ppThis = nullptr;
        }
        else
        {
            IMPL_RTL_STRINGDATA* pTempStr = IMPL_RTL_STRINGNAME( ImplAlloc )( pLeft->length + pRight->length );
            OSL_ASSERT(pTempStr != nullptr);
            *ppThis = pTempStr;
            if (*ppThis != nullptr) {
                rtl_str_ImplCopy( pTempStr->buffer, pLeft->buffer, pLeft->length );
                rtl_str_ImplCopy( pTempStr->buffer+pLeft->length, pRight->buffer, pRight->length );

                RTL_LOG_STRING_NEW( *ppThis );
            }
        }

        /* must be done last, if left or right == *ppThis */
        if ( pOrg )
            IMPL_RTL_STRINGNAME( release )( pOrg );
    }

    /* ----------------------------------------------------------------------- */

    void SAL_CALL IMPL_RTL_STRINGNAME( ensureCapacity )( IMPL_RTL_STRINGDATA** ppThis,
                                                         sal_Int32 size )
        SAL_THROW_EXTERN_C()
    {
        assert(ppThis);
        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 );

        IMPL_RTL_STRINGNAME( release )( pOrg );
    }

    /* ----------------------------------------------------------------------- */

    void SAL_CALL IMPL_RTL_STRINGNAME( newReplaceStrAt )( IMPL_RTL_STRINGDATA** ppThis,
                                                          IMPL_RTL_STRINGDATA* pStr,
                                                          sal_Int32 nIndex,
                                                          sal_Int32 nCount,
                                                          IMPL_RTL_STRINGDATA* pNewSubStr )
        SAL_THROW_EXTERN_C()
    {
        assert(ppThis);
        assert(nIndex >= 0 && nIndex <= pStr->length);
        assert(nCount >= 0);
        assert(nCount <= pStr->length - nIndex);
        /* Append? */
        if ( nIndex >= pStr->length )
        {
            /* newConcat test, if pNewSubStr is 0 */
            IMPL_RTL_STRINGNAME( newConcat )( ppThis, pStr, pNewSubStr );
            return;
        }

        /* negative index? */
        if ( nIndex < 0 )
        {
            nCount -= nIndex;
            nIndex = 0;
        }

        /* not more than the String length could be deleted */
        if ( nCount >= pStr->length-nIndex )
        {
            nCount = pStr->length-nIndex;

            /* Assign of NewSubStr? */
            if ( !nIndex && (nCount >= pStr->length) )
            {
                if ( !pNewSubStr )
                    IMPL_RTL_STRINGNAME( new )( ppThis );
                else
                    IMPL_RTL_STRINGNAME( assign )( ppThis, pNewSubStr );
                return;
            }
        }

        /* Assign of Str? */
        if ( !nCount && (!pNewSubStr || !pNewSubStr->length) )
        {
            IMPL_RTL_STRINGNAME( assign )( ppThis, pStr );
            return;
        }

        IMPL_RTL_STRINGDATA*    pOrg = *ppThis;
        IMPL_RTL_STRCODE*       pBuffer;
        sal_Int32               nNewLen;

        /* Calculate length of the new string */
        nNewLen = pStr->length-nCount;
        if ( pNewSubStr )
            nNewLen += pNewSubStr->length;

        /* Alloc New Buffer */
        *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( nNewLen );
        OSL_ASSERT(*ppThis != nullptr);
        pBuffer = (*ppThis)->buffer;
        if ( nIndex )
        {
            rtl_str_ImplCopy( pBuffer, pStr->buffer, nIndex );
            pBuffer += nIndex;
        }
        if ( pNewSubStr && pNewSubStr->length )
        {
            rtl_str_ImplCopy( pBuffer, pNewSubStr->buffer, pNewSubStr->length );
            pBuffer += pNewSubStr->length;
        }
        rtl_str_ImplCopy( pBuffer, pStr->buffer+nIndex+nCount, pStr->length-nIndex-nCount );

        RTL_LOG_STRING_NEW( *ppThis );
        /* must be done last, if pStr or pNewSubStr == *ppThis */
        if ( pOrg )
            IMPL_RTL_STRINGNAME( release )( pOrg );
    }

    /* ----------------------------------------------------------------------- */

    void SAL_CALL IMPL_RTL_STRINGNAME( newReplace )( IMPL_RTL_STRINGDATA** ppThis,
                                                     IMPL_RTL_STRINGDATA* pStr,
                                                     IMPL_RTL_STRCODE cOld,
                                                     IMPL_RTL_STRCODE cNew )
        SAL_THROW_EXTERN_C()
    {
        assert(ppThis);
        assert(pStr);
        IMPL_RTL_STRINGDATA*    pOrg        = *ppThis;
        bool                    bChanged    = false;
        sal_Int32               nLen        = pStr->length;
        const IMPL_RTL_STRCODE* pCharStr    = pStr->buffer;

        while ( nLen > 0 )
        {
            if ( *pCharStr == cOld )
            {
                /* Copy String */
                IMPL_RTL_STRCODE* pNewCharStr = IMPL_RTL_STRINGNAME( ImplNewCopy )( ppThis, pStr, pCharStr-pStr->buffer );

                /* replace/copy rest of the string */
                if ( pNewCharStr )
                {
                    *pNewCharStr = cNew;
                    pNewCharStr++;
                    pCharStr++;
                    nLen--;

                    while ( nLen > 0 )
                    {
                        if ( *pCharStr == cOld )
                            *pNewCharStr = cNew;
                        else
                            *pNewCharStr = *pCharStr;

                        pNewCharStr++;
                        pCharStr++;
                        nLen--;
                    }
                }

                bChanged = true;
                break;
            }

            pCharStr++;
            nLen--;
        }

        if ( !bChanged )
        {
            *ppThis = pStr;
            IMPL_RTL_ACQUIRE( pStr );
        }

        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( newToAsciiLowerCase )( IMPL_RTL_STRINGDATA** ppThis,
                                                              IMPL_RTL_STRINGDATA* pStr )
        SAL_THROW_EXTERN_C()
    {
        assert(ppThis);
        assert(pStr);
        IMPL_RTL_STRINGDATA*    pOrg        = *ppThis;
        bool                    bChanged    = false;
        sal_Int32               nLen        = pStr->length;
        const IMPL_RTL_STRCODE* pCharStr    = pStr->buffer;

        while ( nLen > 0 )
        {
            if ( rtl::isAsciiUpperCase(IMPL_RTL_USTRCODE(*pCharStr)) )
            {
                /* Copy String */
                IMPL_RTL_STRCODE* pNewCharStr = IMPL_RTL_STRINGNAME( ImplNewCopy )( ppThis, pStr, pCharStr-pStr->buffer );

                /* replace/copy rest of the string */
                if ( pNewCharStr )
                {
                    *pNewCharStr = rtl::toAsciiLowerCase(IMPL_RTL_USTRCODE(*pCharStr));
                    pNewCharStr++;
                    pCharStr++;
                    nLen--;

                    while ( nLen > 0 )
                    {
                        *pNewCharStr = rtl::toAsciiLowerCase(IMPL_RTL_USTRCODE(*pCharStr));

                        pNewCharStr++;
                        pCharStr++;
                        nLen--;
                    }
                }

                bChanged = true;
                break;
            }

            pCharStr++;
            nLen--;
        }

        if ( !bChanged )
        {
            *ppThis = pStr;
            IMPL_RTL_ACQUIRE( pStr );
        }

        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( newToAsciiUpperCase )( IMPL_RTL_STRINGDATA** ppThis,
                                                              IMPL_RTL_STRINGDATA* pStr )
        SAL_THROW_EXTERN_C()
    {
        assert(ppThis);
        assert(pStr);
        IMPL_RTL_STRINGDATA*    pOrg        = *ppThis;
        bool                    bChanged    = false;
        sal_Int32               nLen        = pStr->length;
        const IMPL_RTL_STRCODE* pCharStr    = pStr->buffer;

        while ( nLen > 0 )
        {
            if ( rtl::isAsciiLowerCase(IMPL_RTL_USTRCODE(*pCharStr)) )
            {
                /* Copy String */
                IMPL_RTL_STRCODE* pNewCharStr = IMPL_RTL_STRINGNAME( ImplNewCopy )( ppThis, pStr, pCharStr-pStr->buffer );

                /* replace/copy rest of the string */
                if ( pNewCharStr )
                {
                    *pNewCharStr = rtl::toAsciiUpperCase(IMPL_RTL_USTRCODE(*pCharStr));
                    pNewCharStr++;
                    pCharStr++;
                    nLen--;

                    while ( nLen > 0 )
                    {
                        *pNewCharStr = rtl::toAsciiUpperCase(IMPL_RTL_USTRCODE(*pCharStr));

                        pNewCharStr++;
                        pCharStr++;
                        nLen--;
                    }
                }

                bChanged = true;
                break;
            }

            pCharStr++;
            nLen--;
        }

        if ( !bChanged )
        {
            *ppThis = pStr;
            IMPL_RTL_ACQUIRE( pStr );
        }

        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( newTrim )( IMPL_RTL_STRINGDATA** ppThis,
                                                  IMPL_RTL_STRINGDATA* pStr )
        SAL_THROW_EXTERN_C()
    {
        assert(ppThis);
        assert(pStr);
        IMPL_RTL_STRINGDATA*    pOrg        = *ppThis;
        const IMPL_RTL_STRCODE* pCharStr    = pStr->buffer;
        sal_Int32               nPreSpaces  = 0;
        sal_Int32               nPostSpaces = 0;
        sal_Int32               nLen        = pStr->length;
        sal_Int32               nIndex      = nLen-1;

        while ( (nPreSpaces < nLen) && rtl_ImplIsWhitespace( IMPL_RTL_USTRCODE(*(pCharStr+nPreSpaces)) ) )
            nPreSpaces++;

        while ( (nIndex > nPreSpaces) && rtl_ImplIsWhitespace( IMPL_RTL_USTRCODE(*(pCharStr+nIndex)) ) )
        {
            nPostSpaces++;
            nIndex--;
        }

        if ( !nPreSpaces && !nPostSpaces )
        {
            *ppThis = pStr;
            IMPL_RTL_ACQUIRE( pStr );
        }
        else
        {
            nLen -= nPostSpaces+nPreSpaces;
            *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( nLen );
            assert(*ppThis);
            rtl_str_ImplCopy( (*ppThis)->buffer, pStr->buffer+nPreSpaces, nLen );
        }

        RTL_LOG_STRING_NEW( *ppThis );
        /* must be done last, if pStr == *ppThis */
        if ( pOrg )
            IMPL_RTL_STRINGNAME( release )( pOrg );
    }

    /* ----------------------------------------------------------------------- */

    sal_Int32 SAL_CALL IMPL_RTL_STRINGNAME( getToken )( IMPL_RTL_STRINGDATA** ppThis,
                                                        IMPL_RTL_STRINGDATA* pStr,
                                                        sal_Int32 nToken,
                                                        IMPL_RTL_STRCODE cTok,
                                                        sal_Int32 nIndex )
        SAL_THROW_EXTERN_C()
    {
        assert(ppThis);
        assert(pStr);
        const IMPL_RTL_STRCODE* pCharStr        = pStr->buffer;
        const IMPL_RTL_STRCODE* pCharStrStart;
        const IMPL_RTL_STRCODE* pOrgCharStr;
        sal_Int32               nLen            = pStr->length-nIndex;
        sal_Int32               nTokCount       = 0;

        // Set ppThis to an empty string and return -1 if either nToken or nIndex is
        // negative:
        if (nIndex < 0)
            nToken = -1;

        pCharStr += nIndex;
        pOrgCharStr = pCharStr;
        pCharStrStart = pCharStr;
        while ( nLen > 0 )
        {
            if ( *pCharStr == cTok )
            {
                nTokCount++;

                if ( nTokCount == nToken )
                    pCharStrStart = pCharStr+1;
                else
                {
                    if ( nTokCount > nToken )
                        break;
                }
            }

            pCharStr++;
            nLen--;
        }

        if ( (nToken < 0) || (nTokCount < nToken) || (pCharStr == pCharStrStart) )
        {
            IMPL_RTL_STRINGNAME( new )( ppThis );
            if( (nToken < 0) || (nTokCount < nToken ) )
                return -1;
            else if( nLen > 0 )
                return nIndex+(pCharStr-pOrgCharStr)+1;
            else return -1;
        }
        else
        {
            IMPL_RTL_STRINGNAME( newFromStr_WithLength )( ppThis, pCharStrStart, pCharStr-pCharStrStart );
            if ( nLen )
                return nIndex+(pCharStr-pOrgCharStr)+1;
            else
                return -1;
        }
    }

    /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

↑ V547 Expression 'pNewCharStr' is always true.

↑ V1004 The 'pCharStr' pointer was used unsafely after it was verified against nullptr. Check lines: 1309, 1325.

↑ V547 Expression 'pNewCharStr' is always true.

↑ V547 Expression 'pNewCharStr' is always true.