basic/source/sbx/sbxconv.hxx |    4 -
 basic/source/sbx/sbxexec.cxx |    2 
 basic/source/sbx/sbxscan.cxx |  150 ++++++++++++++++++-------------------------
 include/basic/sbxvar.hxx     |    2 
 4 files changed, 70 insertions(+), 88 deletions(-)

New commits:
commit a3b43e95baefd03f257765d9153b9827c337b90f
Author:     Mike Kaganski <[email protected]>
AuthorDate: Mon Dec 23 14:26:20 2024 +0100
Commit:     Mike Kaganski <[email protected]>
CommitDate: Mon Dec 23 20:36:11 2024 +0100

    Simplify ImpScan
    
    Change-Id: I8928d3c7f0fc6884a75c05e77908df7f482c9e44
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/179246
    Reviewed-by: Mike Kaganski <[email protected]>
    Tested-by: Jenkins

diff --git a/basic/source/sbx/sbxconv.hxx b/basic/source/sbx/sbxconv.hxx
index f32e5fc890d7..1ddc6f73c847 100644
--- a/basic/source/sbx/sbxconv.hxx
+++ b/basic/source/sbx/sbxconv.hxx
@@ -63,11 +63,11 @@ inline auto ImpDoubleToSalInt64(double d)
 // SBXSCAN.CXX
 extern void ImpCvtNum( double nNum, short nPrec, OUString& rRes, bool 
bCoreString=false );
 extern ErrCode ImpScan
