LCOV - code coverage report
Current view: top level - sc/source/core/data - grouptokenconverter.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 1 118 0.8 %
Date: 2014-11-03 Functions: 2 7 28.6 %
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 <formula/token.hxx>
      11             : #include <formula/vectortoken.hxx>
      12             : 
      13             : #include "compiler.hxx"
      14             : #include "grouptokenconverter.hxx"
      15             : 
      16             : using namespace formula;
      17             : 
      18           0 : bool ScGroupTokenConverter::isSelfReferenceRelative(const ScAddress& rRefPos, SCROW nRelRow)
      19             : {
      20           0 :     if (rRefPos.Col() != mrPos.Col())
      21           0 :         return false;
      22             : 
      23           0 :     SCROW nLen = mrCell.GetCellGroup()->mnLength;
      24           0 :     SCROW nEndRow = mrPos.Row() + nLen - 1;
      25             : 
      26           0 :     if (nRelRow < 0)
      27             :     {
      28           0 :         SCROW nTest = nEndRow;
      29           0 :         nTest += nRelRow;
      30           0 :         if (nTest >= mrPos.Row())
      31           0 :             return true;
      32             :     }
      33           0 :     else if (nRelRow > 0)
      34             :     {
      35           0 :         SCROW nTest = mrPos.Row(); // top row.
      36           0 :         nTest += nRelRow;
      37           0 :         if (nTest <= nEndRow)
      38           0 :             return true;
      39             :     }
      40             : 
      41           0 :     return false;
      42             : }
      43             : 
      44           0 : bool ScGroupTokenConverter::isSelfReferenceAbsolute(const ScAddress& rRefPos)
      45             : {
      46           0 :     if (rRefPos.Col() != mrPos.Col())
      47           0 :         return false;
      48             : 
      49           0 :     SCROW nLen = mrCell.GetCellGroup()->mnLength;
      50           0 :     SCROW nEndRow = mrPos.Row() + nLen - 1;
      51             : 
      52           0 :     if (rRefPos.Row() < mrPos.Row())
      53           0 :         return false;
      54             : 
      55           0 :     if (rRefPos.Row() > nEndRow)
      56           0 :         return false;
      57             : 
      58           0 :     return true;
      59             : }
      60             : 
      61           0 : SCROW ScGroupTokenConverter::trimLength(SCTAB nTab, SCCOL nCol1, SCCOL nCol2, SCROW nRow, SCROW nRowLen)
      62             : {
      63           0 :     SCROW nLastRow = nRow + nRowLen - 1; // current last row.
      64           0 :     nLastRow = mrDoc.GetLastDataRow(nTab, nCol1, nCol2, nLastRow);
      65           0 :     if (nLastRow < (nRow + nRowLen - 1))
      66           0 :         nRowLen = nLastRow - nRow + 1;
      67           0 :     else if (nLastRow == 0)
      68             :         // Column is empty.
      69           0 :         nRowLen = 1;
      70             : 
      71           0 :     return nRowLen;
      72             : }
      73             : 
      74           0 : ScGroupTokenConverter::ScGroupTokenConverter(ScTokenArray& rGroupTokens, ScDocument& rDoc, ScFormulaCell& rCell, const ScAddress& rPos) :
      75           0 :         mrGroupTokens(rGroupTokens), mrDoc(rDoc), mrCell(rCell), mrPos(rPos)
      76             : 
      77             : {
      78           0 : }
      79             : 
      80           0 : bool ScGroupTokenConverter::convert(ScTokenArray& rCode)
      81             : {
      82             : #if 0
      83             :     { // debug to start with:
      84             :         ScCompiler aComp( &mrDoc, mrPos, rCode);
      85             :         aComp.SetGrammar(formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1);
      86             :         OUStringBuffer aAsString;
      87             :         aComp.CreateStringFromTokenArray(aAsString);
      88             :     }
      89             : #endif
      90             : 
      91           0 :     rCode.Reset();
      92           0 :     for (const formula::FormulaToken* p = rCode.First(); p; p = rCode.Next())
      93             :     {
      94             :         // A reference can be either absolute or relative.  If it's absolute,
      95             :         // convert it to a static value token.  If relative, convert it to a
      96             :         // vector reference token.  Note: we only care about relative vs
      97             :         // absolute reference state for row directions.
      98             : 
      99           0 :         SCROW nLen = mrCell.GetCellGroup()->mnLength;
     100           0 :         switch (p->GetType())
     101             :         {
     102             :             case svSingleRef:
     103             :             {
     104           0 :                 ScSingleRefData aRef = *p->GetSingleRef();
     105           0 :                 ScAddress aRefPos = aRef.toAbs(mrPos);
     106           0 :                 if (aRef.IsRowRel())
     107             :                 {
     108           0 :                     if (isSelfReferenceRelative(aRefPos, aRef.Row()))
     109           0 :                         return false;
     110             : 
     111             :                     // Trim data array length to actual data range.
     112           0 :                     SCROW nTrimLen = trimLength(aRefPos.Tab(), aRefPos.Col(), aRefPos.Col(), aRefPos.Row(), nLen);
     113             :                     // Fetch double array guarantees that the length of the
     114             :                     // returned array equals or greater than the requested
     115             :                     // length.
     116             : 
     117           0 :                     formula::VectorRefArray aArray;
     118           0 :                     if (nTrimLen)
     119           0 :                         aArray = mrDoc.FetchVectorRefArray(aRefPos, nTrimLen);
     120             : 
     121           0 :                     if (!aArray.isValid())
     122           0 :                         return false;
     123             : 
     124           0 :                     formula::SingleVectorRefToken aTok(aArray, nLen, nTrimLen);
     125           0 :                     mrGroupTokens.AddToken(aTok);
     126             :                 }
     127             :                 else
     128             :                 {
     129             :                     // Absolute row reference.
     130           0 :                     if (isSelfReferenceAbsolute(aRefPos))
     131           0 :                         return false;
     132             : 
     133           0 :                     formula::FormulaTokenRef pNewToken = mrDoc.ResolveStaticReference(aRefPos);
     134           0 :                     if (!pNewToken)
     135           0 :                         return false;
     136             : 
     137           0 :                     mrGroupTokens.AddToken(*pNewToken);
     138             :                 }
     139             :             }
     140           0 :             break;
     141             :             case svDoubleRef:
     142             :             {
     143           0 :                 ScComplexRefData aRef = *p->GetDoubleRef();
     144           0 :                 ScRange aAbs = aRef.toAbs(mrPos);
     145             : 
     146             :                 // Check for self reference.
     147           0 :                 if (aRef.Ref1.IsRowRel())
     148             :                 {
     149           0 :                     if (isSelfReferenceRelative(aAbs.aStart, aRef.Ref1.Row()))
     150           0 :                         return false;
     151             :                 }
     152           0 :                 else if (isSelfReferenceAbsolute(aAbs.aStart))
     153           0 :                     return false;
     154             : 
     155           0 :                 if (aRef.Ref2.IsRowRel())
     156             :                 {
     157           0 :                     if (isSelfReferenceRelative(aAbs.aEnd, aRef.Ref2.Row()))
     158           0 :                         return false;
     159             :                 }
     160           0 :                 else if (isSelfReferenceAbsolute(aAbs.aEnd))
     161           0 :                     return false;
     162             : 
     163             :                 // Row reference is relative.
     164           0 :                 bool bAbsFirst = !aRef.Ref1.IsRowRel();
     165           0 :                 bool bAbsLast = !aRef.Ref2.IsRowRel();
     166           0 :                 ScAddress aRefPos = aAbs.aStart;
     167           0 :                 size_t nCols = aAbs.aEnd.Col() - aAbs.aStart.Col() + 1;
     168           0 :                 std::vector<formula::VectorRefArray> aArrays;
     169           0 :                 aArrays.reserve(nCols);
     170           0 :                 SCROW nRefRowSize = aAbs.aEnd.Row() - aAbs.aStart.Row() + 1;
     171           0 :                 SCROW nArrayLength = nRefRowSize;
     172           0 :                 if (!bAbsLast)
     173             :                 {
     174             :                     // range end position is relative. Extend the array length.
     175           0 :                     SCROW nLastRefRowOffset = aAbs.aEnd.Row() - mrPos.Row();
     176           0 :                     SCROW nLastRefRow = mrPos.Row() + nLen - 1 + nLastRefRowOffset;
     177           0 :                     SCROW nNewLength = nLastRefRow - aAbs.aStart.Row() + 1;
     178           0 :                     if (nNewLength > nArrayLength)
     179           0 :                         nArrayLength = nNewLength;
     180             :                 }
     181             : 
     182             :                 // Trim trailing empty rows.
     183           0 :                 SCROW nRequestedLength = nArrayLength; // keep the original length.
     184           0 :                 nArrayLength = trimLength(aRefPos.Tab(), aAbs.aStart.Col(), aAbs.aEnd.Col(), aRefPos.Row(), nArrayLength);
     185             : 
     186           0 :                 for (SCCOL i = aAbs.aStart.Col(); i <= aAbs.aEnd.Col(); ++i)
     187             :                 {
     188           0 :                     aRefPos.SetCol(i);
     189           0 :                     formula::VectorRefArray aArray;
     190           0 :                     if (nArrayLength)
     191           0 :                         aArray = mrDoc.FetchVectorRefArray(aRefPos, nArrayLength);
     192             : 
     193           0 :                     if (!aArray.isValid())
     194           0 :                         return false;
     195             : 
     196           0 :                     aArrays.push_back(aArray);
     197             :                 }
     198             : 
     199           0 :                 formula::DoubleVectorRefToken aTok(aArrays, nRequestedLength, nArrayLength, nRefRowSize, bAbsFirst, bAbsLast);
     200           0 :                 mrGroupTokens.AddToken(aTok);
     201             :             }
     202           0 :             break;
     203             :             case svIndex:
     204             :             {
     205             :                 // Named range.
     206           0 :                 ScRangeName* pNames = mrDoc.GetRangeName();
     207           0 :                 if (!pNames)
     208             :                     // This should never fail.
     209           0 :                     return false;
     210             : 
     211           0 :                 ScRangeData* pRange = pNames->findByIndex(p->GetIndex());
     212           0 :                 if (!pRange)
     213             :                     // No named range exists by that index.
     214           0 :                     return false;
     215             : 
     216           0 :                 ScTokenArray* pNamedTokens = pRange->GetCode();
     217           0 :                 if (!pNamedTokens)
     218             :                     // This named range is empty.
     219           0 :                     return false;
     220             : 
     221           0 :                 mrGroupTokens.AddOpCode(ocOpen);
     222             : 
     223           0 :                 if (!convert(*pNamedTokens))
     224           0 :                     return false;
     225             : 
     226           0 :                 mrGroupTokens.AddOpCode(ocClose);
     227             :             }
     228           0 :             break;
     229             :             default:
     230           0 :                 mrGroupTokens.AddToken(*p);
     231             :         }
     232             :     }
     233             : 
     234           0 :     return true;
     235         228 : }
     236             : 
     237             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10