basic/source/runtime/methods.cxx |  922 ++++++++++++++++++---------------------
 1 file changed, 443 insertions(+), 479 deletions(-)

New commits:
commit 541c72dbadb72219767d0e0fb4c4f6ebe4c9b07c
Author:     Jim Chen <jim.chen.1...@gmail.com>
AuthorDate: Wed Jul 9 18:53:59 2025 -0700
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Tue Sep 2 13:17:01 2025 +0200

    tdf#147132 - Flatten 'Basic' function implementations
    
    Flattens function implementations by returning early when an argument
    check fails rather than using if/else blocks.
    
    Change-Id: I5adad466e41ac95ad5bde43d758babf5932ec304
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187606
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Tested-by: Jenkins

diff --git a/basic/source/runtime/methods.cxx b/basic/source/runtime/methods.cxx
index f6fefdfb760c..9a2199d0d31c 100644
--- a/basic/source/runtime/methods.cxx
+++ b/basic/source/runtime/methods.cxx
@@ -1737,87 +1737,74 @@ void SbRtl_CDateToIso(StarBASIC *, SbxArray & rPar, 
bool)
 // And even YYMMDD for compatibility, sigh...
 void SbRtl_CDateFromIso(StarBASIC *, SbxArray & rPar, bool)
 {
-    if (rPar.Count() == 2)
-    {
-        do
-        {
-            OUString aStr = rPar.Get(1)->GetOUString();
-            if (aStr.isEmpty())
-                break;
-
-            // Valid formats are
-            // YYYYMMDD    -YYYMMDD     YYYYYMMDD    -YYYYYMMDD    YYMMDD
-            // YYYY-MM-DD  -YYYY-MM-DD  YYYYY-MM-DD  -YYYYY-MM-DD
-
-            sal_Int32 nSign = 1;
-            if (aStr[0] == '-')
-            {
-                nSign = -1;
-                aStr = aStr.copy(1);
-            }
-            const sal_Int32 nLen = aStr.getLength();
-
-            // Signed YYMMDD two digit year is invalid.
-            if (nLen == 6 && nSign == -1)
-                break;
-
-            // Now valid
-            // YYYYMMDD    YYYYYMMDD    YYMMDD
-            // YYYY-MM-DD  YYYYY-MM-DD
-            if (nLen != 6 && (nLen < 8 || 11 < nLen))
-                break;
-
-            bool bUseTwoDigitYear = false;
-            std::u16string_view aYearStr, aMonthStr, aDayStr;
-            if (nLen == 6 || nLen == 8 || nLen == 9)
-            {
-                // ((Y)YY)YYMMDD
-                if (!comphelper::string::isdigitAsciiString(aStr))
-                    break;
+    if (rPar.Count() != 2)
+        return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+    OUString aStr = rPar.Get(1)->GetOUString();
+    if (aStr.isEmpty())
+        return SbxBase::SetError( ERRCODE_BASIC_BAD_PARAMETER );
 
-                const sal_Int32 nMonthPos = (nLen == 8 ? 4 : (nLen == 6 ? 2 : 
5));
-                if (nMonthPos == 2)
-                    bUseTwoDigitYear = true;
-                aYearStr  = aStr.subView( 0, nMonthPos );
-                aMonthStr = aStr.subView( nMonthPos, 2 );
-                aDayStr   = aStr.subView( nMonthPos + 2, 2 );
-            }
-            else
-            {
-                // (Y)YYYY-MM-DD
-                const sal_Int32 nMonthSep = (nLen == 11 ? 5 : 4);
-                if (aStr.indexOf('-') != nMonthSep)
-                    break;
-                if (aStr.indexOf('-', nMonthSep + 1) != nMonthSep + 3)
-                    break;
+    // Valid formats are
+    // YYYYMMDD    -YYYMMDD     YYYYYMMDD    -YYYYYMMDD    YYMMDD
+    // YYYY-MM-DD  -YYYY-MM-DD  YYYYY-MM-DD  -YYYYY-MM-DD
 
-                aYearStr  = aStr.subView( 0, nMonthSep );
-                aMonthStr = aStr.subView( nMonthSep + 1, 2 );
-                aDayStr   = aStr.subView( nMonthSep + 4, 2 );
-                if (    !comphelper::string::isdigitAsciiString(aYearStr) ||
-                        !comphelper::string::isdigitAsciiString(aMonthStr) ||
-                        !comphelper::string::isdigitAsciiString(aDayStr))
-                    break;
-            }
+    sal_Int32 nSign = 1;
+    if (aStr[0] == '-')
+    {
+        nSign = -1;
+        aStr = aStr.copy(1);
+    }
+    const sal_Int32 nLen = aStr.getLength();
 
-            double dDate;
-            if (!implDateSerial( static_cast<sal_Int16>(nSign * 
o3tl::toInt32(aYearStr)),
-                        static_cast<sal_Int16>(o3tl::toInt32(aMonthStr)), 
static_cast<sal_Int16>(o3tl::toInt32(aDayStr)),
-                        bUseTwoDigitYear, SbDateCorrection::None, dDate ))
-                break;
+    // Signed YYMMDD two digit year is invalid.
+    if (nLen == 6 && nSign == -1)
+        return SbxBase::SetError( ERRCODE_BASIC_BAD_PARAMETER );
 
-            rPar.Get(0)->PutDate(dDate);
+    // Now valid
+    // YYYYMMDD    YYYYYMMDD    YYMMDD
+    // YYYY-MM-DD  YYYYY-MM-DD
+    if (nLen != 6 && (nLen < 8 || 11 < nLen))
+        return SbxBase::SetError( ERRCODE_BASIC_BAD_PARAMETER );
 
-            return;
-        }
-        while (false);
+    bool bUseTwoDigitYear = false;
+    std::u16string_view aYearStr, aMonthStr, aDayStr;
+    if (nLen == 6 || nLen == 8 || nLen == 9)
+    {
+        // ((Y)YY)YYMMDD
+        if (!comphelper::string::isdigitAsciiString(aStr))
+            return SbxBase::SetError( ERRCODE_BASIC_BAD_PARAMETER );
 
-        SbxBase::SetError( ERRCODE_BASIC_BAD_PARAMETER );
+        const sal_Int32 nMonthPos = (nLen == 8 ? 4 : (nLen == 6 ? 2 : 5));
+        if (nMonthPos == 2)
+            bUseTwoDigitYear = true;
+        aYearStr  = aStr.subView( 0, nMonthPos );
+        aMonthStr = aStr.subView( nMonthPos, 2 );
+        aDayStr   = aStr.subView( nMonthPos + 2, 2 );
     }
     else
     {
-        StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+        // (Y)YYYY-MM-DD
+        const sal_Int32 nMonthSep = (nLen == 11 ? 5 : 4);
+        if (aStr.indexOf('-') != nMonthSep)
+            return SbxBase::SetError( ERRCODE_BASIC_BAD_PARAMETER );
+        if (aStr.indexOf('-', nMonthSep + 1) != nMonthSep + 3)
+            return SbxBase::SetError( ERRCODE_BASIC_BAD_PARAMETER );
+
+        aYearStr  = aStr.subView( 0, nMonthSep );
+        aMonthStr = aStr.subView( nMonthSep + 1, 2 );
+        aDayStr   = aStr.subView( nMonthSep + 4, 2 );
+        if (    !comphelper::string::isdigitAsciiString(aYearStr) ||
+                !comphelper::string::isdigitAsciiString(aMonthStr) ||
+                !comphelper::string::isdigitAsciiString(aDayStr))
+            return SbxBase::SetError( ERRCODE_BASIC_BAD_PARAMETER );
     }
+
+    double dDate;
+    if (!implDateSerial( static_cast<sal_Int16>(nSign * 
o3tl::toInt32(aYearStr)),
+                         static_cast<sal_Int16>(o3tl::toInt32(aMonthStr)), 
static_cast<sal_Int16>(o3tl::toInt32(aDayStr)),
+                         bUseTwoDigitYear, SbDateCorrection::None, dDate ))
+        return SbxBase::SetError( ERRCODE_BASIC_BAD_PARAMETER );
+
+    rPar.Get(0)->PutDate(dDate);
 }
 
 void SbRtl_DateSerial(StarBASIC *, SbxArray & rPar, bool)
@@ -2061,55 +2048,51 @@ void SbRtl_Now(StarBASIC*, SbxArray& rPar, bool)
 
 void SbRtl_Time(StarBASIC *, SbxArray & rPar, bool bWrite)
 {
-    if ( !bWrite )
+    if (bWrite)
+        return StarBASIC::Error( ERRCODE_BASIC_NOT_IMPLEMENTED );
+
+    tools::Time aTime( tools::Time::SYSTEM );
+    SbxVariable* pMeth = rPar.Get(0);
+    if (!pMeth->IsString())
     {
-        tools::Time aTime( tools::Time::SYSTEM );
-        SbxVariable* pMeth = rPar.Get(0);
-        if (!pMeth->IsString())
-        {
-            pMeth->PutDate(aTime.GetTimeInDays());
-            return;
-        }
-        OUString aRes;
-        if( pMeth->IsFixed() )
+        pMeth->PutDate(aTime.GetTimeInDays());
+        return;
+    }
+    OUString aRes;
+    if( pMeth->IsFixed() )
+    {
+        // Time$: hh:mm:ss
+        char buf[ 20 ];
+        snprintf( buf, sizeof(buf), "%02d:%02d:%02d",
+                  aTime.GetHour(), aTime.GetMin(), aTime.GetSec() );
+        aRes = OUString::createFromAscii( buf );
+    }
+    else
+    {
+        // Time: system dependent
+        tools::Long nSeconds=aTime.GetHour();
+        nSeconds *= 3600;
+        nSeconds += aTime.GetMin() * 60;
+        nSeconds += aTime.GetSec();
+        double nDays = static_cast<double>(nSeconds) * ( 1.0 / (24.0*3600.0) );
+        const Color* pCol;
+
+        std::shared_ptr<SvNumberFormatter> pFormatter;
+        sal_uInt32 nIndex;
+        if( GetSbData()->pInst )
         {
-            // Time$: hh:mm:ss
-            char buf[ 20 ];
-            snprintf( buf, sizeof(buf), "%02d:%02d:%02d",
-                      aTime.GetHour(), aTime.GetMin(), aTime.GetSec() );
-            aRes = OUString::createFromAscii( buf );
+            pFormatter = GetSbData()->pInst->GetNumberFormatter();
+            nIndex = GetSbData()->pInst->GetStdTimeIdx();
         }
         else
         {
-            // Time: system dependent
-            tools::Long nSeconds=aTime.GetHour();
-            nSeconds *= 3600;
-            nSeconds += aTime.GetMin() * 60;
-            nSeconds += aTime.GetSec();
-            double nDays = static_cast<double>(nSeconds) * ( 1.0 / 
(24.0*3600.0) );
-            const Color* pCol;
-
-            std::shared_ptr<SvNumberFormatter> pFormatter;
-            sal_uInt32 nIndex;
-            if( GetSbData()->pInst )
-            {
-                pFormatter = GetSbData()->pInst->GetNumberFormatter();
-                nIndex = GetSbData()->pInst->GetStdTimeIdx();
-            }
-            else
-            {
-                sal_uInt32 n;   // Dummy
-                pFormatter = SbiInstance::PrepareNumberFormatter( n, nIndex, n 
);
-            }
-
-            pFormatter->GetOutputString( nDays, nIndex, aRes, &pCol );
+            sal_uInt32 n;   // Dummy
+            pFormatter = SbiInstance::PrepareNumberFormatter( n, nIndex, n );
         }
-        pMeth->PutString( aRes );
-    }
-    else
-    {
-        StarBASIC::Error( ERRCODE_BASIC_NOT_IMPLEMENTED );
+
+        pFormatter->GetOutputString( nDays, nIndex, aRes, &pCol );
     }
+    pMeth->PutString( aRes );
 }
 
 void SbRtl_Timer(StarBASIC *, SbxArray & rPar, bool)
@@ -2125,40 +2108,36 @@ void SbRtl_Timer(StarBASIC *, SbxArray & rPar, bool)
 
 void SbRtl_Date(StarBASIC *, SbxArray & rPar, bool bWrite)
 {
-    if ( !bWrite )
-    {
-        Date aToday( Date::SYSTEM );
-        double nDays = static_cast<double>(GetDayDiff( aToday ));
-        SbxVariable* pMeth = rPar.Get(0);
-        if( pMeth->IsString() )
-        {
-            OUString aRes;
-            const Color* pCol;
+    if (bWrite)
+        return StarBASIC::Error(ERRCODE_BASIC_NOT_IMPLEMENTED);
 
-            std::shared_ptr<SvNumberFormatter> pFormatter;
-            sal_uInt32 nIndex;
-            if( GetSbData()->pInst )
-            {
-                pFormatter = GetSbData()->pInst->GetNumberFormatter();
-                nIndex = GetSbData()->pInst->GetStdDateIdx();
-            }
-            else
-            {
-                sal_uInt32 n;
-                pFormatter = SbiInstance::PrepareNumberFormatter( nIndex, n, n 
);
-            }
+    Date aToday( Date::SYSTEM );
+    double nDays = static_cast<double>(GetDayDiff( aToday ));
+    SbxVariable* pMeth = rPar.Get(0);
+    if( pMeth->IsString() )
+    {
+        OUString aRes;
+        const Color* pCol;
 
-            pFormatter->GetOutputString( nDays, nIndex, aRes, &pCol );
-            pMeth->PutString( aRes );
+        std::shared_ptr<SvNumberFormatter> pFormatter;
+        sal_uInt32 nIndex;
+        if( GetSbData()->pInst )
+        {
+            pFormatter = GetSbData()->pInst->GetNumberFormatter();
+            nIndex = GetSbData()->pInst->GetStdDateIdx();
         }
         else
         {
-            pMeth->PutDate( nDays );
+            sal_uInt32 n;
+            pFormatter = SbiInstance::PrepareNumberFormatter( nIndex, n, n );
         }
+
+        pFormatter->GetOutputString( nDays, nIndex, aRes, &pCol );
+        pMeth->PutString( aRes );
     }
     else
     {
-        StarBASIC::Error( ERRCODE_BASIC_NOT_IMPLEMENTED );
+        pMeth->PutDate( nDays );
     }
 }
 
@@ -2420,211 +2399,91 @@ void SbRtl_Dir(StarBASIC *, SbxArray & rPar, bool)
 
     const sal_uInt32 nParCount = rPar.Count();
     if( nParCount > 3 )
-    {
-        StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
-    }
-    else
-    {
-        SbiRTLData& rRTLData = GetSbData()->pInst->GetRTLData();
+        return StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
 
-        if( hasUno() )
+    SbiRTLData& rRTLData = GetSbData()->pInst->GetRTLData();
+    if( hasUno() )
+    {
+        const uno::Reference< ucb::XSimpleFileAccess3 >& xSFI = 
getFileAccess();
+        if( xSFI.is() )
         {
-            const uno::Reference< ucb::XSimpleFileAccess3 >& xSFI = 
getFileAccess();
-            if( xSFI.is() )
+            if ( nParCount >= 2 )
             {
-                if ( nParCount >= 2 )
+                OUString aFileParam = rPar.Get(1)->GetOUString();
+
+                OUString aFileURLStr = implSetupWildcard(aFileParam, rRTLData);
+                if (!rRTLData.sFullNameToBeChecked.isEmpty())
                 {
-                    OUString aFileParam = rPar.Get(1)->GetOUString();
+                    bool bExists = false;
+                    try { bExists = xSFI->exists( aFileURLStr ); }
+                    catch(const Exception & ) {}
 
-                    OUString aFileURLStr = implSetupWildcard(aFileParam, 
rRTLData);
-                    if (!rRTLData.sFullNameToBeChecked.isEmpty())
+                    OUString aNameOnlyStr;
+                    if( bExists )
                     {
-                        bool bExists = false;
-                        try { bExists = xSFI->exists( aFileURLStr ); }
-                        catch(const Exception & ) {}
-
-                        OUString aNameOnlyStr;
-                        if( bExists )
-                        {
-                            INetURLObject aFileURL( aFileURLStr );
-                            aNameOnlyStr = aFileURL.getName( 
INetURLObject::LAST_SEGMENT,
-                                                             true, 
INetURLObject::DecodeMechanism::WithCharset );
-                        }
-                        rPar.Get(0)->PutString(aNameOnlyStr);
-                        return;
+                        INetURLObject aFileURL( aFileURLStr );
+                        aNameOnlyStr = aFileURL.getName( 
INetURLObject::LAST_SEGMENT,
+                                                         true, 
INetURLObject::DecodeMechanism::WithCharset );
                     }
+                    rPar.Get(0)->PutString(aNameOnlyStr);
+                    return;
+                }
 
-                    try
-                    {
-                        OUString aDirURLStr;
-                        bool bFolder = xSFI->isFolder( aFileURLStr );
-
-                        if( bFolder )
-                        {
-                            aDirURLStr = aFileURLStr;
-                        }
-                        else
-                        {
-                            rPar.Get(0)->PutString(u""_ustr);
-                        }
-
-                        sal_Int16 nFlags = SbAttributes::NORMAL;
-                        if ( nParCount > 2 )
-                        {
-                            rRTLData.nDirFlags = nFlags = 
rPar.Get(2)->GetInteger();
-                        }
-                        else
-                        {
-                            rRTLData.nDirFlags = SbAttributes::NORMAL;
-                        }
-                        // Read directory
-                        bool bIncludeFolders = bool(nFlags & 
SbAttributes::DIRECTORY);
-                        rRTLData.aDirSeq = xSFI->getFolderContents(aDirURLStr, 
bIncludeFolders);
-                        rRTLData.nCurDirPos = 0;
-
-                        // #78651 Add "." and ".." directories for VB 
compatibility
-                        if( bIncludeFolders )
-                        {
-                            bool bRoot = isRootDir( aDirURLStr );
+                try
+                {
+                    OUString aDirURLStr;
+                    bool bFolder = xSFI->isFolder( aFileURLStr );
 
-                            // If it's no root directory we flag the need for
-                            // the "." and ".." directories by the value -2
-                            // for the actual position. Later for -2 will be
-                            // returned "." and for -1 ".."
-                            if( !bRoot )
-                            {
-                                rRTLData.nCurDirPos = -2;
-                            }
-                        }
+                    if( bFolder )
+                    {
+                        aDirURLStr = aFileURLStr;
                     }
-                    catch(const Exception & )
+                    else
                     {
+                        rPar.Get(0)->PutString(u""_ustr);
                     }
-                }
-
-
-                if (rRTLData.aDirSeq.hasElements())
-                {
-                    bool bFolderFlag = bool(rRTLData.nDirFlags & 
SbAttributes::DIRECTORY);
 
-                    SbiInstance* pInst = GetSbData()->pInst;
-                    bool bCompatibility = ( pInst && pInst->IsCompatibility() 
);
-                    for( ;; )
+                    sal_Int16 nFlags = SbAttributes::NORMAL;
+                    if ( nParCount > 2 )
                     {
-                        if (rRTLData.nCurDirPos < 0)
-                        {
-                            if (rRTLData.nCurDirPos == -2)
-                            {
-                                aPath = ".";
-                            }
-                            else if (rRTLData.nCurDirPos == -1)
-                            {
-                                aPath = "..";
-                            }
-                            rRTLData.nCurDirPos++;
-                        }
-                        else if (rRTLData.nCurDirPos >= 
rRTLData.aDirSeq.getLength())
-                        {
-                            rRTLData.aDirSeq.realloc(0);
-                            aPath.clear();
-                            break;
-                        }
-                        else
-                        {
-                            OUString aFile
-                                = 
rRTLData.aDirSeq.getConstArray()[rRTLData.nCurDirPos++];
-
-                            if( bCompatibility )
-                            {
-                                if( !bFolderFlag )
-                                {
-                                    bool bFolder = xSFI->isFolder( aFile );
-                                    if( bFolder )
-                                    {
-                                        continue;
-                                    }
-                                }
-                            }
-                            else
-                            {
-                                // Only directories
-                                if( bFolderFlag )
-                                {
-                                    bool bFolder = xSFI->isFolder( aFile );
-                                    if( !bFolder )
-                                    {
-                                        continue;
-                                    }
-                                }
-                            }
+                        rRTLData.nDirFlags = nFlags = 
rPar.Get(2)->GetInteger();
+                    }
+                    else
+                    {
+                        rRTLData.nDirFlags = SbAttributes::NORMAL;
+                    }
+                    // Read directory
+                    bool bIncludeFolders = bool(nFlags & 
SbAttributes::DIRECTORY);
+                    rRTLData.aDirSeq = xSFI->getFolderContents(aDirURLStr, 
bIncludeFolders);
+                    rRTLData.nCurDirPos = 0;
 
-                            INetURLObject aURL( aFile );
-                            aPath = aURL.getName( INetURLObject::LAST_SEGMENT, 
true,
-                                                  
INetURLObject::DecodeMechanism::WithCharset );
-                        }
+                    // #78651 Add "." and ".." directories for VB compatibility
+                    if( bIncludeFolders )
+                    {
+                        bool bRoot = isRootDir( aDirURLStr );
 
-                        bool bMatch = implCheckWildcard(aPath, rRTLData);
-                        if( !bMatch )
+                        // If it's no root directory we flag the need for
+                        // the "." and ".." directories by the value -2
+                        // for the actual position. Later for -2 will be
+                        // returned "." and for -1 ".."
+                        if( !bRoot )
                         {
-                            continue;
+                            rRTLData.nCurDirPos = -2;
                         }
-                        break;
                     }
                 }
-                rPar.Get(0)->PutString(aPath);
-            }
-        }
-        else
-        {
-            // TODO: OSL
-            if ( nParCount >= 2 )
-            {
-                OUString aFileParam = rPar.Get(1)->GetOUString();
-
-                OUString aDirURL = implSetupWildcard(aFileParam, rRTLData);
-
-                sal_Int16 nFlags = SbAttributes::NORMAL;
-                if ( nParCount > 2 )
-                {
-                    rRTLData.nDirFlags = nFlags = rPar.Get(2)->GetInteger();
-                }
-                else
-                {
-                    rRTLData.nDirFlags = SbAttributes::NORMAL;
-                }
-
-                // Read directory
-                bool bIncludeFolders = bool(nFlags & SbAttributes::DIRECTORY);
-                rRTLData.pDir = std::make_unique<Directory>(aDirURL);
-                FileBase::RC nRet = rRTLData.pDir->open();
-                if( nRet != FileBase::E_None )
-                {
-                    rRTLData.pDir.reset();
-                    rPar.Get(0)->PutString(OUString());
-                    return;
-                }
-
-                // #86950 Add "." and ".." directories for VB compatibility
-                rRTLData.nCurDirPos = 0;
-                if( bIncludeFolders )
+                catch(const Exception & )
                 {
-                    bool bRoot = isRootDir( aDirURL );
-
-                    // If it's no root directory we flag the need for
-                    // the "." and ".." directories by the value -2
-                    // for the actual position. Later for -2 will be
-                    // returned "." and for -1 ".."
-                    if( !bRoot )
-                    {
-                        rRTLData.nCurDirPos = -2;
-                    }
                 }
-
             }
 
-            if (rRTLData.pDir)
+
+            if (rRTLData.aDirSeq.hasElements())
             {
                 bool bFolderFlag = bool(rRTLData.nDirFlags & 
SbAttributes::DIRECTORY);
+
+                SbiInstance* pInst = GetSbData()->pInst;
+                bool bCompatibility = ( pInst && pInst->IsCompatibility() );
                 for( ;; )
                 {
                     if (rRTLData.nCurDirPos < 0)
@@ -2639,38 +2498,44 @@ void SbRtl_Dir(StarBASIC *, SbxArray & rPar, bool)
                         }
                         rRTLData.nCurDirPos++;
                     }
+                    else if (rRTLData.nCurDirPos >= 
rRTLData.aDirSeq.getLength())
+                    {
+                        rRTLData.aDirSeq.realloc(0);
+                        aPath.clear();
+                        break;
+                    }
                     else
                     {
-                        DirectoryItem aItem;
-                        FileBase::RC nRet = rRTLData.pDir->getNextItem(aItem);
-                        if( nRet != FileBase::E_None )
-                        {
-                            rRTLData.pDir.reset();
-                            aPath.clear();
-                            break;
-                        }
+                        OUString aFile
+                            = 
rRTLData.aDirSeq.getConstArray()[rRTLData.nCurDirPos++];
 
-                        // Handle flags
-                        FileStatus aFileStatus( osl_FileStatus_Mask_Type | 
osl_FileStatus_Mask_FileName );
-                        nRet = aItem.getFileStatus( aFileStatus );
-                        if( nRet != FileBase::E_None )
+                        if( bCompatibility )
                         {
-                            SAL_WARN("basic", "getFileStatus failed");
-                            continue;
+                            if( !bFolderFlag )
+                            {
+                                bool bFolder = xSFI->isFolder( aFile );
+                                if( bFolder )
+                                {
+                                    continue;
+                                }
+                            }
                         }
-
-                        // Only directories?
-                        if( bFolderFlag )
+                        else
                         {
-                            FileStatus::Type aType = aFileStatus.getFileType();
-                            bool bFolder = isFolder( aType );
-                            if( !bFolder )
+                            // Only directories
+                            if( bFolderFlag )
                             {
-                                continue;
+                                bool bFolder = xSFI->isFolder( aFile );
+                                if( !bFolder )
+                                {
+                                    continue;
+                                }
                             }
                         }
 
-                        aPath = aFileStatus.getFileName();
+                        INetURLObject aURL( aFile );
+                        aPath = aURL.getName( INetURLObject::LAST_SEGMENT, 
true,
+                                              
INetURLObject::DecodeMechanism::WithCharset );
                     }
 
                     bool bMatch = implCheckWildcard(aPath, rRTLData);
@@ -2684,208 +2549,307 @@ void SbRtl_Dir(StarBASIC *, SbxArray & rPar, bool)
             rPar.Get(0)->PutString(aPath);
         }
     }
-}
-
-
-void SbRtl_GetAttr(StarBASIC *, SbxArray & rPar, bool)
-{
-    if (rPar.Count() == 2)
+    else
     {
-        sal_Int16 nFlags = SbAttributes::NORMAL;
-
-        // In Windows, we want to use Windows API to get the file attributes
-        // for VBA interoperability.
-    #if defined(_WIN32)
-        if( SbiRuntime::isVBAEnabled() )
+        // TODO: OSL
+        if ( nParCount >= 2 )
         {
-            OUString aPathURL = getFullPath(rPar.Get(1)->GetOUString());
-            OUString aPath;
-            FileBase::getSystemPathFromFileURL( aPathURL, aPath );
-            DWORD nRealFlags = GetFileAttributesW (o3tl::toW(aPath.getStr()));
-            if (nRealFlags != 0xffffffff)
+            OUString aFileParam = rPar.Get(1)->GetOUString();
+
+            OUString aDirURL = implSetupWildcard(aFileParam, rRTLData);
+
+            sal_Int16 nFlags = SbAttributes::NORMAL;
+            if ( nParCount > 2 )
             {
-                if (nRealFlags == FILE_ATTRIBUTE_NORMAL)
-                {
-                    nRealFlags = 0;
-                }
-                nFlags = static_cast<sal_Int16>(nRealFlags);
+                rRTLData.nDirFlags = nFlags = rPar.Get(2)->GetInteger();
             }
             else
             {
-                StarBASIC::Error( ERRCODE_BASIC_FILE_NOT_FOUND );
+                rRTLData.nDirFlags = SbAttributes::NORMAL;
+            }
+
+            // Read directory
+            bool bIncludeFolders = bool(nFlags & SbAttributes::DIRECTORY);
+            rRTLData.pDir = std::make_unique<Directory>(aDirURL);
+            FileBase::RC nRet = rRTLData.pDir->open();
+            if( nRet != FileBase::E_None )
+            {
+                rRTLData.pDir.reset();
+                rPar.Get(0)->PutString(OUString());
+                return;
+            }
+
+            // #86950 Add "." and ".." directories for VB compatibility
+            rRTLData.nCurDirPos = 0;
+            if( bIncludeFolders )
+            {
+                bool bRoot = isRootDir( aDirURL );
+
+                // If it's no root directory we flag the need for
+                // the "." and ".." directories by the value -2
+                // for the actual position. Later for -2 will be
+                // returned "." and for -1 ".."
+                if( !bRoot )
+                {
+                    rRTLData.nCurDirPos = -2;
+                }
             }
-            rPar.Get(0)->PutInteger(nFlags);
 
-            return;
         }
-    #endif
 
-        if( hasUno() )
+        if (rRTLData.pDir)
         {
-            const uno::Reference< ucb::XSimpleFileAccess3 >& xSFI = 
getFileAccess();
-            if( xSFI.is() )
+            bool bFolderFlag = bool(rRTLData.nDirFlags & 
SbAttributes::DIRECTORY);
+            for( ;; )
             {
-                try
+                if (rRTLData.nCurDirPos < 0)
                 {
-                    OUString aPath = getFullPath(rPar.Get(1)->GetOUString());
-                    bool bExists = false;
-                    try { bExists = xSFI->exists( aPath ); }
-                    catch(const Exception & ) {}
-                    if( !bExists )
+                    if (rRTLData.nCurDirPos == -2)
                     {
-                        return StarBASIC::Error( ERRCODE_BASIC_FILE_NOT_FOUND 
);
+                        aPath = ".";
                     }
-
-                    bool bReadOnly = xSFI->isReadOnly( aPath );
-                    bool bHidden = xSFI->isHidden( aPath );
-                    bool bDirectory = xSFI->isFolder( aPath );
-                    if( bReadOnly )
+                    else if (rRTLData.nCurDirPos == -1)
                     {
-                        nFlags |= SbAttributes::READONLY;
+                        aPath = "..";
                     }
-                    if( bHidden )
+                    rRTLData.nCurDirPos++;
+                }
+                else
+                {
+                    DirectoryItem aItem;
+                    FileBase::RC nRet = rRTLData.pDir->getNextItem(aItem);
+                    if( nRet != FileBase::E_None )
                     {
-                        nFlags |= SbAttributes::HIDDEN;
+                        rRTLData.pDir.reset();
+                        aPath.clear();
+                        break;
                     }
-                    if( bDirectory )
+
+                    // Handle flags
+                    FileStatus aFileStatus( osl_FileStatus_Mask_Type | 
osl_FileStatus_Mask_FileName );
+                    nRet = aItem.getFileStatus( aFileStatus );
+                    if( nRet != FileBase::E_None )
                     {
-                        nFlags |= SbAttributes::DIRECTORY;
+                        SAL_WARN("basic", "getFileStatus failed");
+                        continue;
                     }
+
+                    // Only directories?
+                    if( bFolderFlag )
+                    {
+                        FileStatus::Type aType = aFileStatus.getFileType();
+                        bool bFolder = isFolder( aType );
+                        if( !bFolder )
+                        {
+                            continue;
+                        }
+                    }
+
+                    aPath = aFileStatus.getFileName();
                 }
-                catch(const Exception & )
+
+                bool bMatch = implCheckWildcard(aPath, rRTLData);
+                if( !bMatch )
                 {
-                    StarBASIC::Error( ERRCODE_IO_GENERAL );
+                    continue;
                 }
+                break;
             }
         }
+        rPar.Get(0)->PutString(aPath);
+    }
+}
+
+
+void SbRtl_GetAttr(StarBASIC *, SbxArray & rPar, bool)
+{
+    if (rPar.Count() != 2)
+        return StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+    sal_Int16 nFlags = SbAttributes::NORMAL;
+
+    // In Windows, we want to use Windows API to get the file attributes
+    // for VBA interoperability.
+#if defined(_WIN32)
+    if( SbiRuntime::isVBAEnabled() )
+    {
+        OUString aPathURL = getFullPath(rPar.Get(1)->GetOUString());
+        OUString aPath;
+        FileBase::getSystemPathFromFileURL( aPathURL, aPath );
+        DWORD nRealFlags = GetFileAttributesW (o3tl::toW(aPath.getStr()));
+        if (nRealFlags != 0xffffffff)
+        {
+            if (nRealFlags == FILE_ATTRIBUTE_NORMAL)
+            {
+                nRealFlags = 0;
+            }
+            nFlags = static_cast<sal_Int16>(nRealFlags);
+        }
         else
         {
-            DirectoryItem aItem;
-            (void)DirectoryItem::get(getFullPath(rPar.Get(1)->GetOUString()), 
aItem);
-            FileStatus aFileStatus( osl_FileStatus_Mask_Attributes | 
osl_FileStatus_Mask_Type );
-            (void)aItem.getFileStatus( aFileStatus );
-            sal_uInt64 nAttributes = aFileStatus.getAttributes();
-            bool bReadOnly = (nAttributes & osl_File_Attribute_ReadOnly) != 0;
-
-            FileStatus::Type aType = aFileStatus.getFileType();
-            bool bDirectory = isFolder( aType );
-            if( bReadOnly )
+            StarBASIC::Error( ERRCODE_BASIC_FILE_NOT_FOUND );
+        }
+        rPar.Get(0)->PutInteger(nFlags);
+
+        return;
+    }
+#endif
+
+    if( hasUno() )
+    {
+        const uno::Reference< ucb::XSimpleFileAccess3 >& xSFI = 
getFileAccess();
+        if( xSFI.is() )
+        {
+            try
             {
-                nFlags |= SbAttributes::READONLY;
+                OUString aPath = getFullPath(rPar.Get(1)->GetOUString());
+                bool bExists = false;
+                try { bExists = xSFI->exists( aPath ); }
+                catch(const Exception & ) {}
+                if( !bExists )
+                {
+                    return StarBASIC::Error( ERRCODE_BASIC_FILE_NOT_FOUND );
+                }
+
+                bool bReadOnly = xSFI->isReadOnly( aPath );
+                bool bHidden = xSFI->isHidden( aPath );
+                bool bDirectory = xSFI->isFolder( aPath );
+                if( bReadOnly )
+                {
+                    nFlags |= SbAttributes::READONLY;
+                }
+                if( bHidden )
+                {
+                    nFlags |= SbAttributes::HIDDEN;
+                }
+                if( bDirectory )
+                {
+                    nFlags |= SbAttributes::DIRECTORY;
+                }
             }
-            if( bDirectory )
+            catch(const Exception & )
             {
-                nFlags |= SbAttributes::DIRECTORY;
+                StarBASIC::Error( ERRCODE_IO_GENERAL );
             }
         }
-        rPar.Get(0)->PutInteger(nFlags);
     }
     else
     {
-        StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+        DirectoryItem aItem;
+        (void)DirectoryItem::get(getFullPath(rPar.Get(1)->GetOUString()), 
aItem);
+        FileStatus aFileStatus( osl_FileStatus_Mask_Attributes | 
osl_FileStatus_Mask_Type );
+        (void)aItem.getFileStatus( aFileStatus );
+        sal_uInt64 nAttributes = aFileStatus.getAttributes();
+        bool bReadOnly = (nAttributes & osl_File_Attribute_ReadOnly) != 0;
+
+        FileStatus::Type aType = aFileStatus.getFileType();
+        bool bDirectory = isFolder( aType );
+        if( bReadOnly )
+        {
+            nFlags |= SbAttributes::READONLY;
+        }
+        if( bDirectory )
+        {
+            nFlags |= SbAttributes::DIRECTORY;
+        }
     }
+    rPar.Get(0)->PutInteger(nFlags);
 }
 
 
 void SbRtl_FileDateTime(StarBASIC *, SbxArray & rPar, bool)
 {
     if (rPar.Count() != 2)
+        return StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
+
+    OUString aPath = rPar.Get(1)->GetOUString();
+    tools::Time aTime( tools::Time::EMPTY );
+    Date aDate( Date::EMPTY );
+    if( hasUno() )
     {
-        StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
-    }
-    else
-    {
-        OUString aPath = rPar.Get(1)->GetOUString();
-        tools::Time aTime( tools::Time::EMPTY );
-        Date aDate( Date::EMPTY );
-        if( hasUno() )
+        const uno::Reference< ucb::XSimpleFileAccess3 >& xSFI = 
getFileAccess();
+        if( xSFI.is() )
         {
-            const uno::Reference< ucb::XSimpleFileAccess3 >& xSFI = 
getFileAccess();
-            if( xSFI.is() )
+            try
             {
-                try
-                {
-                    util::DateTime aUnoDT = xSFI->getDateTimeModified( aPath );
-                    aTime = tools::Time( aUnoDT );
-                    aDate = Date( aUnoDT );
-                }
-                catch(const Exception & )
-                {
-                    StarBASIC::Error( ERRCODE_IO_GENERAL );
-                }
+                util::DateTime aUnoDT = xSFI->getDateTimeModified( aPath );
+                aTime = tools::Time( aUnoDT );
+                aDate = Date( aUnoDT );
+            }
+            catch(const Exception & )
+            {
+                StarBASIC::Error( ERRCODE_IO_GENERAL );
             }
         }
-        else
+    }
+    else
+    {
+        bool bSuccess = false;
+        do
         {
-            bool bSuccess = false;
-            do
-            {
-                DirectoryItem aItem;
-                if (DirectoryItem::get( getFullPath( aPath ), aItem ) != 
FileBase::E_None)
-                    break;
-
-                FileStatus aFileStatus( osl_FileStatus_Mask_ModifyTime );
-                if (aItem.getFileStatus( aFileStatus ) != FileBase::E_None)
-                    break;
+            DirectoryItem aItem;
+            if (DirectoryItem::get( getFullPath( aPath ), aItem ) != 
FileBase::E_None)
+                break;
 
-                TimeValue aTimeVal = aFileStatus.getModifyTime();
-                oslDateTime aDT;
-                if (!osl_getDateTimeFromTimeValue( &aTimeVal, &aDT ))
-                    // Strictly spoken this is not an i/o error but some other 
failure.
-                    break;
+            FileStatus aFileStatus( osl_FileStatus_Mask_ModifyTime );
+            if (aItem.getFileStatus( aFileStatus ) != FileBase::E_None)
+                break;
 
-                aTime = tools::Time( aDT.Hours, aDT.Minutes, aDT.Seconds, 
aDT.NanoSeconds );
-                aDate = Date( aDT.Day, aDT.Month, aDT.Year );
-                bSuccess = true;
-            }
-            while(false);
+            TimeValue aTimeVal = aFileStatus.getModifyTime();
+            oslDateTime aDT;
+            if (!osl_getDateTimeFromTimeValue( &aTimeVal, &aDT ))
+                // Strictly spoken this is not an i/o error but some other 
failure.
+                break;
 
-            if (!bSuccess)
-                StarBASIC::Error( ERRCODE_IO_GENERAL );
+            aTime = tools::Time( aDT.Hours, aDT.Minutes, aDT.Seconds, 
aDT.NanoSeconds );
+            aDate = Date( aDT.Day, aDT.Month, aDT.Year );
+            bSuccess = true;
         }
+        while(false);
 
-        // An empty date shall not result in a formatted null-date (1899-12-30
-        // or 1900-01-01) or even worse -0001-12-03 or some such due to how
-        // GetDayDiff() treats things. There should be an error set in this
-        // case anyway because of a missing file or other error above, but... 
so
-        // do not even bother to use the number formatter.
-        OUString aRes;
-        if (aDate.IsEmpty())
+        if (!bSuccess)
+            StarBASIC::Error( ERRCODE_IO_GENERAL );
+    }
+
+    // An empty date shall not result in a formatted null-date (1899-12-30
+    // or 1900-01-01) or even worse -0001-12-03 or some such due to how
+    // GetDayDiff() treats things. There should be an error set in this
+    // case anyway because of a missing file or other error above, but... so
+    // do not even bother to use the number formatter.
+    OUString aRes;
+    if (aDate.IsEmpty())
+    {
+        aRes = "0000-00-00 00:00:00";
+    }
+    else
+    {
+        double fSerial = static_cast<double>(GetDayDiff( aDate ));
+        tools::Long nSeconds = aTime.GetHour();
+        nSeconds *= 3600;
+        nSeconds += aTime.GetMin() * 60;
+        nSeconds += aTime.GetSec();
+        double nDays = static_cast<double>(nSeconds) / (24.0*3600.0);
+        fSerial += nDays;
+
+        const Color* pCol;
+
+        std::shared_ptr<SvNumberFormatter> pFormatter;
+        sal_uInt32 nIndex;
+        if( GetSbData()->pInst )
         {
-            aRes = "0000-00-00 00:00:00";
+            pFormatter = GetSbData()->pInst->GetNumberFormatter();
+            nIndex = GetSbData()->pInst->GetStdDateTimeIdx();
         }
         else
         {
-            double fSerial = static_cast<double>(GetDayDiff( aDate ));
-            tools::Long nSeconds = aTime.GetHour();
-            nSeconds *= 3600;
-            nSeconds += aTime.GetMin() * 60;
-            nSeconds += aTime.GetSec();
-            double nDays = static_cast<double>(nSeconds) / (24.0*3600.0);
-            fSerial += nDays;
-
-            const Color* pCol;
-
-            std::shared_ptr<SvNumberFormatter> pFormatter;
-            sal_uInt32 nIndex;
-            if( GetSbData()->pInst )
-            {
-                pFormatter = GetSbData()->pInst->GetNumberFormatter();
-                nIndex = GetSbData()->pInst->GetStdDateTimeIdx();
-            }
-            else
-            {
-                sal_uInt32 n;
-                pFormatter = SbiInstance::PrepareNumberFormatter( n, n, nIndex 
);
-            }
-
-            pFormatter->GetOutputString( fSerial, nIndex, aRes, &pCol );
+            sal_uInt32 n;
+            pFormatter = SbiInstance::PrepareNumberFormatter( n, n, nIndex );
         }
-        rPar.Get(0)->PutString(aRes);
+
+        pFormatter->GetOutputString( fSerial, nIndex, aRes, &pCol );
     }
+    rPar.Get(0)->PutString(aRes);
 }
 
-
 void SbRtl_EOF(StarBASIC *, SbxArray & rPar, bool)
 {
     // No changes for UCB

Reply via email to