-    ( const OUString& rSrc, double& nVal, SbxDataType& rType, sal_uInt16* pLen,
+    ( std::u16string_view rSrc, double& nVal, SbxDataType& rType, sal_uInt16* 
pLen,
       bool bOnlyIntntl );
 // A version that uses defaults / compatibility settings for bOnlyIntntl
 extern ErrCode ImpScan
-    ( const OUString& rSrc, double& nVal, SbxDataType& rType, sal_uInt16* pLen 
);
+    ( std::u16string_view rSrc, double& nVal, SbxDataType& rType, sal_uInt16* 
pLen );
 
 // with advanced evaluation (International, "TRUE"/"FALSE")
 extern bool ImpConvStringExt( OUString& rSrc, SbxDataType eTargetType );
diff --git a/basic/source/sbx/sbxexec.cxx b/basic/source/sbx/sbxexec.cxx
index af7d12c00651..8c88099efbee 100644
--- a/basic/source/sbx/sbxexec.cxx
+++ b/basic/source/sbx/sbxexec.cxx
@@ -130,7 +130,7 @@ static SbxVariableRef Operand
     {
         // A number could be scanned in directly!
         sal_uInt16 nLen;
-        if( !refVar->Scan( OUString( p ), &nLen ) )
+        if (!refVar->Scan(p, &nLen))
         {
             refVar.clear();
         }
diff --git a/basic/source/sbx/sbxscan.cxx b/basic/source/sbx/sbxscan.cxx
index d3a605cd112b..5619a59d548f 100644
--- a/basic/source/sbx/sbxscan.cxx
+++ b/basic/source/sbx/sbxscan.cxx
@@ -70,7 +70,7 @@ static bool ImpStrChr( std::u16string_view str, sal_Unicode c 
) { return str.fin
 // but exponent may also be a D, so data type is SbxDOUBLE
 // conversion error if data type is fixed and it doesn't fit
 
-ErrCode ImpScan( const OUString& rWSrc, double& nVal, SbxDataType& rType,
+ErrCode ImpScan( std::u16string_view rWSrc, double& nVal, SbxDataType& rType,
                   sal_uInt16* pLen, bool bOnlyIntntl )
 {
     sal_Unicode cDecSep, cGrpSep, cDecSepAlt;
@@ -88,30 +88,27 @@ ErrCode ImpScan( const OUString& rWSrc, double& nVal, 
SbxDataType& rType,
         cDecSepAlt = 0;
     }
 
-    const sal_Unicode* const pStart = rWSrc.getStr();
-    const sal_Unicode* p = pStart;
-    OUStringBuffer aBuf( rWSrc.getLength());
-    bool bRes = true;
+    auto const pStart = rWSrc.begin();
+    auto p = pStart;
     bool bMinus = false;
     nVal = 0;
     SbxDataType eScanType = SbxSINGLE;
-    while( *p == ' ' || *p == '        ' )
+    while (p != rWSrc.end() && (*p == ' ' || *p == '   '))
         p++;
-    if (*p == '+')
+    if (p != rWSrc.end() && *p == '+')
         p++;
-    else if( *p == '-' )
+    else if (p != rWSrc.end() && *p == '-')
     {
         p++;
         bMinus = true;
     }
-    if (rtl::isAsciiDigit(*p)
-        || ((*p == cDecSep || (cGrpSep && *p == cGrpSep) || (cDecSepAlt && *p 
== cDecSepAlt))
-            && rtl::isAsciiDigit(*(p + 1))))
+    if (p != rWSrc.end()
+        && (rtl::isAsciiDigit(*p)
+            || ((*p == cDecSep || (cGrpSep && *p == cGrpSep) || (cDecSepAlt && 
*p == cDecSepAlt))
+                && p + 1 != rWSrc.end() && rtl::isAsciiDigit(*(p + 1)))))
     {
-        // tdf#118442: Whitespace and minus are skipped; store the position to 
calculate index
-        const sal_Unicode* const pDigitsStart = p;
-        short exp = 0;
-        short decsep = 0;
+        bool exp = false;
+        bool decsep = false;
         short ndig = 0;
         short ncdig = 0;    // number of digits after decimal point
         OUStringBuffer aSearchStr("0123456789DEde" + OUStringChar(cDecSep));
@@ -119,61 +116,59 @@ ErrCode ImpScan( const OUString& rWSrc, double& nVal, 
SbxDataType& rType,
             aSearchStr.append(cDecSepAlt);
         if (cGrpSep)
             aSearchStr.append(cGrpSep);
-        const OUString pSearchStr = aSearchStr.makeStringAndClear();
-        static constexpr OUStringLiteral pDdEe = u"DdEe";
-        while( ImpStrChr( pSearchStr, *p ) )
+        OUStringBuffer aBuf(rWSrc.end() - p);
+        for (; p != rWSrc.end() && ImpStrChr(aSearchStr, *p); ++p)
         {
-            aBuf.append( *p );
-            if (cGrpSep && *p == cGrpSep)
+            if (rtl::isAsciiDigit(*p))
             {
-                p++;
-                continue;
+                aBuf.append(*p);
+                if (!exp)
+                {
+                    ndig++;
+                    if (decsep)
+                        ncdig++;
+                }
             }
-            if (*p == cDecSep || (cDecSepAlt && *p == cDecSepAlt))
+            else if (cGrpSep && *p == cGrpSep)
             {
+                aBuf.append(*p);
+            }
+            else if (*p == cDecSep || (cDecSepAlt && *p == cDecSepAlt))
+            {
+                if (decsep)
+                    return ERRCODE_BASIC_CONVERSION;
+                decsep = true;
+
                 // Use the separator that is passed to stringToDouble()
-                aBuf[p - pDigitsStart] = cDecSep;
-                p++;
-                if( ++decsep > 1 )
-                    continue;
+                aBuf.append(cDecSep);
             }
-            else if( ImpStrChr( pDdEe, *p ) )
+            else // DdEe
             {
-                if( ++exp > 1 )
-                {
-                    p++;
-                    continue;
-                }
+                if (exp)
+                    return ERRCODE_BASIC_CONVERSION;
+                exp = true;
+
                 if( *p == 'D' || *p == 'd' )
                     eScanType = SbxDOUBLE;
-                aBuf[p - pDigitsStart] = 'E';
-                p++;
-                if (*p == '+')
-                    ++p;
-                else if (*p == '-')
+                aBuf.append('E');
+                if (auto pNext = p + 1; pNext != rWSrc.end())
                 {
-                    aBuf.append('-');
-                    ++p;
+                    if (*pNext == '+')
+                        ++p;
+                    else if (*pNext == '-')
+                    {
+                        aBuf.append('-');
+                        ++p;
+                    }
                 }
             }
-            else
-            {
-                p++;
-                if( decsep && !exp )
-                    ncdig++;
-            }
-            if( !exp )
-                ndig++;
         }
 
-        if( decsep > 1 || exp > 1 )
-            bRes = false;
-
         rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok;
         sal_Int32 nParseEnd = 0;
         nVal = rtl::math::stringToDouble(aBuf, cDecSep, cGrpSep, &eStatus, 
&nParseEnd);
         if( eStatus != rtl_math_ConversionStatus_Ok || nParseEnd != 
aBuf.getLength() )
-            bRes = false;
+            return ERRCODE_BASIC_CONVERSION;
 
         if( !decsep && !exp )
         {
@@ -183,29 +178,29 @@ ErrCode ImpScan( const OUString& rWSrc, double& nVal, 
SbxDataType& rType,
                 eScanType = SbxLONG;
         }
 
-        ndig = ndig - decsep;
         // too many numbers for SINGLE?
         if( ndig > 15 || ncdig > 6 )
             eScanType = SbxDOUBLE;
 
         // type detection?
-        static constexpr OUStringLiteral pTypes = u"%!&#";
-        if( ImpStrChr( pTypes, *p ) )
+        static constexpr std::u16string_view pTypes = u"%!&#";
+        if (p != rWSrc.end() && ImpStrChr(pTypes, *p))
             p++;
     }
     // hex/octal number? read in and convert:
-    else if( *p == '&' )
+    else if (p != rWSrc.end() && *p == '&')
     {
-        p++;
+        if (++p == rWSrc.end())
+            return ERRCODE_BASIC_CONVERSION;
         eScanType = SbxLONG;
-        OUString aCmp( u"0123456789ABCDEF"_ustr );
+        auto isValidDigit = rtl::isAsciiHexDigit<sal_Unicode>;
         char base = 16;
         char ndig = 8;
         switch( *p++ )
         {
             case 'O':
             case 'o':
-                aCmp = "01234567";
+                isValidDigit = rtl::isAsciiOctalDigit<sal_Unicode>;
                 base = 8;
                 ndig = 11;
                 break;
@@ -213,29 +208,18 @@ ErrCode ImpScan( const OUString& rWSrc, double& nVal, 
SbxDataType& rType,
             case 'h':
                 break;
             default :
-                bRes = false;
+                return ERRCODE_BASIC_CONVERSION;
         }
-        while( rtl::isAsciiAlphanumeric( *p ) )    /* XXX: really munge all 
alnum also when error? */
+        const auto pDigitsStart = p;
+        for (; p != rWSrc.end() && rtl::isAsciiAlphanumeric(*p); ++p)
         {
-            sal_Unicode ch = rtl::toAsciiUpperCase(*p);
-            if( ImpStrChr( aCmp, ch ) )
-                aBuf.append( ch );
-            else
-                bRes = false;
-            p++;
+            if (!isValidDigit(*p))
+                return ERRCODE_BASIC_CONVERSION;
         }
-        OUString aBufStr( aBuf.makeStringAndClear());
-        sal_Int32 l = 0;
-        for( const sal_Unicode* q = aBufStr.getStr(); bRes && *q; q++ )
-        {
-            int i = *q - '0';
-            if( i > 9 )
-                i -= 7;     // 'A'-'0' = 17 => 10, ...
-            l = ( l * base ) + i;
-            if( !ndig-- )
-                bRes = false;
-        }
-        if( *p == '&' )
+        if (p - pDigitsStart > ndig)
+                return ERRCODE_BASIC_CONVERSION;
+        sal_Int32 l = o3tl::toInt32(rWSrc.substr(pDigitsStart - pStart, p - 
pDigitsStart), base);
+        if (p != rWSrc.end() && *p == '&')
             p++;
         nVal = static_cast<double>(l);
         if( l >= SbxMININT && l <= SbxMAXINT )
@@ -248,19 +232,17 @@ ErrCode ImpScan( const OUString& rWSrc, double& nVal, 
SbxDataType& rType,
     }
 #endif
     // tdf#146672 - skip whitespaces and tabs at the end of the scanned string
-    while (*p == ' ' || *p == '        ')
+    while (p != rWSrc.end() && (*p == ' ' || *p == '   '))
         p++;
     if( pLen )
         *pLen = static_cast<sal_uInt16>( p - pStart );
-    if( !bRes )
-        return ERRCODE_BASIC_CONVERSION;
     if( bMinus )
         nVal = -nVal;
     rType = eScanType;
     return ERRCODE_NONE;
 }
 
-ErrCode ImpScan(const OUString& rSrc, double& nVal, SbxDataType& rType, 
sal_uInt16* pLen)
+ErrCode ImpScan(std::u16string_view rSrc, double& nVal, SbxDataType& rType, 
sal_uInt16* pLen)
 {
     using namespace officecfg::Office::Scripting;
     static const bool bEnv = std::getenv("LIBREOFFICE6FLOATINGPOINTMODE") != 
nullptr;
@@ -397,7 +379,7 @@ static void printfmtstr(std::u16string_view rStr, OUString& 
rRes, std::u16string
 }
 
 
-bool SbxValue::Scan( const OUString& rSrc, sal_uInt16* pLen )
+bool SbxValue::Scan(std::u16string_view rSrc, sal_uInt16* pLen)
 {
     ErrCode eRes = ERRCODE_NONE;
     if( !CanWrite() )
diff --git a/include/basic/sbxvar.hxx b/include/basic/sbxvar.hxx
index b6aed459ca6c..29976d1fe7f6 100644
--- a/include/basic/sbxvar.hxx
+++ b/include/basic/sbxvar.hxx
@@ -189,7 +189,7 @@ public:
     SAL_DLLPRIVATE bool Convert( SbxDataType );
     bool Compute( SbxOperator, const SbxValue& );
     bool Compare( SbxOperator, const SbxValue& ) const;
-    SAL_DLLPRIVATE bool Scan( const OUString&, sal_uInt16* );
+    SAL_DLLPRIVATE bool Scan( std::u16string_view, sal_uInt16* );
     SAL_DLLPRIVATE void Format( OUString&, const OUString* = nullptr ) const;
 
     // The following operators are defined for easier handling.

Reply via email to