/* -*- 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 .
*/
template< typename A, typename D > void ScCompressedArray<A,D>::SetValue( A nStart, A nEnd, const D& rValue )
{ if (!(0 <= nStart && nStart <= nMaxAccess && 0 <= nEnd && nEnd <= nMaxAccess
&& nStart <= nEnd)) return;
if ((nStart == 0) && (nEnd == nMaxAccess))
Reset( rValue); else
{ // Create a temporary copy in case we got a reference passed that // points to a part of the array to be reallocated.
D aNewVal( rValue);
size_t nNeeded = nCount + 2; if (nLimit < nNeeded)
{
nLimit *= 1.5; if (nLimit < nNeeded)
nLimit = nNeeded;
std::unique_ptr<DataEntry[]> pNewData(new DataEntry[nLimit]);
memcpy( pNewData.get(), pData.get(), nCount*sizeof(DataEntry));
pData = std::move(pNewData);
}
size_t ni; // number of leading entries
size_t nInsert; // insert position (nMaxAccess+1 := no insert) bool bCombined = false; bool bSplit = false; if (nStart > 0)
{ // skip leading
ni = this->Search( nStart);
nInsert = nMaxAccess+1; if (!(pData[ni].aValue == aNewVal))
{ if (ni == 0 || (pData[ni-1].nEnd < nStart - 1))
{ // may be a split or a simple insert or just a shrink, // row adjustment is done further down if (pData[ni].nEnd > nEnd)
bSplit = true;
ni++;
nInsert = ni;
} elseif (ni > 0 && pData[ni-1].nEnd == nStart - 1)
nInsert = ni;
} if (ni > 0 && pData[ni-1].aValue == aNewVal)
{ // combine
pData[ni-1].nEnd = nEnd;
nInsert = nMaxAccess+1;
bCombined = true;
}
} else
{
nInsert = 0;
ni = 0;
}
template< typename A, typename D > void ScCompressedArray<A,D>::CopyFrom( const ScCompressedArray<A,D>& rArray, A nDestStart,
A nDestEnd, A nSrcStart )
{
assert( this != &rArray && "cannot copy self->self" );
size_t nIndex = 0;
A nRegionEnd; for (A j=nDestStart; j<=nDestEnd; ++j)
{ const D& rValue = (j==nDestStart ?
rArray.GetValue( j - nDestStart + nSrcStart, nIndex, nRegionEnd) :
rArray.GetNextValue( nIndex, nRegionEnd));
nRegionEnd = nRegionEnd - nSrcStart + nDestStart; if (nRegionEnd > nDestEnd)
nRegionEnd = nDestEnd;
this->SetValue( j, nRegionEnd, rValue);
j = nRegionEnd;
}
}
template< typename A, typename D > const D& ScCompressedArray<A,D>::Insert( A nStart, size_t nAccessCount )
{
size_t nIndex = this->Search( nStart); // No real insertion is needed, simply extend the one entry and adapt all // following. In case nStart points to the start row of an entry, extend // the previous entry (inserting before nStart). if (nIndex > 0 && pData[nIndex-1].nEnd+1 == nStart)
--nIndex; const D& rValue = pData[nIndex].aValue; // the value "copied" do
{
pData[nIndex].nEnd += nAccessCount; if (pData[nIndex].nEnd >= nMaxAccess)
{
pData[nIndex].nEnd = nMaxAccess;
nCount = nIndex + 1; // discard trailing entries
}
} while (++nIndex < nCount); return rValue;
}
template< typename A, typename D > void ScCompressedArray<A,D>::InsertPreservingSize( A nStart, size_t nAccessCount, const D& rFillValue )
{ const A nPrevLastPos = GetLastPos();
Insert(nStart, nAccessCount); for (A i = nStart; i < A(nStart + nAccessCount); ++i)
SetValue(i, rFillValue);
const A nNewLastPos = GetLastPos();
Remove(nPrevLastPos, nNewLastPos - nPrevLastPos);
}
template< typename A, typename D > void ScCompressedArray<A,D>::Remove( A nStart, size_t nAccessCount )
{
A nEnd = nStart + nAccessCount - 1;
size_t nIndex = this->Search( nStart); // equalize/combine/remove all entries in between if (nEnd > pData[nIndex].nEnd)
this->SetValue( nStart, nEnd, pData[nIndex].aValue); // remove an exactly matching entry by shifting up all following by one if ((nStart == 0 || (nIndex > 0 && nStart == pData[nIndex-1].nEnd+1)) &&
pData[nIndex].nEnd == nEnd && nIndex < nCount-1)
{ // In case removing an entry results in two adjacent entries with // identical data, combine them into one. This is also necessary to // make the algorithm used in SetValue() work correctly, it relies on // the fact that consecutive values actually differ.
size_t nRemove; if (nIndex > 0 && pData[nIndex-1].aValue == pData[nIndex+1].aValue)
{
nRemove = 2;
--nIndex;
} else
nRemove = 1;
memmove( pData.get() + nIndex, pData.get() + nIndex + nRemove, (nCount - (nIndex +
nRemove)) * sizeof(DataEntry));
nCount -= nRemove;
} // adjust end rows, nIndex still being valid do
{
pData[nIndex].nEnd -= nAccessCount;
} while (++nIndex < nCount);
pData[nCount-1].nEnd = nMaxAccess;
}
template< typename A, typename D > void ScCompressedArray<A,D>::RemovePreservingSize( A nStart, size_t nAccessCount, const D& rFillValue )
{ const A nPrevLastPos = GetLastPos();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.