LCOV - code coverage report
Current view: top level - sc/source/core/data - grouptokenconverter.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 0 117 0.0 %
Date: 2014-04-11 Functions: 0 5 0.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 <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 :         const ScToken* pToken = static_cast<const ScToken*>(p);
     100           0 :         SCROW nLen = mrCell.GetCellGroup()->mnLength;
     101           0 :         switch (pToken->GetType())
     102             :         {
     103             :             case svSingleRef:
     104             :             {
     105           0 :                 ScSingleRefData aRef = pToken->GetSingleRef();
     106           0 :                 ScAddress aRefPos = aRef.toAbs(mrPos);
     107           0 :                 if (aRef.IsRowRel())
     108             :                 {
     109           0 :                     if (isSelfReferenceRelative(aRefPos, aRef.Row()))
     110           0 :                         return false;
     111             : 
     112             :                     // Trim data array length to actual data range.
     113           0 :                     SCROW nTrimLen = trimLength(aRefPos.Tab(), aRefPos.Col(), aRefPos.Col(), aRefPos.Row(), nLen);
     114             :                     // Fetch double array guarantees that the length of the
     115             :                     // returned array equals or greater than the requested
     116             :                     // length.
     117             : 
     118           0 :                     formula::VectorRefArray aArray;
     119           0 :                     if (nTrimLen)
     120           0 :                         aArray = mrDoc.FetchVectorRefArray(aRefPos, nTrimLen);
     121             : 
     122           0 :                     formula::SingleVectorRefToken aTok(aArray, nLen, nTrimLen);
     123           0 :                     mrGroupTokens.AddToken(aTok);
     124             :                 }
     125             :                 else
     126             :                 {
     127             :                     // Absolute row reference.
     128           0 :                     if (isSelfReferenceAbsolute(aRefPos))
     129           0 :                         return false;
     130             : 
     131           0 :                     formula::FormulaTokenRef pNewToken = mrDoc.ResolveStaticReference(aRefPos);
     132           0 :                     if (!pNewToken)
     133           0 :                         return false;
     134             : 
     135           0 :                     mrGroupTokens.AddToken(*pNewToken);
     136             :                 }
     137             :             }
     138           0 :             break;
     139             :             case svDoubleRef:
     140             :             {
     141           0 :                 ScComplexRefData aRef = pToken->GetDoubleRef();
     142           0 :                 ScRange aAbs = aRef.toAbs(mrPos);
     143             : 
     144             :                 // Check for self reference.
     145           0 :                 if (aRef.Ref1.IsRowRel())
     146             :                 {
     147           0 :                     if (isSelfReferenceRelative(aAbs.aStart, aRef.Ref1.Row()))
     148           0 :                         return false;
     149             :                 }
     150           0 :                 else if (isSelfReferenceAbsolute(aAbs.aStart))
     151           0 :                     return false;
     152             : 
     153           0 :                 if (aRef.Ref2.IsRowRel())
     154             :                 {
     155           0 :                     if (isSelfReferenceRelative(aAbs.aEnd, aRef.Ref2.Row()))
     156           0 :                         return false;
     157             :                 }
     158           0 :                 else if (isSelfReferenceAbsolute(aAbs.aEnd))
     159           0 :                     return false;
     160             : 
     161             :                 // Row reference is relative.
     162           0 :                 bool bAbsFirst = !aRef.Ref1.IsRowRel();
     163           0 :                 bool bAbsLast = !aRef.Ref2.IsRowRel();
     164           0 :                 ScAddress aRefPos = aAbs.aStart;
     165           0 :                 size_t nCols = aAbs.aEnd.Col() - aAbs.aStart.Col() + 1;
     166           0 :                 std::vector<formula::VectorRefArray> aArrays;
     167           0 :                 aArrays.reserve(nCols);
     168           0 :                 SCROW nRefRowSize = aAbs.aEnd.Row() - aAbs.aStart.Row() + 1;
     169           0 :                 SCROW nArrayLength = nRefRowSize;
     170           0 :                 if (!bAbsLast)
     171             :                 {
     172             :                     // range end position is relative. Extend the array length.
     173           0 :                     SCROW nLastRefRowOffset = aAbs.aEnd.Row() - mrPos.Row();
     174           0 :                     SCROW nLastRefRow = mrPos.Row() + nLen - 1 + nLastRefRowOffset;
     175           0 :                     SCROW nNewLength = nLastRefRow - aAbs.aStart.Row() + 1;
     176           0 :                     if (nNewLength > nArrayLength)
     177           0 :                         nArrayLength = nNewLength;
     178             :                 }
     179             : 
     180             :                 // Trim trailing empty rows.
     181           0 :                 SCROW nRequestedLength = nArrayLength; // keep the original length.
     182           0 :                 nArrayLength = trimLength(aRefPos.Tab(), aAbs.aStart.Col(), aAbs.aEnd.Col(), aRefPos.Row(), nArrayLength);
     183             : 
     184           0 :                 for (SCCOL i = aAbs.aStart.Col(); i <= aAbs.aEnd.Col(); ++i)
     185             :                 {
     186           0 :                     aRefPos.SetCol(i);
     187           0 :                     formula::VectorRefArray aArray;
     188           0 :                     if (nArrayLength)
     189           0 :                         aArray = mrDoc.FetchVectorRefArray(aRefPos, nArrayLength);
     190             : 
     191           0 :                     aArrays.push_back(aArray);
     192             :                 }
     193             : 
     194           0 :                 formula::DoubleVectorRefToken aTok(aArrays, nRequestedLength, nArrayLength, nRefRowSize, bAbsFirst, bAbsLast);
     195           0 :                 mrGroupTokens.AddToken(aTok);
     196             :             }
     197           0 :             break;
     198             :             case svIndex:
     199             :             {
     200             :                 // Named range.
     201           0 :                 ScRangeName* pNames = mrDoc.GetRangeName();
     202           0 :                 if (!pNames)
     203             :                     // This should never fail.
     204           0 :                     return false;
     205             : 
     206           0 :                 ScRangeData* pRange = pNames->findByIndex(p->GetIndex());
     207           0 :                 if (!pRange)
     208             :                     // No named range exists by that index.
     209           0 :                     return false;
     210             : 
     211           0 :                 ScTokenArray* pNamedTokens = pRange->GetCode();
     212           0 :                 if (!pNamedTokens)
     213             :                     // This named range is empty.
     214           0 :                     return false;
     215             : 
     216           0 :                 mrGroupTokens.AddOpCode(ocOpen);
     217             : 
     218           0 :                 if (!convert(*pNamedTokens))
     219           0 :                     return false;
     220             : 
     221           0 :                 mrGroupTokens.AddOpCode(ocClose);
     222             :             }
     223           0 :             break;
     224             :             default:
     225           0 :                 mrGroupTokens.AddToken(*pToken);
     226             :         }
     227             :     }
     228             : 
     229           0 :     ScCompiler aComp(&mrDoc, mrPos, mrGroupTokens);
     230           0 :     aComp.SetGrammar(mrDoc.GetGrammar());
     231           0 :     aComp.CompileTokenArray(); // Regenerate RPN tokens.
     232             : 
     233           0 :     return true;
     234             : }
     235             : 
     236             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10