diff options
author | Mike Kaganski <mike.kaganski@collabora.com> | 2019-12-08 14:52:07 +0300 |
---|---|---|
committer | Mike Kaganski <mike.kaganski@collabora.com> | 2019-12-08 14:14:37 +0100 |
commit | 4f4fe34b29638ed37c45b2c795fdc6cd6d59f1cf (patch) | |
tree | 5c4710d76b7e1d10f366e2080a724d39e832067a /basic | |
parent | bc1a8c682f889e488a7961faa0708568c480438a (diff) |
Unify code that restores preserved array
Change-Id: I5e8e8d3d7d185d3968c7ff40b86d046599ca44df
Reviewed-on: https://gerrit.libreoffice.org/84709
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Diffstat (limited to 'basic')
-rw-r--r-- | basic/source/runtime/runtime.cxx | 179 |
1 files changed, 65 insertions, 114 deletions
diff --git a/basic/source/runtime/runtime.cxx b/basic/source/runtime/runtime.cxx index f9754cdbe773..232778c73af3 100644 --- a/basic/source/runtime/runtime.cxx +++ b/basic/source/runtime/runtime.cxx @@ -2160,7 +2160,7 @@ void SbiRuntime::StepREDIM() } -// Helper function for StepREDIMP +// Helper function for StepREDIMP and StepDCREATE_IMPL / bRedimp = true static void implCopyDimArray( SbxDimArray* pNewArray, SbxDimArray* pOldArray, short nMaxDimIndex, short nActualDim, sal_Int32* pActualIndices, sal_Int32* pLowerBounds, sal_Int32* pUpperBounds ) { @@ -2175,13 +2175,61 @@ static void implCopyDimArray( SbxDimArray* pNewArray, SbxDimArray* pOldArray, sh else { SbxVariable* pSource = pOldArray->Get32( pActualIndices ); - SbxVariable* pDest = pNewArray->Get32( pActualIndices ); - if( pSource && pDest ) + pNewArray->Put32(pSource, pActualIndices); + } + } +} + +// Returns true when actually restored +static bool implRestorePreservedArray(SbxDimArray* pNewArray, SbxArrayRef& rrefRedimpArray, bool* pbWasError = nullptr) +{ + assert(pNewArray); + bool bResult = false; + if (pbWasError) + *pbWasError = false; + if (rrefRedimpArray) + { + SbxDimArray* pOldArray = static_cast<SbxDimArray*>(rrefRedimpArray.get()); + const short nDimsNew = pNewArray->GetDims(); + const short nDimsOld = pOldArray->GetDims(); + + if (nDimsOld != nDimsNew) + { + StarBASIC::Error(ERRCODE_BASIC_OUT_OF_RANGE); + if (pbWasError) + *pbWasError = true; + } + else if (nDimsNew > 0) + { + // Store dims to use them for copying later + std::unique_ptr<sal_Int32[]> pLowerBounds(new sal_Int32[nDimsNew]); + std::unique_ptr<sal_Int32[]> pUpperBounds(new sal_Int32[nDimsNew]); + std::unique_ptr<sal_Int32[]> pActualIndices(new sal_Int32[nDimsNew]); + + // Compare bounds + for (short i = 1; i <= nDimsNew; i++) { - *pDest = *pSource; + sal_Int32 lBoundNew, uBoundNew; + sal_Int32 lBoundOld, uBoundOld; + pNewArray->GetDim32(i, lBoundNew, uBoundNew); + pOldArray->GetDim32(i, lBoundOld, uBoundOld); + lBoundNew = std::max(lBoundNew, lBoundOld); + uBoundNew = std::min(uBoundNew, uBoundOld); + short j = i - 1; + pActualIndices[j] = pLowerBounds[j] = lBoundNew; + pUpperBounds[j] = uBoundNew; } + // Copy data from old array by going recursively through all dimensions + // (It would be faster to work on the flat internal data array of an + // SbyArray but this solution is clearer and easier) + implCopyDimArray(pNewArray, pOldArray, nDimsNew - 1, 0, pActualIndices.get(), + pLowerBounds.get(), pUpperBounds.get()); + bResult = true; } + + rrefRedimpArray.clear(); } + return bResult; } // REDIM PRESERVE @@ -2196,50 +2244,9 @@ void SbiRuntime::StepREDIMP() // Now check, if we can copy from the old array if( refRedimpArray.is() ) { - SbxBase* pElemObj = refVar->GetObject(); - SbxDimArray* pNewArray = dynamic_cast<SbxDimArray*>( pElemObj ); - SbxDimArray* pOldArray = static_cast<SbxDimArray*>(refRedimpArray.get()); - if( pNewArray ) - { - short nDimsNew = pNewArray->GetDims(); - short nDimsOld = pOldArray->GetDims(); - short nDims = nDimsNew; - - if( nDimsOld != nDimsNew ) - { - StarBASIC::Error( ERRCODE_BASIC_OUT_OF_RANGE ); - } - else if (nDims > 0) - { - // Store dims to use them for copying later - std::unique_ptr<sal_Int32[]> pLowerBounds(new sal_Int32[nDims]); - std::unique_ptr<sal_Int32[]> pUpperBounds(new sal_Int32[nDims]); - std::unique_ptr<sal_Int32[]> pActualIndices(new sal_Int32[nDims]); - - // Compare bounds - for( short i = 1 ; i <= nDims ; i++ ) - { - sal_Int32 lBoundNew, uBoundNew; - sal_Int32 lBoundOld, uBoundOld; - pNewArray->GetDim32( i, lBoundNew, uBoundNew ); - pOldArray->GetDim32( i, lBoundOld, uBoundOld ); - lBoundNew = std::max( lBoundNew, lBoundOld ); - uBoundNew = std::min( uBoundNew, uBoundOld ); - short j = i - 1; - pActualIndices[j] = pLowerBounds[j] = lBoundNew; - pUpperBounds[j] = uBoundNew; - } - // Copy data from old array by going recursively through all dimensions - // (It would be faster to work on the flat internal data array of an - // SbyArray but this solution is clearer and easier) - implCopyDimArray( pNewArray, pOldArray, nDims - 1, - 0, pActualIndices.get(), pLowerBounds.get(), pUpperBounds.get() ); - } - - refRedimpArray = nullptr; - } + if (SbxDimArray* pNewArray = dynamic_cast<SbxDimArray*>(refVar->GetObject())) + implRestorePreservedArray(pNewArray, refRedimpArray); } - } // REDIM_COPY @@ -4278,27 +4285,6 @@ void SbiRuntime::StepDCREATE_REDIMP( sal_uInt32 nOp1, sal_uInt32 nOp2 ) StepDCREATE_IMPL( nOp1, nOp2 ); } - -// Helper function for StepDCREATE_IMPL / bRedimp = true -static void implCopyDimArray_DCREATE( SbxDimArray* pNewArray, SbxDimArray* pOldArray, short nMaxDimIndex, - short nActualDim, sal_Int32* pActualIndices, sal_Int32* pLowerBounds, sal_Int32* pUpperBounds ) -{ - sal_Int32& ri = pActualIndices[nActualDim]; - for( ri = pLowerBounds[nActualDim] ; ri <= pUpperBounds[nActualDim] ; ri++ ) - { - if( nActualDim < nMaxDimIndex ) - { - implCopyDimArray_DCREATE( pNewArray, pOldArray, nMaxDimIndex, nActualDim + 1, - pActualIndices, pLowerBounds, pUpperBounds ); - } - else - { - SbxVariable* pSource = pOldArray->Get32( pActualIndices ); - pNewArray->Put32( pSource, pActualIndices ); - } - } -} - // #56204 create object array (+StringID+StringID), DCREATE == Dim-Create void SbiRuntime::StepDCREATE_IMPL( sal_uInt32 nOp1, sal_uInt32 nOp2 ) { @@ -4307,15 +4293,14 @@ void SbiRuntime::StepDCREATE_IMPL( sal_uInt32 nOp1, sal_uInt32 nOp2 ) DimImpl( refVar ); // fill the array with instances of the requested class - SbxBaseRef xObj = refVar->GetObject(); - if( !xObj.is() ) + SbxBase* pObj = refVar->GetObject(); + if (!pObj) { StarBASIC::Error( ERRCODE_BASIC_INVALID_OBJECT ); return; } - SbxDimArray* pArray = dynamic_cast<SbxDimArray*>(xObj.get()); - if (pArray) + if (SbxDimArray* pArray = dynamic_cast<SbxDimArray*>(pObj)) { const short nDims = pArray->GetDims(); sal_Int32 nTotalSize = nDims > 0 ? 1 : 0; @@ -4330,52 +4315,17 @@ void SbiRuntime::StepDCREATE_IMPL( sal_uInt32 nOp1, sal_uInt32 nOp2 ) } // First, fill those parts of the array that are preserved - SbxDimArray* const pOldArray = static_cast<SbxDimArray*>(refRedimpArray.get()); - if (nTotalSize && pOldArray) - { - const short nDimsOld = pOldArray->GetDims(); - - if (nDimsOld != nDims) - { - StarBASIC::Error(ERRCODE_BASIC_OUT_OF_RANGE); - nTotalSize = 0; // don't create objects on error - } - else - { - std::unique_ptr<sal_Int32[]> pLowerBounds(new sal_Int32[nDims]); - std::unique_ptr<sal_Int32[]> pUpperBounds(new sal_Int32[nDims]); - std::unique_ptr<sal_Int32[]> pActualIndices(new sal_Int32[nDims]); - - // Compare bounds - for (short i = 1; i <= nDims; i++) - { - sal_Int32 lBoundNew, uBoundNew; - sal_Int32 lBoundOld, uBoundOld; - pArray->GetDim32(i, lBoundNew, uBoundNew); - pOldArray->GetDim32(i, lBoundOld, uBoundOld); - - lBoundNew = std::max(lBoundNew, lBoundOld); - uBoundNew = std::min(uBoundNew, uBoundOld); - short j = i - 1; - pActualIndices[j] = pLowerBounds[j] = lBoundNew; - pUpperBounds[j] = uBoundNew; - } - - // Copy data from old array by going recursively through all dimensions - // (It would be faster to work on the flat internal data array of an - // SbyArray but this solution is clearer and easier) - implCopyDimArray_DCREATE(pArray, pOldArray, nDims - 1, - 0, pActualIndices.get(), pLowerBounds.get(), pUpperBounds.get()); - } - refRedimpArray.clear(); - } - // pOldArray points to destroyed object now, and only used as "ReDim Preserve" flag below + bool bWasError = false; + const bool bRestored = implRestorePreservedArray(pArray, refRedimpArray, &bWasError); + if (bWasError) + nTotalSize = 0; // on error, don't create objects // create objects and insert them into the array OUString aClass( pImg->GetString( static_cast<short>( nOp2 ) ) ); + OUString aName; for( sal_Int32 i = 0 ; i < nTotalSize ; ++i ) { - if (!pOldArray || !pArray->SbxArray::GetRef32(i)) // For those left unset after preserve + if (!bRestored || !pArray->SbxArray::GetRef32(i)) // For those left unset after preserve { SbxObject* pClassObj = SbxBase::CreateObject(aClass); if (!pClassObj) @@ -4385,7 +4335,8 @@ void SbiRuntime::StepDCREATE_IMPL( sal_uInt32 nOp1, sal_uInt32 nOp2 ) } else { - OUString aName(pImg->GetString(static_cast<short>(nOp1))); + if (aName.isEmpty()) + aName = pImg->GetString(static_cast<short>(nOp1)); pClassObj->SetName(aName); // the object must be able to call the basic pClassObj->SetParent(&rBasic); |