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

Generated by: LCOV version 1.11