add OString::getTokenView (tdf#42374 related)

small improvement to PDF import

no need to construct temporary string objects when we are just to
going to convert them into int/double.
So use a view and convert the data through the view.

Change-Id: I824fe88bf17142b48fe6032e10c0f3a111927e96
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/115616
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
diff --git a/include/rtl/string.h b/include/rtl/string.h
index bfbb450..c0f7242 100644
--- a/include/rtl/string.h
+++ b/include/rtl/string.h
@@ -747,6 +747,31 @@ SAL_DLLPUBLIC sal_Bool SAL_CALL rtl_str_toBoolean(
SAL_DLLPUBLIC sal_Int32 SAL_CALL rtl_str_toInt32(
        const char * str, sal_Int16 radix ) SAL_THROW_EXTERN_C();

/** Interpret a string as an integer.

    This function cannot be used for language-specific conversion.  The string
    must be null-terminated.

    @param str
    a null-terminated string.

    @param radix
    the radix.  Must be between RTL_STR_MIN_RADIX (2) and RTL_STR_MAX_RADIX
    (36), inclusive.

    @param len
    the length of the character array.

    @return
    the integer value represented by the string, or 0 if the string does not
    represent an integer.

    @since LibreOffice 7.2
    @internal
 */
SAL_DLLPUBLIC sal_Int32 SAL_CALL rtl_str_toInt32_WithLength(
        const char * str, sal_Int16 radix, sal_Int32 nStrLength ) SAL_THROW_EXTERN_C();

/** Interpret a string as an unsigned integer.

    This function cannot be used for language-specific conversion.  The string
@@ -1309,6 +1334,59 @@ SAL_DLLPUBLIC void SAL_CALL rtl_string_newTrim(
SAL_DLLPUBLIC sal_Int32 SAL_CALL rtl_string_getToken(
        rtl_String ** newStr , rtl_String * str, sal_Int32 token, char cTok, sal_Int32 idx ) SAL_THROW_EXTERN_C();

/** Create a new string by extracting a single token from another string.

    Starting at index, the token's next token is searched for.  If there is no
    such token, the result is an empty string.  Otherwise, all characters from
    the start of that token and up to, but not including the next occurrence
    of cTok make up the resulting token.  The return value is the position of
    the next token, or -1 if no more tokens follow.

    Example code could look like
      rtl_String * pToken = NULL;
      sal_Int32 nIndex = 0;
      do
      {
          ...
          nIndex = rtl_string_getToken(&pToken, pStr, 0, ';', nIndex);
          ...
      }
      while (nIndex >= 0);

    The new string does not necessarily have a reference count of 1, so it
    must not be modified without checking the reference count.  This function
    does not handle out-of-memory conditions.

    @param ppViewStr
    pointer to the start of the token.  The pointed-to data must be null or a valid
    string.  If either token or index is negative, nullptr is stored in
    newStr (and -1 is returned).

    @param pViewLength
    length of the token.

    @param str
    a valid string.

    @param token
    the number of the token to return, starting at index.

    @param cTok
    the character that separates the tokens.

    @param idx
    the position at which searching for the token starts.  Must not be greater
    than the length of str.

    @return
    the index of the next token, or -1 if no more tokens follow.

    @since LibreOffice 7.2
    @internal
 */
SAL_DLLPUBLIC sal_Int32 SAL_CALL rtl_string_getTokenView(
    const char ** ppViewStr , sal_Int32* pViewLength, rtl_String * str, sal_Int32 token, char cTok, sal_Int32 idx ) SAL_THROW_EXTERN_C();

/* ======================================================================= */

/** Supply an ASCII string literal together with its length.
diff --git a/include/rtl/string.hxx b/include/rtl/string.hxx
index f80dd74..c16519f 100644
--- a/include/rtl/string.hxx
+++ b/include/rtl/string.hxx
@@ -1765,6 +1765,15 @@ public:
        index = rtl_string_getToken( &pNew, pData, token, cTok, index );
        return OString( pNew, SAL_NO_ACQUIRE );
    }
#ifdef LIBO_INTERNAL_ONLY // "RTL_FAST_STRING"
    std::string_view getTokenView( sal_Int32 token, char cTok, sal_Int32& index ) const
    {
        const char* pViewData = nullptr;
        sal_Int32 nViewLength = 0;
        index = rtl_string_getTokenView( &pViewData, &nViewLength, pData, token, cTok, index );
        return std::string_view(pViewData, nViewLength);
    }
#endif

    /**
      Returns a token from the string.
diff --git a/sal/rtl/string.cxx b/sal/rtl/string.cxx
index 94be8029..2eb4654 100644
--- a/sal/rtl/string.cxx
+++ b/sal/rtl/string.cxx
@@ -559,6 +559,11 @@ sal_Int32 SAL_CALL rtl_str_toInt32(const char* pStr, sal_Int16 nRadix) SAL_THROW
    return rtl::str::toInt32(pStr, nRadix);
}

sal_Int32 SAL_CALL rtl_str_toInt32_WithLength(const char* pStr, sal_Int16 nRadix, sal_Int32 nStrLength) SAL_THROW_EXTERN_C()
{
    return rtl::str::toInt32_WithLength(pStr, nRadix, nStrLength);
}

sal_Int64 SAL_CALL rtl_str_toInt64(const char* pStr, sal_Int16 nRadix) SAL_THROW_EXTERN_C()
{
    return rtl::str::toInt64(pStr, nRadix);
@@ -700,4 +705,9 @@ sal_Int32 SAL_CALL rtl_string_getToken(rtl_String** ppThis, rtl_String* pStr, sa
    return rtl::str::getToken(ppThis, pStr, nToken, cTok, nIndex);
}

sal_Int32 SAL_CALL rtl_string_getTokenView(const char ** ppViewStr , sal_Int32* pViewLength, rtl_String* pStr, sal_Int32 nToken,
                                       char cTok, sal_Int32 nIndex) SAL_THROW_EXTERN_C()
{
    return rtl::str::getTokenView(ppViewStr, pViewLength, pStr, nToken, cTok, nIndex);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/rtl/strtmpl.hxx b/sal/rtl/strtmpl.hxx
index fdb26fd..a25e821 100644
--- a/sal/rtl/strtmpl.hxx
+++ b/sal/rtl/strtmpl.hxx
@@ -914,6 +914,15 @@ sal_Int32 toInt32                             ( const IMPL_RTL_STRCODE* pStr,
}

template <typename IMPL_RTL_STRCODE>
sal_Int32 toInt32_WithLength                  ( const IMPL_RTL_STRCODE* pStr,
                                                sal_Int16 nRadix,
                                                sal_Int32 nStrLength )
{
    assert(pStr);
    return toInt_WithLength<sal_Int32, sal_uInt32>(pStr, nRadix, nStrLength);
}

template <typename IMPL_RTL_STRCODE>
sal_Int64 toInt64                             ( const IMPL_RTL_STRCODE* pStr,
                                                sal_Int16 nRadix )
{
@@ -1731,6 +1740,73 @@ sal_Int32 getToken                                ( IMPL_RTL_STRINGDATA** ppThis
            return -1;
    }
}


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

template <typename IMPL_RTL_STRINGDATA>
sal_Int32 getTokenView                            ( const char ** ppViewStr,
                                                    sal_Int32 * pViewLength,
                                                    IMPL_RTL_STRINGDATA* pStr,
                                                    sal_Int32 nToken,
                                                    STRCODE<IMPL_RTL_STRINGDATA> cTok,
                                                    sal_Int32 nIndex )
{
    assert(ppViewStr);
    assert(pViewLength);
    assert(pStr);
    const auto*             pCharStr        = pStr->buffer;
    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;
    const auto* pOrgCharStr = pCharStr;
    const auto* 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) )
    {
        if( (nToken < 0) || (nTokCount < nToken) )
            return -1;
        else if( nLen > 0 )
            return nIndex+(pCharStr-pOrgCharStr)+1;
        else return -1;
    }
    else
    {
        *ppViewStr = pCharStrStart;
        *pViewLength = pCharStr-pCharStrStart;
        if ( nLen )
            return nIndex+(pCharStr-pOrgCharStr)+1;
        else
            return -1;
    }
}



}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/util/sal.map b/sal/util/sal.map
index 49efb2a..2f74ceb 100644
--- a/sal/util/sal.map
+++ b/sal/util/sal.map
@@ -753,7 +753,13 @@ PRIVATE_1.6 { # LibreOffice 6.4
PRIVATE_1.7 { # LibreOffice 7.1
    global:
        rtl_uString_newReplaceAllFromIndexUtf16LUtf16L;
} PRIVATE_1.5;
} PRIVATE_1.6;

PRIVATE_1.8 { # LibreOffice 7.2
    global:
        rtl_string_getTokenView;
        rtl_str_toInt32_WithLength;
} PRIVATE_1.7;

PRIVATE_textenc.1 { # LibreOffice 3.6
    global:
diff --git a/sdext/source/pdfimport/wrapper/wrapper.cxx b/sdext/source/pdfimport/wrapper/wrapper.cxx
index 1b9a6c1..953d437 100644
--- a/sdext/source/pdfimport/wrapper/wrapper.cxx
+++ b/sdext/source/pdfimport/wrapper/wrapper.cxx
@@ -151,7 +151,7 @@ class Parser
    sal_Int32                                    m_nCharIndex;


    OString readNextToken();
    std::string_view readNextToken();
    void           readInt32( sal_Int32& o_Value );
    sal_Int32      readInt32();
    void           readInt64( sal_Int64& o_Value );
@@ -244,35 +244,42 @@ OString lcl_unescapeLineFeeds(const OString& i_rStr)
    return aResult;
}

OString Parser::readNextToken()
std::string_view Parser::readNextToken()
{
    OSL_PRECOND(m_nCharIndex!=-1,"insufficient input");
    return m_aLine.getToken(m_nNextToken,' ',m_nCharIndex);
    return m_aLine.getTokenView(m_nNextToken,' ',m_nCharIndex);
}

void Parser::readInt32( sal_Int32& o_Value )
{
    o_Value = readNextToken().toInt32();
    std::string_view tok = readNextToken();
    o_Value = rtl_str_toInt32_WithLength(tok.data(), 10, tok.size());
}

sal_Int32 Parser::readInt32()
{
    return readNextToken().toInt32();
    std::string_view tok = readNextToken();
    return rtl_str_toInt32_WithLength(tok.data(), 10, tok.size());
}

void Parser::readInt64( sal_Int64& o_Value )
{
    o_Value = readNextToken().toInt64();
    std::string_view tok = readNextToken();
    o_Value = rtl_str_toInt64_WithLength(tok.data(), 10, tok.size());
}

void Parser::readDouble( double& o_Value )
{
    o_Value = readNextToken().toDouble();
    std::string_view tok = readNextToken();
    o_Value = rtl_math_stringToDouble(tok.data(), tok.data() + tok.size(), '.', 0,
                                   nullptr, nullptr);
}

double Parser::readDouble()
{
    return readNextToken().toDouble();
    std::string_view tok = readNextToken();
    return rtl_math_stringToDouble(tok.data(), tok.data() + tok.size(), '.', 0,
                                   nullptr, nullptr);
}

void Parser::readBinaryData( uno::Sequence<sal_Int8>& rBuf )
@@ -679,7 +686,7 @@ void Parser::readFont()

uno::Sequence<beans::PropertyValue> Parser::readImageImpl()
{
    OString aToken = readNextToken();
    std::string_view aToken = readNextToken();
    const sal_Int32 nImageSize( readInt32() );

    OUString           aFileName;
@@ -809,9 +816,9 @@ void Parser::parseLine( const OString& rLine )
    OSL_PRECOND( m_xContext.is(), "Invalid service factory" );

    m_nNextToken = 0; m_nCharIndex = 0; m_aLine = rLine;
    const OString& rCmd = readNextToken();
    const hash_entry* pEntry = PdfKeywordHash::in_word_set( rCmd.getStr(),
                                                            rCmd.getLength() );
    const std::string_view rCmd = readNextToken();
    const hash_entry* pEntry = PdfKeywordHash::in_word_set( rCmd.data(),
                                                            rCmd.size() );
    OSL_ASSERT(pEntry);
    switch( pEntry->eKey )
    {