LCOV - code coverage report
Current view: top level - sc/source/core/data - cellvalues.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 99 186 53.2 %
Date: 2014-11-03 Functions: 24 32 75.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  */
       9             : 
      10             : #include <cellvalues.hxx>
      11             : #include <column.hxx>
      12             : #include <cellvalue.hxx>
      13             : 
      14             : #include <cassert>
      15             : #include <boost/noncopyable.hpp>
      16             : 
      17             : namespace sc {
      18             : 
      19             : namespace {
      20             : 
      21             : struct BlockPos
      22             : {
      23             :     size_t mnStart;
      24             :     size_t mnEnd;
      25             : };
      26             : 
      27          16 : CellType toCellType( mdds::mtv::element_t eType )
      28             : {
      29          16 :     switch (eType)
      30             :     {
      31             :         case element_type_numeric:
      32           4 :             return CELLTYPE_VALUE;
      33             :         case element_type_string:
      34           0 :             return CELLTYPE_STRING;
      35             :         case element_type_edittext:
      36           0 :             return CELLTYPE_EDIT;
      37             :         case element_type_formula:
      38          12 :             return CELLTYPE_FORMULA;
      39             :         default:
      40             :             ;
      41             :     }
      42             : 
      43           0 :     return CELLTYPE_NONE;
      44             : }
      45             : 
      46             : }
      47             : 
      48          16 : CellValueSpan::CellValueSpan( SCROW nRow1, SCROW nRow2, CellType eType ) :
      49          16 :     mnRow1(nRow1), mnRow2(nRow2), meType(eType) {}
      50             : 
      51          44 : struct CellValuesImpl : boost::noncopyable
      52             : {
      53             :     CellStoreType maCells;
      54             :     CellTextAttrStoreType maCellTextAttrs;
      55             :     CellStoreType::iterator miCellPos;
      56             :     CellTextAttrStoreType::iterator miAttrPos;
      57             : };
      58             : 
      59          22 : CellValues::CellValues() :
      60          22 :     mpImpl(new CellValuesImpl) {}
      61             : 
      62          22 : CellValues::~CellValues()
      63             : {
      64          22 :     delete mpImpl;
      65          22 : }
      66             : 
      67           0 : void CellValues::transferFrom( ScColumn& rCol, SCROW nRow, size_t nLen )
      68             : {
      69           0 :     mpImpl->maCells.resize(nLen);
      70           0 :     mpImpl->maCellTextAttrs.resize(nLen);
      71           0 :     rCol.maCells.transfer(nRow, nRow+nLen-1, mpImpl->maCells, 0);
      72           0 :     rCol.maCellTextAttrs.transfer(nRow, nRow+nLen-1, mpImpl->maCellTextAttrs, 0);
      73           0 : }
      74             : 
      75           0 : void CellValues::transferTo( ScColumn& rCol, SCROW nRow )
      76             : {
      77             :     assert(mpImpl->maCells.size() == mpImpl->maCellTextAttrs.size());
      78             : 
      79           0 :     size_t nLen = mpImpl->maCells.size();
      80           0 :     mpImpl->maCells.transfer(0, nLen-1, rCol.maCells, nRow);
      81           0 :     mpImpl->maCellTextAttrs.transfer(0, nLen-1, rCol.maCellTextAttrs, nRow);
      82           0 : }
      83             : 
      84           0 : void CellValues::copyTo( ScColumn& rCol, SCROW nRow ) const
      85             : {
      86           0 :     copyCellsTo(rCol, nRow);
      87           0 :     copyCellTextAttrsTo(rCol, nRow);
      88           0 : }
      89             : 
      90          20 : void CellValues::swapNonEmpty( ScColumn& rCol )
      91             : {
      92          20 :     std::vector<BlockPos> aBlocksToSwap;
      93             : 
      94             :     {
      95             :         // Go through static value blocks and record their positions and sizes.
      96          20 :         sc::CellStoreType::const_iterator it = mpImpl->maCells.begin(), itEnd = mpImpl->maCells.end();
      97          88 :         for (; it != itEnd; ++it)
      98             :         {
      99          68 :             if (it->type == sc::element_type_empty)
     100          44 :                 continue;
     101             : 
     102             :             BlockPos aPos;
     103          24 :             aPos.mnStart = it->position;
     104          24 :             aPos.mnEnd = aPos.mnStart + it->size - 1;
     105          24 :             aBlocksToSwap.push_back(aPos);
     106             :         }
     107             :     }
     108             : 
     109             :     // Do the swapping.  The undo storage will store the replaced formula cells after this.
     110          20 :     std::vector<BlockPos>::const_iterator it = aBlocksToSwap.begin(), itEnd = aBlocksToSwap.end();
     111          44 :     for (; it != itEnd; ++it)
     112             :     {
     113          24 :         rCol.maCells.swap(it->mnStart, it->mnEnd, mpImpl->maCells, it->mnStart);
     114          24 :         rCol.maCellTextAttrs.swap(it->mnStart, it->mnEnd, mpImpl->maCellTextAttrs, it->mnStart);
     115          20 :     }
     116          20 : }
     117             : 
     118           0 : void CellValues::assign( const std::vector<double>& rVals )
     119             : {
     120           0 :     mpImpl->maCells.resize(rVals.size());
     121           0 :     mpImpl->maCells.set(0, rVals.begin(), rVals.end());
     122             : 
     123             :     // Set default text attributes.
     124           0 :     std::vector<CellTextAttr> aDefaults(rVals.size(), CellTextAttr());
     125           0 :     mpImpl->maCellTextAttrs.resize(rVals.size());
     126           0 :     mpImpl->maCellTextAttrs.set(0, aDefaults.begin(), aDefaults.end());
     127           0 : }
     128             : 
     129           0 : size_t CellValues::size() const
     130             : {
     131             :     assert(mpImpl->maCells.size() == mpImpl->maCellTextAttrs.size());
     132           0 :     return mpImpl->maCells.size();
     133             : }
     134             : 
     135           6 : void CellValues::reset( size_t nSize )
     136             : {
     137           6 :     mpImpl->maCells.clear();
     138           6 :     mpImpl->maCells.resize(nSize);
     139           6 :     mpImpl->maCellTextAttrs.clear();
     140           6 :     mpImpl->maCellTextAttrs.resize(nSize);
     141             : 
     142           6 :     mpImpl->miCellPos = mpImpl->maCells.begin();
     143           6 :     mpImpl->miAttrPos = mpImpl->maCellTextAttrs.begin();
     144           6 : }
     145             : 
     146          12 : void CellValues::setValue( size_t nRow, double fVal )
     147             : {
     148          12 :     mpImpl->miCellPos = mpImpl->maCells.set(mpImpl->miCellPos, nRow, fVal);
     149          12 :     mpImpl->miAttrPos = mpImpl->maCellTextAttrs.set(mpImpl->miAttrPos, nRow, sc::CellTextAttr());
     150          12 : }
     151             : 
     152           0 : void CellValues::setValue( size_t nRow, const svl::SharedString& rStr )
     153             : {
     154           0 :     mpImpl->miCellPos = mpImpl->maCells.set(mpImpl->miCellPos, nRow, rStr);
     155           0 :     mpImpl->miAttrPos = mpImpl->maCellTextAttrs.set(mpImpl->miAttrPos, nRow, sc::CellTextAttr());
     156           0 : }
     157             : 
     158          12 : void CellValues::swap( CellValues& r )
     159             : {
     160          12 :     std::swap(mpImpl, r.mpImpl);
     161          12 : }
     162             : 
     163          14 : std::vector<CellValueSpan> CellValues::getNonEmptySpans() const
     164             : {
     165          14 :     std::vector<CellValueSpan> aRet;
     166          14 :     CellStoreType::const_iterator it = mpImpl->maCells.begin(), itEnd = mpImpl->maCells.end();
     167          60 :     for (; it != itEnd; ++it)
     168             :     {
     169          46 :         if (it->type != element_type_empty)
     170             :         {
     171             :             // Record this span.
     172          16 :             size_t nRow1 = it->position;
     173          16 :             size_t nRow2 = nRow1 + it->size - 1;
     174          16 :             aRet.push_back(CellValueSpan(nRow1, nRow2, toCellType(it->type)));
     175             :         }
     176             :     }
     177          14 :     return aRet;
     178             : }
     179             : 
     180           0 : void CellValues::copyCellsTo( ScColumn& rCol, SCROW nRow ) const
     181             : {
     182           0 :     CellStoreType& rDest = rCol.maCells;
     183           0 :     const CellStoreType& rSrc = mpImpl->maCells;
     184             : 
     185             :     // Caller must ensure the destination is long enough.
     186             :     assert(rSrc.size() + static_cast<size_t>(nRow) < rDest.size());
     187             : 
     188           0 :     SCROW nCurRow = nRow;
     189           0 :     CellStoreType::iterator itPos = rDest.begin();
     190             : 
     191           0 :     CellStoreType::const_iterator itBlk = rSrc.begin(), itBlkEnd = rSrc.end();
     192           0 :     for (; itBlk != itBlkEnd; ++itBlk)
     193             :     {
     194           0 :         switch (itBlk->type)
     195             :         {
     196             :             case element_type_numeric:
     197             :             {
     198           0 :                 numeric_block::const_iterator it = numeric_block::begin(*itBlk->data);
     199           0 :                 numeric_block::const_iterator itEnd = numeric_block::end(*itBlk->data);
     200           0 :                 itPos = rDest.set(itPos, nCurRow, it, itEnd);
     201             :             }
     202           0 :             break;
     203             :             case element_type_string:
     204             :             {
     205           0 :                 string_block::const_iterator it = string_block::begin(*itBlk->data);
     206           0 :                 string_block::const_iterator itEnd = string_block::end(*itBlk->data);
     207           0 :                 itPos = rDest.set(itPos, nCurRow, it, itEnd);
     208             :             }
     209           0 :             break;
     210             :             case element_type_edittext:
     211             :             {
     212           0 :                 edittext_block::const_iterator it = edittext_block::begin(*itBlk->data);
     213           0 :                 edittext_block::const_iterator itEnd = edittext_block::end(*itBlk->data);
     214           0 :                 std::vector<EditTextObject*> aVals;
     215           0 :                 aVals.reserve(itBlk->size);
     216           0 :                 for (; it != itEnd; ++it)
     217             :                 {
     218           0 :                     const EditTextObject* p = *it;
     219           0 :                     aVals.push_back(p->Clone());
     220             :                 }
     221           0 :                 itPos = rDest.set(itPos, nCurRow, aVals.begin(), aVals.end());
     222             :             }
     223           0 :             break;
     224             :             case element_type_formula:
     225             :             {
     226           0 :                 formula_block::const_iterator it = formula_block::begin(*itBlk->data);
     227           0 :                 formula_block::const_iterator itEnd = formula_block::end(*itBlk->data);
     228           0 :                 std::vector<ScFormulaCell*> aVals;
     229           0 :                 aVals.reserve(itBlk->size);
     230           0 :                 for (; it != itEnd; ++it)
     231             :                 {
     232           0 :                     const ScFormulaCell* p = *it;
     233           0 :                     aVals.push_back(p->Clone());
     234             :                 }
     235           0 :                 itPos = rDest.set(itPos, nCurRow, aVals.begin(), aVals.end());
     236             :             }
     237           0 :             break;
     238             :             default:
     239           0 :                 itPos = rDest.set_empty(itPos, nCurRow, nCurRow+itBlk->size-1);
     240             :         }
     241             : 
     242           0 :         nCurRow += itBlk->size;
     243             :     }
     244           0 : }
     245             : 
     246           0 : void CellValues::copyCellTextAttrsTo( ScColumn& rCol, SCROW nRow ) const
     247             : {
     248           0 :     CellTextAttrStoreType& rDest = rCol.maCellTextAttrs;
     249           0 :     const CellTextAttrStoreType& rSrc = mpImpl->maCellTextAttrs;
     250             : 
     251             :     // Caller must ensure the destination is long enough.
     252             :     assert(rSrc.size() + static_cast<size_t>(nRow) < rDest.size());
     253             : 
     254           0 :     SCROW nCurRow = nRow;
     255           0 :     CellTextAttrStoreType::iterator itPos = rDest.begin();
     256             : 
     257           0 :     CellTextAttrStoreType::const_iterator itBlk = rSrc.begin(), itBlkEnd = rSrc.end();
     258           0 :     for (; itBlk != itBlkEnd; ++itBlk)
     259             :     {
     260           0 :         switch (itBlk->type)
     261             :         {
     262             :             case element_type_celltextattr:
     263             :             {
     264           0 :                 celltextattr_block::const_iterator it = celltextattr_block::begin(*itBlk->data);
     265           0 :                 celltextattr_block::const_iterator itEnd = celltextattr_block::end(*itBlk->data);
     266           0 :                 itPos = rDest.set(itPos, nCurRow, it, itEnd);
     267             :             }
     268           0 :             break;
     269             :             default:
     270           0 :                 itPos = rDest.set_empty(itPos, nCurRow, nCurRow+itBlk->size-1);
     271             :         }
     272             : 
     273           0 :         nCurRow += itBlk->size;
     274             :     }
     275           0 : }
     276             : 
     277             : typedef boost::ptr_vector<CellValues> TableType;
     278             : typedef boost::ptr_vector<TableType> TablesType;
     279             : 
     280           8 : struct TableValues::Impl
     281             : {
     282             :     ScRange maRange;
     283             :     TablesType maTables;
     284             : 
     285           8 :     Impl( const ScRange& rRange ) : maRange(rRange)
     286             :     {
     287           8 :         size_t nTabs = rRange.aEnd.Tab() - rRange.aStart.Tab() + 1;
     288           8 :         size_t nCols = rRange.aEnd.Col() - rRange.aStart.Col() + 1;
     289             : 
     290          16 :         for (size_t nTab = 0; nTab < nTabs; ++nTab)
     291             :         {
     292           8 :             maTables.push_back(new TableType);
     293           8 :             TableType& rTab = maTables.back();
     294          18 :             for (size_t nCol = 0; nCol < nCols; ++nCol)
     295          10 :                 rTab.push_back(new CellValues);
     296             :         }
     297           8 :     }
     298             : 
     299          34 :     CellValues* getCellValues( SCTAB nTab, SCCOL nCol )
     300             :     {
     301          34 :         if (nTab < maRange.aStart.Tab() || maRange.aEnd.Tab() < nTab)
     302             :             // sheet index out of bound.
     303           0 :             return NULL;
     304             : 
     305          34 :         if (nCol < maRange.aStart.Col() || maRange.aEnd.Col() < nCol)
     306             :             // column index out of bound.
     307           0 :             return NULL;
     308             : 
     309          34 :         size_t nTabOffset = nTab - maRange.aStart.Tab();
     310          34 :         if (nTabOffset >= maTables.size())
     311           0 :             return NULL;
     312             : 
     313          34 :         TableType& rTab = maTables[nTab-maRange.aStart.Tab()];
     314             : 
     315          34 :         size_t nColOffset = nCol - maRange.aStart.Col();
     316          34 :         if (nColOffset >= rTab.size())
     317           0 :             return NULL;
     318             : 
     319          34 :         return &rTab[nColOffset];
     320             :     }
     321             : };
     322             : 
     323           4 : TableValues::TableValues() :
     324           4 :     mpImpl(new Impl(ScRange(ScAddress::INITIALIZE_INVALID))) {}
     325             : 
     326           4 : TableValues::TableValues( const ScRange& rRange ) :
     327           4 :     mpImpl(new Impl(rRange)) {}
     328             : 
     329           8 : TableValues::~TableValues()
     330             : {
     331           8 :     delete mpImpl;
     332           8 : }
     333             : 
     334          54 : const ScRange& TableValues::getRange() const
     335             : {
     336          54 :     return mpImpl->maRange;
     337             : }
     338             : 
     339           6 : void TableValues::swap( SCTAB nTab, SCCOL nCol, CellValues& rColValue )
     340             : {
     341           6 :     CellValues* pCol = mpImpl->getCellValues(nTab, nCol);
     342           6 :     if (!pCol)
     343           6 :         return;
     344             : 
     345           6 :     pCol->swap(rColValue);
     346             : }
     347             : 
     348          14 : void TableValues::swapNonEmpty( SCTAB nTab, SCCOL nCol, ScColumn& rCol )
     349             : {
     350          14 :     CellValues* pCol = mpImpl->getCellValues(nTab, nCol);
     351          14 :     if (!pCol)
     352          14 :         return;
     353             : 
     354          14 :     pCol->swapNonEmpty(rCol);
     355             : }
     356             : 
     357          14 : std::vector<CellValueSpan> TableValues::getNonEmptySpans( SCTAB nTab, SCCOL nCol ) const
     358             : {
     359          14 :     std::vector<CellValueSpan> aRet;
     360          14 :     CellValues* pCol = mpImpl->getCellValues(nTab, nCol);
     361          14 :     if (pCol)
     362          14 :         aRet = pCol->getNonEmptySpans();
     363             : 
     364          14 :     return aRet;
     365             : }
     366             : 
     367           4 : void TableValues::swap( TableValues& rOther )
     368             : {
     369           4 :     std::swap(mpImpl, rOther.mpImpl);
     370           4 : }
     371             : 
     372         228 : }
     373             : 
     374             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10