LCOV - code coverage report
Current view: top level - sc/source/core/data - dpcache.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 396 525 75.4 %
Date: 2012-08-25 Functions: 62 63 98.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 278 695 40.0 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright IBM Corporation 2009.
       7                 :            :  * Copyright 2009 by Sun Microsystems, Inc.
       8                 :            :  *
       9                 :            :  * OpenOffice.org - a multi-platform office productivity suite
      10                 :            :  *
      11                 :            :  * This file is part of OpenOffice.org.
      12                 :            :  *
      13                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      14                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      15                 :            :  * only, as published by the Free Software Foundation.
      16                 :            :  *
      17                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      18                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      19                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      20                 :            :  * GNU Lesser General Public License version 3 for more details
      21                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      22                 :            :  *
      23                 :            :  * You should have received a copy of the GNU Lesser General Public License
      24                 :            :  * version 3 along with OpenOffice.org.  If not, see
      25                 :            :  * <http://www.openoffice.org/license.html>
      26                 :            :  * for a copy of the LGPLv3 License.
      27                 :            :  *
      28                 :            :  ************************************************************************/
      29                 :            : 
      30                 :            : #include "dpcache.hxx"
      31                 :            : 
      32                 :            : #include "document.hxx"
      33                 :            : #include "queryentry.hxx"
      34                 :            : #include "queryparam.hxx"
      35                 :            : #include "dpglobal.hxx"
      36                 :            : #include "dpobject.hxx"
      37                 :            : #include "globstr.hrc"
      38                 :            : #include "docoptio.hxx"
      39                 :            : #include "dpitemdata.hxx"
      40                 :            : #include "dputil.hxx"
      41                 :            : #include "dpnumgroupinfo.hxx"
      42                 :            : 
      43                 :            : #include <rtl/math.hxx>
      44                 :            : #include <unotools/textsearch.hxx>
      45                 :            : #include <unotools/localedatawrapper.hxx>
      46                 :            : #include <svl/zforlist.hxx>
      47                 :            : 
      48                 :            : #include <memory>
      49                 :            : 
      50                 :            : using namespace ::com::sun::star;
      51                 :            : 
      52                 :            : using ::com::sun::star::uno::Exception;
      53                 :            : using ::com::sun::star::uno::Reference;
      54                 :            : using ::com::sun::star::uno::UNO_QUERY;
      55                 :            : using ::com::sun::star::uno::UNO_QUERY_THROW;
      56                 :            : 
      57 [ +  - ][ +  - ]:         17 : ScDPCache::GroupItems::GroupItems() : mnGroupType(0) {}
      58                 :            : 
      59                 :          6 : ScDPCache::GroupItems::GroupItems(const ScDPNumGroupInfo& rInfo, sal_Int32 nGroupType) :
      60 [ +  - ][ +  - ]:          6 :     maInfo(rInfo), mnGroupType(nGroupType) {}
      61                 :            : 
      62 [ +  - ][ +  - ]:        309 : ScDPCache::Field::Field() : mnNumFormat(0) {}
      63                 :            : 
      64                 :         95 : ScDPCache::ScDPCache(ScDocument* pDoc) :
      65                 :            :     mpDoc( pDoc ),
      66                 :            :     mnColumnCount ( 0 ),
      67                 :            :     maEmptyRows(0, MAXROW, true),
      68 [ +  - ][ +  - ]:         95 :     mbDisposing(false)
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
      69                 :            : {
      70                 :         95 : }
      71                 :            : 
      72                 :            : namespace {
      73                 :            : 
      74                 :            : struct ClearObjectSource : std::unary_function<ScDPObject*, void>
      75                 :            : {
      76                 :         17 :     void operator() (ScDPObject* p) const
      77                 :            :     {
      78                 :         17 :         p->ClearTableData();
      79                 :         17 :     }
      80                 :            : };
      81                 :            : 
      82                 :            : }
      83                 :            : 
      84 [ +  - ][ +  - ]:         95 : ScDPCache::~ScDPCache()
         [ +  - ][ +  - ]
      85                 :            : {
      86                 :            :     // Make sure no live ScDPObject instances hold reference to this cache any
      87                 :            :     // more.
      88                 :         95 :     mbDisposing = true;
      89         [ +  - ]:         95 :     std::for_each(maRefObjects.begin(), maRefObjects.end(), ClearObjectSource());
      90                 :         95 : }
      91                 :            : 
      92                 :            : namespace {
      93                 :            : 
      94                 :            : /**
      95                 :            :  * While the macro interpret level is incremented, the formula cells are
      96                 :            :  * (semi-)guaranteed to be interpreted.
      97                 :            :  */
      98                 :            : class MacroInterpretIncrementer
      99                 :            : {
     100                 :            : public:
     101                 :        103 :     MacroInterpretIncrementer(ScDocument* pDoc) :
     102                 :        103 :         mpDoc(pDoc)
     103                 :            :     {
     104                 :        103 :         mpDoc->IncMacroInterpretLevel();
     105                 :        103 :     }
     106                 :        103 :     ~MacroInterpretIncrementer()
     107                 :            :     {
     108                 :        103 :         mpDoc->DecMacroInterpretLevel();
     109                 :        103 :     }
     110                 :            : private:
     111                 :            :     ScDocument* mpDoc;
     112                 :            : };
     113                 :            : 
     114                 :        309 : rtl::OUString createLabelString(ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab)
     115                 :            : {
     116                 :        309 :     rtl::OUString aDocStr = pDoc->GetString(nCol, nRow, nTab);
     117         [ +  + ]:        309 :     if (aDocStr.isEmpty())
     118                 :            :     {
     119                 :            :         // Replace an empty label string with column name.
     120                 :         39 :         rtl::OUStringBuffer aBuf;
     121 [ +  - ][ +  - ]:         39 :         aBuf.append(ScGlobal::GetRscString(STR_COLUMN));
                 [ +  - ]
     122         [ +  - ]:         39 :         aBuf.append(sal_Unicode(' '));
     123                 :            : 
     124                 :         39 :         ScAddress aColAddr(nCol, 0, 0);
     125                 :         39 :         rtl::OUString aColStr;
     126         [ +  - ]:         39 :         aColAddr.Format(aColStr, SCA_VALID_COL, NULL);
     127         [ +  - ]:         39 :         aBuf.append(aColStr);
     128         [ +  - ]:         39 :         aDocStr = aBuf.makeStringAndClear();
     129                 :            :     }
     130                 :        309 :     return aDocStr;
     131                 :            : }
     132                 :            : 
     133                 :       1657 : void initFromCell(
     134                 :            :     ScDPCache& rCache, ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab,
     135                 :            :     ScDPItemData& rData, sal_uLong& rNumFormat)
     136                 :            : {
     137         [ +  - ]:       1657 :     rtl::OUString aDocStr = pDoc->GetString(nCol, nRow, nTab);
     138                 :       1657 :     rNumFormat = 0;
     139                 :            : 
     140                 :       1657 :     ScAddress aPos(nCol, nRow, nTab);
     141                 :            : 
     142 [ -  + ][ +  - ]:       1657 :     if (pDoc->GetErrCode(aPos))
     143                 :            :     {
     144 [ #  # ][ #  # ]:          0 :         rData.SetErrorString(rCache.InternString(aDocStr));
     145                 :            :     }
     146 [ +  - ][ +  + ]:       1657 :     else if (pDoc->HasValueData(nCol, nRow, nTab))
     147                 :            :     {
     148         [ +  - ]:       1083 :         double fVal = pDoc->GetValue(aPos);
     149         [ +  - ]:       1083 :         rNumFormat = pDoc->GetNumberFormat(aPos);
     150         [ +  - ]:       1083 :         rData.SetValue(fVal);
     151                 :            :     }
     152 [ +  - ][ +  + ]:        574 :     else if (pDoc->HasData(nCol, nRow, nTab))
     153                 :            :     {
     154 [ +  - ][ +  - ]:        454 :         rData.SetString(rCache.InternString(aDocStr));
     155                 :            :     }
     156                 :            :     else
     157         [ +  - ]:       1657 :         rData.SetEmpty();
     158                 :       1657 : }
     159                 :            : 
     160                 :      19149 : struct Bucket
     161                 :            : {
     162                 :            :     ScDPItemData maValue;
     163                 :            :     SCROW mnOrderIndex;
     164                 :            :     SCROW mnDataIndex;
     165                 :            :     SCROW mnValueSortIndex;
     166                 :       1657 :     Bucket(const ScDPItemData& rValue, SCROW nOrder, SCROW nData) :
     167                 :       1657 :         maValue(rValue), mnOrderIndex(nOrder), mnDataIndex(nData), mnValueSortIndex(0) {}
     168                 :            : };
     169                 :            : 
     170                 :            : struct LessByValue : std::binary_function<Bucket, Bucket, bool>
     171                 :            : {
     172                 :       3100 :     bool operator() (const Bucket& left, const Bucket& right) const
     173                 :            :     {
     174                 :       3100 :         return left.maValue < right.maValue;
     175                 :            :     }
     176                 :            : };
     177                 :            : 
     178                 :            : struct LessByValueSortIndex : std::binary_function<Bucket, Bucket, bool>
     179                 :            : {
     180                 :       3100 :     bool operator() (const Bucket& left, const Bucket& right) const
     181                 :            :     {
     182                 :       3100 :         return left.mnValueSortIndex < right.mnValueSortIndex;
     183                 :            :     }
     184                 :            : };
     185                 :            : 
     186                 :            : struct LessByDataIndex : std::binary_function<Bucket, Bucket, bool>
     187                 :            : {
     188                 :       3121 :     bool operator() (const Bucket& left, const Bucket& right) const
     189                 :            :     {
     190                 :       3121 :         return left.mnDataIndex < right.mnDataIndex;
     191                 :            :     }
     192                 :            : };
     193                 :            : 
     194                 :            : struct EqualByValue : std::binary_function<Bucket, Bucket, bool>
     195                 :            : {
     196                 :       1367 :     bool operator() (const Bucket& left, const Bucket& right) const
     197                 :            :     {
     198                 :       1367 :         return left.maValue.IsCaseInsEqual(right.maValue);
     199                 :            :     }
     200                 :            : };
     201                 :            : 
     202                 :            : class PushBackValue : std::unary_function<Bucket, void>
     203                 :            : {
     204                 :            :     ScDPCache::ItemsType& mrItems;
     205                 :            : public:
     206                 :        290 :     PushBackValue(ScDPCache::ItemsType& _items) : mrItems(_items) {}
     207                 :       1342 :     void operator() (const Bucket& v)
     208                 :            :     {
     209                 :       1342 :         mrItems.push_back(v.maValue);
     210                 :       1342 :     }
     211                 :            : };
     212                 :            : 
     213                 :            : class PushBackOrderIndex : std::unary_function<Bucket, void>
     214                 :            : {
     215                 :            :     ScDPCache::IndexArrayType& mrData;
     216                 :            : public:
     217                 :        290 :     PushBackOrderIndex(ScDPCache::IndexArrayType& _items) : mrData(_items) {}
     218                 :       1657 :     void operator() (const Bucket& v)
     219                 :            :     {
     220                 :       1657 :         mrData.push_back(v.mnOrderIndex);
     221                 :       1657 :     }
     222                 :            : };
     223                 :            : 
     224                 :            : class TagValueSortOrder : std::unary_function<Bucket, void>
     225                 :            : {
     226                 :            :     SCROW mnCurIndex;
     227                 :            : public:
     228                 :        290 :     TagValueSortOrder() : mnCurIndex(0) {}
     229                 :       1657 :     void operator() (Bucket& v)
     230                 :            :     {
     231                 :       1657 :         v.mnValueSortIndex = mnCurIndex++;
     232                 :       1657 :     }
     233                 :            : };
     234                 :            : 
     235                 :        309 : void processBuckets(std::vector<Bucket>& aBuckets, ScDPCache::Field& rField)
     236                 :            : {
     237         [ +  + ]:        309 :     if (aBuckets.empty())
     238                 :        309 :         return;
     239                 :            : 
     240                 :            :     // Sort by the value.
     241         [ +  - ]:        290 :     std::sort(aBuckets.begin(), aBuckets.end(), LessByValue());
     242                 :            : 
     243                 :            :     // Remember this sort order.
     244         [ +  - ]:        290 :     std::for_each(aBuckets.begin(), aBuckets.end(), TagValueSortOrder());
     245                 :            : 
     246                 :            :     {
     247                 :            :         // Set order index such that unique values have identical index value.
     248                 :        290 :         SCROW nCurIndex = 0;
     249                 :        290 :         std::vector<Bucket>::iterator it = aBuckets.begin(), itEnd = aBuckets.end();
     250         [ +  - ]:        290 :         ScDPItemData aPrev = it->maValue;
     251                 :        290 :         it->mnOrderIndex = nCurIndex;
     252 [ +  - ][ +  + ]:       1657 :         for (++it; it != itEnd; ++it)
     253                 :            :         {
     254 [ +  - ][ +  + ]:       1367 :             if (!aPrev.IsCaseInsEqual(it->maValue))
     255                 :       1052 :                 ++nCurIndex;
     256                 :            : 
     257                 :       1367 :             it->mnOrderIndex = nCurIndex;
     258         [ +  - ]:       1367 :             aPrev = it->maValue;
     259         [ +  - ]:        290 :         }
     260                 :            :     }
     261                 :            : 
     262                 :            :     // Re-sort the bucket this time by the data index.
     263         [ +  - ]:        290 :     std::sort(aBuckets.begin(), aBuckets.end(), LessByDataIndex());
     264                 :            : 
     265                 :            :     // Copy the order index series into the field object.
     266         [ +  - ]:        290 :     rField.maData.reserve(aBuckets.size());
     267         [ +  - ]:        290 :     std::for_each(aBuckets.begin(), aBuckets.end(), PushBackOrderIndex(rField.maData));
     268                 :            : 
     269                 :            :     // Sort by the value again.
     270         [ +  - ]:        290 :     std::sort(aBuckets.begin(), aBuckets.end(), LessByValueSortIndex());
     271                 :            : 
     272                 :            :     // Unique by value.
     273                 :            :     std::vector<Bucket>::iterator itUniqueEnd =
     274         [ +  - ]:        290 :         std::unique(aBuckets.begin(), aBuckets.end(), EqualByValue());
     275                 :            : 
     276                 :            :     // Copy the unique values into items.
     277                 :        290 :     std::vector<Bucket>::iterator itBeg = aBuckets.begin();
     278         [ +  - ]:        290 :     size_t nLen = distance(itBeg, itUniqueEnd);
     279         [ +  - ]:        290 :     rField.maItems.reserve(nLen);
     280         [ +  - ]:        309 :     std::for_each(itBeg, itUniqueEnd, PushBackValue(rField.maItems));
     281                 :            : }
     282                 :            : 
     283                 :            : }
     284                 :            : 
     285                 :        103 : bool ScDPCache::InitFromDoc(ScDocument* pDoc, const ScRange& rRange)
     286                 :            : {
     287         [ +  - ]:        103 :     Clear();
     288                 :            : 
     289                 :            :     // Make sure the formula cells within the data range are interpreted
     290                 :            :     // during this call, for this method may be called from the interpretation
     291                 :            :     // of GETPIVOTDATA, which disables nested formula interpretation without
     292                 :            :     // increasing the macro level.
     293                 :        103 :     MacroInterpretIncrementer aMacroInc(pDoc);
     294                 :            : 
     295                 :        103 :     SCROW nStartRow = rRange.aStart.Row();  // start of data
     296                 :        103 :     SCROW nEndRow = rRange.aEnd.Row();
     297                 :        103 :     sal_uInt16 nStartCol = rRange.aStart.Col();
     298                 :        103 :     sal_uInt16 nEndCol = rRange.aEnd.Col();
     299                 :        103 :     sal_uInt16 nDocTab = rRange.aStart.Tab();
     300                 :            : 
     301                 :        103 :     mnColumnCount = nEndCol - nStartCol + 1;
     302                 :            : 
     303         [ +  - ]:        103 :     maFields.reserve(mnColumnCount);
     304         [ +  + ]:        412 :     for (size_t i = 0; i < static_cast<size_t>(mnColumnCount); ++i)
     305 [ +  - ][ +  - ]:        309 :         maFields.push_back(new Field);
                 [ +  - ]
     306                 :            : 
     307         [ +  - ]:        103 :     maLabelNames.reserve(mnColumnCount+1);
     308                 :            : 
     309         [ +  - ]:        103 :     ScDPItemData aData;
     310         [ +  + ]:        412 :     for (sal_uInt16 nCol = nStartCol; nCol <= nEndCol; ++nCol)
     311                 :            :     {
     312 [ +  - ][ +  - ]:        309 :         AddLabel(createLabelString(pDoc, nCol, nStartRow, nDocTab));
     313         [ +  - ]:        309 :         Field& rField = maFields[nCol-nStartCol];
     314         [ +  - ]:        309 :         std::vector<Bucket> aBuckets;
     315         [ +  - ]:        309 :         aBuckets.reserve(nEndRow-nStartRow); // skip the topmost label cell.
     316                 :            : 
     317                 :            :         // Push back all original values.
     318                 :        309 :         SCROW nOffset = nStartRow + 1;
     319         [ +  + ]:       1966 :         for (SCROW i = 0, n = nEndRow-nStartRow; i < n; ++i)
     320                 :            :         {
     321                 :       1657 :             SCROW nRow = i + nOffset;
     322                 :       1657 :             sal_uLong nNumFormat = 0;
     323         [ +  - ]:       1657 :             initFromCell(*this, pDoc, nCol, nRow, nDocTab, aData, nNumFormat);
     324 [ +  - ][ +  - ]:       1657 :             aBuckets.push_back(Bucket(aData, 0, i));
                 [ +  - ]
     325                 :            : 
     326 [ +  - ][ +  + ]:       1657 :             if (!aData.IsEmpty())
     327                 :            :             {
     328         [ +  - ]:       1537 :                 maEmptyRows.insert_back(i, i+1, false);
     329                 :       1537 :                 rField.mnNumFormat = nNumFormat;
     330                 :            :             }
     331                 :            :         }
     332                 :            : 
     333         [ +  - ]:        309 :         processBuckets(aBuckets, rField);
     334                 :        309 :     }
     335                 :            : 
     336         [ +  - ]:        103 :     PostInit();
     337         [ +  - ]:        103 :     return true;
     338                 :            : }
     339                 :            : 
     340                 :          0 : bool ScDPCache::InitFromDataBase(DBConnector& rDB)
     341                 :            : {
     342                 :          0 :     Clear();
     343                 :            : 
     344                 :            :     try
     345                 :            :     {
     346         [ #  # ]:          0 :         mnColumnCount = rDB.getColumnCount();
     347         [ #  # ]:          0 :         maFields.clear();
     348         [ #  # ]:          0 :         maFields.reserve(mnColumnCount);
     349         [ #  # ]:          0 :         for (size_t i = 0; i < static_cast<size_t>(mnColumnCount); ++i)
     350 [ #  # ][ #  # ]:          0 :             maFields.push_back(new Field);
                 [ #  # ]
     351                 :            : 
     352                 :            :         // Get column titles and types.
     353                 :          0 :         maLabelNames.clear();
     354         [ #  # ]:          0 :         maLabelNames.reserve(mnColumnCount+1);
     355                 :            : 
     356         [ #  # ]:          0 :         std::vector<sal_Int32> aColTypes(mnColumnCount);
     357                 :            : 
     358         [ #  # ]:          0 :         for (sal_Int32 nCol = 0; nCol < mnColumnCount; ++nCol)
     359                 :            :         {
     360         [ #  # ]:          0 :             rtl::OUString aColTitle = rDB.getColumnLabel(nCol);
     361         [ #  # ]:          0 :             AddLabel(aColTitle);
     362                 :          0 :         }
     363                 :            : 
     364         [ #  # ]:          0 :         std::vector<Bucket> aBuckets;
     365         [ #  # ]:          0 :         ScDPItemData aData;
     366         [ #  # ]:          0 :         for (sal_Int32 nCol = 0; nCol < mnColumnCount; ++nCol)
     367                 :            :         {
     368 [ #  # ][ #  # ]:          0 :             if (!rDB.first())
     369                 :          0 :                 continue;
     370                 :            : 
     371                 :          0 :             aBuckets.clear();
     372         [ #  # ]:          0 :             Field& rField = maFields[nCol];
     373                 :          0 :             SCROW nRow = 0;
     374 [ #  # ][ #  # ]:          0 :             do
     375                 :            :             {
     376                 :          0 :                 short nFormatType = NUMBERFORMAT_UNDEFINED;
     377         [ #  # ]:          0 :                 aData.SetEmpty();
     378         [ #  # ]:          0 :                 rDB.getValue(nCol, aData, nFormatType);
     379 [ #  # ][ #  # ]:          0 :                 aBuckets.push_back(Bucket(aData, 0, nRow));
                 [ #  # ]
     380 [ #  # ][ #  # ]:          0 :                 if (!aData.IsEmpty())
     381                 :            :                 {
     382         [ #  # ]:          0 :                     maEmptyRows.insert_back(nRow, nRow+1, false);
     383         [ #  # ]:          0 :                     SvNumberFormatter* pFormatter = mpDoc->GetFormatTable();
     384 [ #  # ][ #  # ]:          0 :                     rField.mnNumFormat = pFormatter ? pFormatter->GetStandardFormat(nFormatType) : 0;
     385                 :            :                 }
     386                 :            : 
     387                 :          0 :                 ++nRow;
     388                 :            :             }
     389                 :          0 :             while (rDB.next());
     390                 :            : 
     391         [ #  # ]:          0 :             processBuckets(aBuckets, rField);
     392                 :            :         }
     393                 :            : 
     394         [ #  # ]:          0 :         rDB.finish();
     395                 :            : 
     396         [ #  # ]:          0 :         PostInit();
     397 [ #  # ][ #  # ]:          0 :         return true;
     398                 :            :     }
     399                 :          0 :     catch (const Exception&)
     400                 :            :     {
     401                 :          0 :         return false;
     402                 :            :     }
     403                 :            : }
     404                 :            : 
     405                 :       3825 : bool ScDPCache::ValidQuery( SCROW nRow, const ScQueryParam &rParam) const
     406                 :            : {
     407 [ +  - ][ -  + ]:       3825 :     if (!rParam.GetEntryCount())
     408                 :          0 :         return true;
     409                 :            : 
     410 [ +  - ][ +  + ]:       3825 :     if (!rParam.GetEntry(0).bDoQuery)
     411                 :       3115 :         return true;
     412                 :            : 
     413         [ +  - ]:        710 :     bool bMatchWholeCell = mpDoc->GetDocOptions().IsMatchWholeCell();
     414                 :            : 
     415         [ +  - ]:        710 :     SCSIZE nEntryCount = rParam.GetEntryCount();
     416         [ +  - ]:        710 :     std::vector<bool> aPassed(nEntryCount, false);
     417                 :            : 
     418                 :        710 :     long nPos = -1;
     419                 :            :     CollatorWrapper* pCollator = (rParam.bCaseSens ? ScGlobal::GetCaseCollator() :
     420 [ #  # ][ +  - ]:        710 :                                   ScGlobal::GetCollator() );
                 [ -  + ]
     421                 :            :     ::utl::TransliterationWrapper* pTransliteration = (rParam.bCaseSens ?
     422 [ -  + ][ #  # ]:        710 :                                                        ScGlobal::GetCaseTransliteration() : ScGlobal::GetpTransliteration());
                 [ +  - ]
     423                 :            : 
     424 [ +  - ][ +  - ]:       2010 :     for (size_t i = 0; i < nEntryCount && rParam.GetEntry(i).bDoQuery; ++i)
         [ +  + ][ +  + ]
     425                 :            :     {
     426         [ +  - ]:       1300 :         const ScQueryEntry& rEntry = rParam.GetEntry(i);
     427         [ +  - ]:       1300 :         const ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
     428                 :            :         // we can only handle one single direct query
     429                 :            :         // #i115431# nField in QueryParam is the sheet column, not the field within the source range
     430                 :       1300 :         SCCOL nQueryCol = (SCCOL)rEntry.nField;
     431         [ -  + ]:       1300 :         if ( nQueryCol < rParam.nCol1 )
     432                 :          0 :             nQueryCol = rParam.nCol1;
     433         [ -  + ]:       1300 :         if ( nQueryCol > rParam.nCol2 )
     434                 :          0 :             nQueryCol = rParam.nCol2;
     435                 :       1300 :         SCCOL nSourceField = nQueryCol - rParam.nCol1;
     436         [ +  - ]:       1300 :         SCROW nId = GetItemDataId( nSourceField, nRow, false );
     437         [ +  - ]:       1300 :         const ScDPItemData* pCellData = GetItemDataById( nSourceField, nId );
     438                 :            : 
     439                 :       1300 :         bool bOk = false;
     440                 :            : 
     441 [ +  - ][ -  + ]:       1300 :         if (rEntry.GetQueryItem().meType == ScQueryEntry::ByEmpty)
     442                 :            :         {
     443 [ #  # ][ #  # ]:          0 :             if (rEntry.IsQueryByEmpty())
     444         [ #  # ]:          0 :                 bOk = pCellData->IsEmpty();
     445                 :            :             else
     446                 :            :             {
     447                 :            :                 OSL_ASSERT(rEntry.IsQueryByNonEmpty());
     448         [ #  # ]:          0 :                 bOk = !pCellData->IsEmpty();
     449                 :            :             }
     450                 :            :         }
     451 [ +  - ][ +  - ]:       1300 :         else if (rEntry.GetQueryItem().meType != ScQueryEntry::ByString && pCellData->IsValue())
         [ +  - ][ +  + ]
                 [ +  + ]
     452                 :            :         {   // by Value
     453         [ +  - ]:       1220 :             double nCellVal = pCellData->GetValue();
     454                 :            : 
     455   [ +  -  +  +  :       1220 :             switch (rEntry.eOp)
                -  -  - ]
     456                 :            :             {
     457                 :            :                 case SC_EQUAL :
     458                 :        120 :                     bOk = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
     459                 :        120 :                     break;
     460                 :            :                 case SC_LESS :
     461 [ #  # ][ #  # ]:          0 :                     bOk = (nCellVal < rItem.mfVal) && !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
     462                 :          0 :                     break;
     463                 :            :                 case SC_GREATER :
     464 [ +  + ][ +  - ]:        550 :                     bOk = (nCellVal > rItem.mfVal) && !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
     465                 :        550 :                     break;
     466                 :            :                 case SC_LESS_EQUAL :
     467 [ +  + ][ -  + ]:        550 :                     bOk = (nCellVal < rItem.mfVal) || ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
     468                 :        550 :                     break;
     469                 :            :                 case SC_GREATER_EQUAL :
     470 [ #  # ][ #  # ]:          0 :                     bOk = (nCellVal > rItem.mfVal) || ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
     471                 :          0 :                     break;
     472                 :            :                 case SC_NOT_EQUAL :
     473                 :          0 :                     bOk = !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
     474                 :          0 :                     break;
     475                 :            :                 default:
     476                 :          0 :                     bOk= false;
     477                 :       1220 :                     break;
     478                 :            :             }
     479                 :            :         }
     480 [ +  - ][ +  - ]:        160 :         else if ((rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL)
         [ -  + ][ #  # ]
                 [ -  + ]
     481         [ +  - ]:         80 :                  || (rEntry.GetQueryItem().meType == ScQueryEntry::ByString
     482         [ #  # ]:          0 :                      && pCellData->HasStringData() )
     483                 :            :                 )
     484                 :            :         {   // by String
     485 [ #  # ][ #  # ]:          0 :             String  aCellStr = pCellData->GetString();
     486                 :            : 
     487                 :            :             bool bRealRegExp = (rParam.bRegExp && ((rEntry.eOp == SC_EQUAL)
     488 [ #  # ][ #  # ]:          0 :                                                    || (rEntry.eOp == SC_NOT_EQUAL)));
                 [ #  # ]
     489                 :          0 :             bool bTestRegExp = false;
     490 [ #  # ][ #  # ]:          0 :             if (bRealRegExp || bTestRegExp)
     491                 :            :             {
     492                 :          0 :                 xub_StrLen nStart = 0;
     493                 :          0 :                 xub_StrLen nEnd   = aCellStr.Len();
     494                 :            :                 bool bMatch = (bool) rEntry.GetSearchTextPtr( rParam.bCaseSens )
     495 [ #  # ][ #  # ]:          0 :                               ->SearchFrwrd( aCellStr, &nStart, &nEnd );
     496                 :            :                 // from 614 on, nEnd is behind the found text
     497 [ #  # ][ #  # ]:          0 :                 if (bMatch && bMatchWholeCell
           [ #  #  #  # ]
                 [ #  # ]
     498                 :          0 :                     && (nStart != 0 || nEnd != aCellStr.Len()))
     499                 :          0 :                     bMatch = false;    // RegExp must match entire cell string
     500         [ #  # ]:          0 :                 if (bRealRegExp)
     501         [ #  # ]:          0 :                     bOk = ((rEntry.eOp == SC_NOT_EQUAL) ? !bMatch : bMatch);
     502                 :            :             }
     503         [ #  # ]:          0 :             if (!bRealRegExp)
     504                 :            :             {
     505 [ #  # ][ #  # ]:          0 :                 if (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL)
     506                 :            :                 {
     507         [ #  # ]:          0 :                     if (bMatchWholeCell)
     508                 :            :                     {
     509 [ #  # ][ #  # ]:          0 :                         String aStr = rEntry.GetQueryItem().maString;
     510         [ #  # ]:          0 :                         bOk = pTransliteration->isEqual(aCellStr, aStr);
     511                 :          0 :                         bool bHasStar = false;
     512                 :            :                         xub_StrLen nIndex;
     513 [ #  # ][ #  # ]:          0 :                         if (( nIndex = aStr.Search('*') ) != STRING_NOTFOUND)
     514                 :          0 :                             bHasStar = sal_True;
     515 [ #  # ][ #  # ]:          0 :                         if (bHasStar && (nIndex>0))
     516                 :            :                         {
     517 [ #  # ][ #  # ]:          0 :                             for (i=0;(i<nIndex) && (i< aCellStr.Len()) ; i++)
                 [ #  # ]
     518                 :            :                             {
     519         [ #  # ]:          0 :                                 if (aCellStr.GetChar( (sal_uInt16)i ) == aStr.GetChar((sal_uInt16) i ))
     520                 :            :                                 {
     521                 :          0 :                                     bOk=1;
     522                 :            :                                 }
     523                 :            :                                 else
     524                 :            :                                 {
     525                 :          0 :                                     bOk=0;
     526                 :          0 :                                     break;
     527                 :            :                                 }
     528                 :            :                             }
     529         [ #  # ]:          0 :                         }
     530                 :            :                     }
     531                 :            :                     else
     532                 :            :                     {
     533         [ #  # ]:          0 :                         const rtl::OUString& rQueryStr = rEntry.GetQueryItem().maString;
     534         [ #  # ]:          0 :                         ::com::sun::star::uno::Sequence< sal_Int32 > xOff;
     535                 :            :                         String aCell = pTransliteration->transliterate(
     536         [ #  # ]:          0 :                             aCellStr, ScGlobal::eLnge, 0, aCellStr.Len(), &xOff);
     537                 :            :                         String aQuer = pTransliteration->transliterate(
     538 [ #  # ][ #  # ]:          0 :                             rQueryStr, ScGlobal::eLnge, 0, rQueryStr.getLength(), &xOff);
                 [ #  # ]
     539 [ #  # ][ #  # ]:          0 :                         bOk = (aCell.Search( aQuer ) != STRING_NOTFOUND);
         [ #  # ][ #  # ]
     540                 :            :                     }
     541         [ #  # ]:          0 :                     if (rEntry.eOp == SC_NOT_EQUAL)
     542                 :          0 :                         bOk = !bOk;
     543                 :            :                 }
     544                 :            :                 else
     545                 :            :                 {   // use collator here because data was probably sorted
     546                 :            :                     sal_Int32 nCompare = pCollator->compareString(
     547 [ #  # ][ #  # ]:          0 :                         aCellStr, rEntry.GetQueryItem().maString);
                 [ #  # ]
     548   [ #  #  #  #  :          0 :                     switch (rEntry.eOp)
                   #  # ]
     549                 :            :                     {
     550                 :            :                         case SC_LESS :
     551                 :          0 :                             bOk = (nCompare < 0);
     552                 :          0 :                             break;
     553                 :            :                         case SC_GREATER :
     554                 :          0 :                             bOk = (nCompare > 0);
     555                 :          0 :                             break;
     556                 :            :                         case SC_LESS_EQUAL :
     557                 :          0 :                             bOk = (nCompare <= 0);
     558                 :          0 :                             break;
     559                 :            :                         case SC_GREATER_EQUAL :
     560                 :          0 :                             bOk = (nCompare >= 0);
     561                 :          0 :                             break;
     562                 :            :                         case SC_NOT_EQUAL:
     563                 :            :                             OSL_FAIL("SC_NOT_EQUAL");
     564                 :          0 :                             break;
     565                 :            :                         case SC_TOPVAL:
     566                 :            :                         case SC_BOTVAL:
     567                 :            :                         case SC_TOPPERC:
     568                 :            :                         case SC_BOTPERC:
     569                 :            :                         default:
     570                 :          0 :                             break;
     571                 :            :                     }
     572                 :            :                 }
     573         [ #  # ]:          0 :             }
     574                 :            :         }
     575                 :            : 
     576         [ +  + ]:       1300 :         if (nPos == -1)
     577                 :            :         {
     578                 :        710 :             nPos++;
     579         [ +  - ]:        710 :             aPassed[nPos] = bOk;
     580                 :            :         }
     581                 :            :         else
     582                 :            :         {
     583         [ +  - ]:        590 :             if (rEntry.eConnect == SC_AND)
     584                 :            :             {
     585 [ +  - ][ +  + ]:        590 :                 aPassed[nPos] = aPassed[nPos] && bOk;
         [ +  + ][ +  - ]
         [ +  - ][ #  # ]
     586                 :            :             }
     587                 :            :             else
     588                 :            :             {
     589                 :          0 :                 nPos++;
     590         [ #  # ]:          0 :                 aPassed[nPos] = bOk;
     591                 :            :             }
     592                 :            :         }
     593                 :            :     }
     594                 :            : 
     595         [ -  + ]:        710 :     for (long j=1; j <= nPos; j++)
     596 [ #  # ][ #  # ]:          0 :         aPassed[0] = aPassed[0] || aPassed[j];
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
           [ #  #  #  # ]
     597                 :            : 
     598         [ +  - ]:        710 :     bool bRet = aPassed[0];
     599                 :       3825 :     return bRet;
     600                 :            : }
     601                 :            : 
     602                 :         72 : bool ScDPCache::IsRowEmpty(SCROW nRow) const
     603                 :            : {
     604                 :         72 :     bool bEmpty = true;
     605         [ +  - ]:         72 :     maEmptyRows.search_tree(nRow, bEmpty);
     606                 :         72 :     return bEmpty;
     607                 :            : }
     608                 :            : 
     609                 :         84 : const ScDPCache::GroupItems* ScDPCache::GetGroupItems(long nDim) const
     610                 :            : {
     611         [ -  + ]:         84 :     if (nDim < 0)
     612                 :          0 :         return NULL;
     613                 :            : 
     614                 :         84 :     long nSourceCount = static_cast<long>(maFields.size());
     615         [ +  + ]:         84 :     if (nDim < nSourceCount)
     616                 :         45 :         return maFields[nDim].mpGroup.get();
     617                 :            : 
     618                 :         39 :     nDim -= nSourceCount;
     619         [ +  - ]:         39 :     if (nDim < static_cast<long>(maGroupFields.size()))
     620                 :         39 :         return &maGroupFields[nDim];
     621                 :            : 
     622                 :         84 :     return NULL;
     623                 :            : }
     624                 :            : 
     625                 :      36838 : rtl::OUString ScDPCache::GetDimensionName(LabelsType::size_type nDim) const
     626                 :            : {
     627                 :            :     OSL_ENSURE(nDim < maLabelNames.size()-1 , "ScDPTableDataCache::GetDimensionName");
     628                 :            :     OSL_ENSURE(maLabelNames.size() == static_cast <sal_uInt16> (mnColumnCount+1), "ScDPTableDataCache::GetDimensionName");
     629                 :            : 
     630         [ +  - ]:      36838 :     if ( nDim+1 < maLabelNames.size() )
     631                 :            :     {
     632                 :      36838 :         return maLabelNames[nDim+1];
     633                 :            :     }
     634                 :            :     else
     635                 :      36838 :         return rtl::OUString();
     636                 :            : }
     637                 :            : 
     638                 :            : namespace {
     639                 :            : 
     640                 :            : typedef boost::unordered_set<rtl::OUString, rtl::OUStringHash> LabelSet;
     641                 :            : 
     642                 :            : class InsertLabel : public std::unary_function<rtl::OUString, void>
     643                 :            : {
     644                 :            :     LabelSet& mrNames;
     645                 :            : public:
     646                 :        309 :     InsertLabel(LabelSet& rNames) : mrNames(rNames) {}
     647                 :        742 :     void operator() (const rtl::OUString& r)
     648                 :            :     {
     649                 :        742 :         mrNames.insert(r);
     650                 :        742 :     }
     651                 :            : };
     652                 :            : 
     653                 :            : }
     654                 :            : 
     655                 :        103 : void ScDPCache::PostInit()
     656                 :            : {
     657                 :        103 :     maEmptyRows.build_tree();
     658                 :        103 : }
     659                 :            : 
     660                 :        103 : void ScDPCache::Clear()
     661                 :            : {
     662                 :        103 :     maFields.clear();
     663                 :        103 :     maLabelNames.clear();
     664                 :        103 :     maGroupFields.clear();
     665                 :        103 :     maEmptyRows.clear();
     666                 :        103 :     maStringPool.clear();
     667                 :        103 : }
     668                 :            : 
     669                 :        309 : void ScDPCache::AddLabel(const rtl::OUString& rLabel)
     670                 :            : {
     671                 :            : 
     672         [ +  + ]:        309 :     if ( maLabelNames.empty() )
     673 [ +  - ][ +  - ]:        103 :         maLabelNames.push_back(ScGlobal::GetRscString(STR_PIVOT_DATA));
                 [ +  - ]
     674                 :            : 
     675                 :            :     //reset name if needed
     676         [ +  - ]:        309 :     LabelSet aExistingNames;
     677         [ +  - ]:        309 :     std::for_each(maLabelNames.begin(), maLabelNames.end(), InsertLabel(aExistingNames));
     678                 :        309 :     sal_Int32 nSuffix = 1;
     679                 :        309 :     rtl::OUString aNewName = rLabel;
     680                 :          0 :     while (true)
     681                 :            :     {
     682 [ +  - ][ +  - ]:        309 :         if (!aExistingNames.count(aNewName))
     683                 :            :         {
     684                 :            :             // unique name found!
     685         [ +  - ]:        309 :             maLabelNames.push_back(aNewName);
     686                 :        309 :             return;
     687                 :            :         }
     688                 :            : 
     689                 :            :         // Name already exists.
     690         [ #  # ]:          0 :         rtl::OUStringBuffer aBuf(rLabel);
     691         [ #  # ]:          0 :         aBuf.append(++nSuffix);
     692         [ #  # ]:          0 :         aNewName = aBuf.makeStringAndClear();
     693         [ +  - ]:        309 :     }
     694                 :            : }
     695                 :            : 
     696                 :       8882 : SCROW ScDPCache::GetItemDataId(sal_uInt16 nDim, SCROW nRow, bool bRepeatIfEmpty) const
     697                 :            : {
     698                 :            :     OSL_ENSURE(nDim < mnColumnCount, "ScDPTableDataCache::GetItemDataId ");
     699                 :            : 
     700                 :       8882 :     const Field& rField = maFields[nDim];
     701         [ -  + ]:       8882 :     if (bRepeatIfEmpty)
     702                 :            :     {
     703 [ #  # ][ #  # ]:          0 :         while (nRow > 0 && rField.maItems[rField.maData[nRow]].IsEmpty())
                 [ #  # ]
     704                 :          0 :             --nRow;
     705                 :            :     }
     706                 :            : 
     707                 :       8882 :     return rField.maData[nRow];
     708                 :            : }
     709                 :            : 
     710                 :      14284 : const ScDPItemData* ScDPCache::GetItemDataById(long nDim, SCROW nId) const
     711                 :            : {
     712 [ +  - ][ -  + ]:      14284 :     if (nDim < 0 || nId < 0)
     713                 :          0 :         return NULL;
     714                 :            : 
     715                 :      14284 :     size_t nSourceCount = maFields.size();
     716                 :      14284 :     size_t nDimPos = static_cast<size_t>(nDim);
     717                 :      14284 :     size_t nItemId = static_cast<size_t>(nId);
     718         [ +  + ]:      14284 :     if (nDimPos < nSourceCount)
     719                 :            :     {
     720                 :            :         // source field.
     721                 :      13703 :         const Field& rField = maFields[nDimPos];
     722         [ +  + ]:      13703 :         if (nItemId < rField.maItems.size())
     723                 :      13265 :             return &rField.maItems[nItemId];
     724                 :            : 
     725         [ +  + ]:        438 :         if (!rField.mpGroup)
     726                 :          9 :             return NULL;
     727                 :            : 
     728                 :        429 :         nItemId -= rField.maItems.size();
     729                 :        429 :         const ItemsType& rGI = rField.mpGroup->maItems;
     730         [ -  + ]:        429 :         if (nItemId >= rGI.size())
     731                 :          0 :             return NULL;
     732                 :            : 
     733                 :        429 :         return &rGI[nItemId];
     734                 :            :     }
     735                 :            : 
     736                 :            :     // Try group fields.
     737                 :        581 :     nDimPos -= nSourceCount;
     738         [ -  + ]:        581 :     if (nDimPos >= maGroupFields.size())
     739                 :          0 :         return NULL;
     740                 :            : 
     741                 :        581 :     const ItemsType& rGI = maGroupFields[nDimPos].maItems;
     742         [ -  + ]:        581 :     if (nItemId >= rGI.size())
     743                 :          0 :         return NULL;
     744                 :            : 
     745                 :      14284 :     return &rGI[nItemId];
     746                 :            : }
     747                 :            : 
     748                 :        976 : SCROW ScDPCache::GetRowCount() const
     749                 :            : {
     750 [ +  - ][ +  + ]:        976 :     if (maFields.empty() || maFields[0].maData.empty())
                 [ +  + ]
     751                 :        342 :         return 0;
     752                 :            : 
     753                 :        976 :     return maFields[0].maData.size();
     754                 :            : }
     755                 :            : 
     756                 :         23 : const ScDPCache::ItemsType& ScDPCache::GetDimMemberValues(SCCOL nDim) const
     757                 :            : {
     758                 :            :     OSL_ENSURE( nDim>=0 && nDim < mnColumnCount ," nDim < mnColumnCount ");
     759                 :         23 :     return maFields.at(nDim).maItems;
     760                 :            : }
     761                 :            : 
     762                 :       1841 : sal_uLong ScDPCache::GetNumberFormat( long nDim ) const
     763                 :            : {
     764         [ -  + ]:       1841 :     if ( nDim >= mnColumnCount )
     765                 :          0 :         return 0;
     766                 :            : 
     767                 :            :     // TODO: Find a way to determine the dominant number format in presence of
     768                 :            :     // multiple number formats in the same field.
     769                 :       1841 :     return maFields[nDim].mnNumFormat;
     770                 :            : }
     771                 :            : 
     772                 :       2653 : bool ScDPCache::IsDateDimension( long nDim ) const
     773                 :            : {
     774         [ -  + ]:       2653 :     if (nDim >= mnColumnCount)
     775                 :          0 :         return false;
     776                 :            : 
     777                 :       2653 :     SvNumberFormatter* pFormatter = mpDoc->GetFormatTable();
     778         [ -  + ]:       2653 :     if (!pFormatter)
     779                 :          0 :         return false;
     780                 :            : 
     781                 :       2653 :     short eType = pFormatter->GetType(maFields[nDim].mnNumFormat);
     782 [ -  + ][ +  + ]:       2653 :     return (eType == NUMBERFORMAT_DATE) || (eType == NUMBERFORMAT_DATETIME);
     783                 :            : }
     784                 :            : 
     785                 :        695 : long ScDPCache::GetDimMemberCount(long nDim) const
     786                 :            : {
     787                 :            :     OSL_ENSURE( nDim>=0 && nDim < mnColumnCount ," ScDPTableDataCache::GetDimMemberCount : out of bound ");
     788                 :        695 :     return maFields[nDim].maItems.size();
     789                 :            : }
     790                 :            : 
     791                 :         23 : SCCOL ScDPCache::GetDimensionIndex(const rtl::OUString& sName) const
     792                 :            : {
     793         [ +  - ]:         23 :     for (size_t i = 1; i < maLabelNames.size(); ++i)
     794                 :            :     {
     795         [ +  - ]:         23 :         if (maLabelNames[i].equals(sName))
     796                 :         23 :             return static_cast<SCCOL>(i-1);
     797                 :            :     }
     798                 :         23 :     return -1;
     799                 :            : }
     800                 :            : 
     801                 :        454 : const rtl::OUString* ScDPCache::InternString(const rtl::OUString& rStr) const
     802                 :            : {
     803         [ +  - ]:        454 :     StringSetType::iterator it = maStringPool.find(rStr);
     804 [ +  - ][ +  + ]:        454 :     if (it != maStringPool.end())
     805                 :            :         // In the pool.
     806         [ +  - ]:        135 :         return &(*it);
     807                 :            : 
     808         [ +  - ]:        319 :     std::pair<StringSetType::iterator, bool> r = maStringPool.insert(rStr);
     809 [ +  - ][ +  - ]:        454 :     return r.second ? &(*r.first) : NULL;
     810                 :            : }
     811                 :            : 
     812                 :        117 : void ScDPCache::AddReference(ScDPObject* pObj) const
     813                 :            : {
     814                 :        117 :     maRefObjects.insert(pObj);
     815                 :        117 : }
     816                 :            : 
     817                 :        117 : void ScDPCache::RemoveReference(ScDPObject* pObj) const
     818                 :            : {
     819         [ +  + ]:        117 :     if (mbDisposing)
     820                 :            :         // Object being deleted.
     821                 :        117 :         return;
     822                 :            : 
     823                 :        100 :     maRefObjects.erase(pObj);
     824         [ +  + ]:        100 :     if (maRefObjects.empty())
     825                 :         76 :         mpDoc->GetDPCollection()->RemoveCache(this);
     826                 :            : }
     827                 :            : 
     828                 :          8 : const ScDPCache::ObjectSetType& ScDPCache::GetAllReferences() const
     829                 :            : {
     830                 :          8 :     return maRefObjects;
     831                 :            : }
     832                 :            : 
     833                 :        271 : SCROW ScDPCache::GetIdByItemData(long nDim, const ScDPItemData& rItem) const
     834                 :            : {
     835         [ -  + ]:        271 :     if (nDim < 0)
     836                 :          0 :         return -1;
     837                 :            : 
     838         [ +  + ]:        271 :     if (nDim < mnColumnCount)
     839                 :            :     {
     840                 :            :         // source field.
     841                 :        108 :         const ItemsType& rItems = maFields[nDim].maItems;
     842         [ +  + ]:       1356 :         for (size_t i = 0, n = rItems.size(); i < n; ++i)
     843                 :            :         {
     844         [ +  + ]:       1254 :             if (rItems[i] == rItem)
     845                 :          6 :                 return i;
     846                 :            :         }
     847                 :            : 
     848         [ -  + ]:        102 :         if (!maFields[nDim].mpGroup)
     849                 :          0 :             return -1;
     850                 :            : 
     851                 :            :         // grouped source field.
     852                 :        102 :         const ItemsType& rGI = maFields[nDim].mpGroup->maItems;
     853         [ +  - ]:        390 :         for (size_t i = 0, n = rGI.size(); i < n; ++i)
     854                 :            :         {
     855         [ +  + ]:        390 :             if (rGI[i] == rItem)
     856                 :        102 :                 return rItems.size() + i;
     857                 :            :         }
     858                 :          0 :         return -1;
     859                 :            :     }
     860                 :            : 
     861                 :            :     // group field.
     862                 :        163 :     nDim -= mnColumnCount;
     863         [ +  - ]:        163 :     if (static_cast<size_t>(nDim) < maGroupFields.size())
     864                 :            :     {
     865                 :        163 :         const ItemsType& rGI = maGroupFields[nDim].maItems;
     866         [ +  - ]:        277 :         for (size_t i = 0, n = rGI.size(); i < n; ++i)
     867                 :            :         {
     868         [ +  + ]:        277 :             if (rGI[i] == rItem)
     869                 :        163 :                 return i;
     870                 :            :         }
     871                 :            :     }
     872                 :            : 
     873                 :        271 :     return -1;
     874                 :            : }
     875                 :            : 
     876                 :       2256 : rtl::OUString ScDPCache::GetFormattedString(long nDim, const ScDPItemData& rItem) const
     877                 :            : {
     878         [ +  + ]:       2256 :     if (nDim < 0)
     879                 :        195 :         return rItem.GetString();
     880                 :            : 
     881                 :       2061 :     ScDPItemData::Type eType = rItem.GetType();
     882         [ +  + ]:       2061 :     if (eType == ScDPItemData::Value)
     883                 :            :     {
     884                 :            :         // Format value using the stored number format.
     885                 :       1627 :         sal_uLong nNumFormat = GetNumberFormat(nDim);
     886                 :       1627 :         SvNumberFormatter* pFormatter = mpDoc->GetFormatTable();
     887         [ +  - ]:       1627 :         if (pFormatter)
     888                 :            :         {
     889                 :       1627 :             Color* pColor = NULL;
     890         [ +  - ]:       1627 :             String aStr;
     891 [ +  - ][ +  - ]:       1627 :             pFormatter->GetOutputString(rItem.GetValue(), nNumFormat, aStr, &pColor);
     892 [ +  - ][ +  - ]:       1627 :             return aStr;
     893                 :            :         }
     894                 :            :     }
     895                 :            : 
     896         [ +  + ]:        434 :     if (eType == ScDPItemData::GroupValue)
     897                 :            :     {
     898         [ +  - ]:         69 :         ScDPItemData::GroupValueAttr aAttr = rItem.GetGroupValue();
     899                 :         69 :         double fStart = 0.0, fEnd = 0.0;
     900         [ +  - ]:         69 :         const GroupItems* p = GetGroupItems(nDim);
     901         [ +  - ]:         69 :         if (p)
     902                 :            :         {
     903                 :         69 :             fStart = p->maInfo.mfStart;
     904                 :         69 :             fEnd = p->maInfo.mfEnd;
     905                 :            :         }
     906                 :            :         return ScDPUtil::getDateGroupName(
     907 [ +  - ][ +  - ]:         69 :             aAttr.mnGroupType, aAttr.mnValue, mpDoc->GetFormatTable(), fStart, fEnd);
     908                 :            :     }
     909                 :            : 
     910         [ +  + ]:        365 :     if (eType == ScDPItemData::RangeStart)
     911                 :            :     {
     912                 :         15 :         double fVal = rItem.GetValue();
     913                 :         15 :         const GroupItems* p = GetGroupItems(nDim);
     914         [ -  + ]:         15 :         if (!p)
     915                 :          0 :             return rItem.GetString();
     916                 :            : 
     917                 :         15 :         sal_Unicode cDecSep = ScGlobal::pLocaleData->getNumDecimalSep()[0];
     918                 :         15 :         return ScDPUtil::getNumGroupName(fVal, p->maInfo, cDecSep, mpDoc->GetFormatTable());
     919                 :            :     }
     920                 :            : 
     921                 :       2256 :     return rItem.GetString();
     922                 :            : }
     923                 :            : 
     924                 :         17 : long ScDPCache::AppendGroupField()
     925                 :            : {
     926         [ +  - ]:         17 :     maGroupFields.push_back(new GroupItems);
     927                 :         17 :     return static_cast<long>(maFields.size() + maGroupFields.size() - 1);
     928                 :            : }
     929                 :            : 
     930                 :         23 : void ScDPCache::ResetGroupItems(long nDim, const ScDPNumGroupInfo& rNumInfo, sal_Int32 nGroupType)
     931                 :            : {
     932         [ -  + ]:         23 :     if (nDim < 0)
     933                 :          0 :         return;
     934                 :            : 
     935                 :         23 :     long nSourceCount = static_cast<long>(maFields.size());
     936         [ +  + ]:         23 :     if (nDim < nSourceCount)
     937                 :            :     {
     938         [ +  - ]:          6 :         maFields.at(nDim).mpGroup.reset(new GroupItems(rNumInfo, nGroupType));
     939                 :          6 :         return;
     940                 :            :     }
     941                 :            : 
     942                 :         17 :     nDim -= nSourceCount;
     943         [ +  - ]:         17 :     if (nDim < static_cast<long>(maGroupFields.size()))
     944                 :            :     {
     945                 :         17 :         GroupItems& rGI = maGroupFields[nDim];
     946                 :         17 :         rGI.maItems.clear();
     947                 :         17 :         rGI.maInfo = rNumInfo;
     948                 :         23 :         rGI.mnGroupType = nGroupType;
     949                 :            :     }
     950                 :            : }
     951                 :            : 
     952                 :        122 : SCROW ScDPCache::SetGroupItem(long nDim, const ScDPItemData& rData)
     953                 :            : {
     954         [ -  + ]:        122 :     if (nDim < 0)
     955                 :          0 :         return -1;
     956                 :            : 
     957                 :        122 :     long nSourceCount = static_cast<long>(maFields.size());
     958         [ +  + ]:        122 :     if (nDim < nSourceCount)
     959                 :            :     {
     960                 :         57 :         GroupItems& rGI = *maFields.at(nDim).mpGroup;
     961                 :         57 :         rGI.maItems.push_back(rData);
     962                 :         57 :         SCROW nId = maFields[nDim].maItems.size() + rGI.maItems.size() - 1;
     963                 :         57 :         return nId;
     964                 :            :     }
     965                 :            : 
     966                 :         65 :     nDim -= nSourceCount;
     967         [ +  - ]:         65 :     if (nDim < static_cast<long>(maGroupFields.size()))
     968                 :            :     {
     969                 :         65 :         ItemsType& rItems = maGroupFields.at(nDim).maItems;
     970                 :         65 :         rItems.push_back(rData);
     971                 :         65 :         return rItems.size()-1;
     972                 :            :     }
     973                 :            : 
     974                 :        122 :     return -1;
     975                 :            : }
     976                 :            : 
     977                 :         32 : void ScDPCache::GetGroupDimMemberIds(long nDim, std::vector<SCROW>& rIds) const
     978                 :            : {
     979         [ -  + ]:         32 :     if (nDim < 0)
     980                 :          0 :         return;
     981                 :            : 
     982                 :         32 :     long nSourceCount = static_cast<long>(maFields.size());
     983         [ +  + ]:         32 :     if (nDim < nSourceCount)
     984                 :            :     {
     985         [ -  + ]:          9 :         if (!maFields.at(nDim).mpGroup)
     986                 :          0 :             return;
     987                 :            : 
     988                 :          9 :         size_t nOffset = maFields[nDim].maItems.size();
     989                 :          9 :         const ItemsType& rGI = maFields[nDim].mpGroup->maItems;
     990         [ +  + ]:        108 :         for (size_t i = 0, n = rGI.size(); i < n; ++i)
     991         [ +  - ]:         99 :             rIds.push_back(static_cast<SCROW>(i + nOffset));
     992                 :            : 
     993                 :          9 :         return;
     994                 :            :     }
     995                 :            : 
     996                 :         23 :     nDim -= nSourceCount;
     997         [ +  - ]:         23 :     if (nDim < static_cast<long>(maGroupFields.size()))
     998                 :            :     {
     999                 :         23 :         const ItemsType& rGI = maGroupFields.at(nDim).maItems;
    1000         [ +  + ]:        127 :         for (size_t i = 0, n = rGI.size(); i < n; ++i)
    1001         [ +  - ]:         95 :             rIds.push_back(static_cast<SCROW>(i));
    1002                 :            :     }
    1003                 :            : }
    1004                 :            : 
    1005                 :            : namespace {
    1006                 :            : 
    1007                 :            : struct ClearGroupItems : std::unary_function<ScDPCache::Field, void>
    1008                 :            : {
    1009                 :         49 :     void operator() (ScDPCache::Field& r) const
    1010                 :            :     {
    1011                 :         49 :         r.mpGroup.reset();
    1012                 :         49 :     }
    1013                 :            : };
    1014                 :            : 
    1015                 :            : }
    1016                 :            : 
    1017                 :         17 : void ScDPCache::ClearGroupFields()
    1018                 :            : {
    1019                 :         17 :     maGroupFields.clear();
    1020 [ +  - ][ +  - ]:         17 :     std::for_each(maFields.begin(), maFields.end(), ClearGroupItems());
                 [ +  - ]
    1021                 :         17 : }
    1022                 :            : 
    1023                 :        367 : const ScDPNumGroupInfo* ScDPCache::GetNumGroupInfo(long nDim) const
    1024                 :            : {
    1025         [ -  + ]:        367 :     if (nDim < 0)
    1026                 :          0 :         return NULL;
    1027                 :            : 
    1028                 :        367 :     long nSourceCount = static_cast<long>(maFields.size());
    1029         [ +  + ]:        367 :     if (nDim < nSourceCount)
    1030                 :            :     {
    1031         [ +  + ]:        204 :         if (!maFields.at(nDim).mpGroup)
    1032                 :        102 :             return NULL;
    1033                 :            : 
    1034                 :        102 :         return &maFields[nDim].mpGroup->maInfo;
    1035                 :            :     }
    1036                 :            : 
    1037                 :        163 :     nDim -= nSourceCount;
    1038         [ +  - ]:        163 :     if (nDim < static_cast<long>(maGroupFields.size()))
    1039                 :        163 :         return &maGroupFields.at(nDim).maInfo;
    1040                 :            : 
    1041                 :        367 :     return NULL;
    1042                 :            : }
    1043                 :            : 
    1044                 :        144 : sal_Int32 ScDPCache::GetGroupType(long nDim) const
    1045                 :            : {
    1046         [ -  + ]:        144 :     if (nDim < 0)
    1047                 :          0 :         return 0;
    1048                 :            : 
    1049                 :        144 :     long nSourceCount = static_cast<long>(maFields.size());
    1050         [ +  + ]:        144 :     if (nDim < nSourceCount)
    1051                 :            :     {
    1052         [ -  + ]:         48 :         if (!maFields.at(nDim).mpGroup)
    1053                 :          0 :             return 0;
    1054                 :            : 
    1055                 :         48 :         return maFields[nDim].mpGroup->mnGroupType;
    1056                 :            :     }
    1057                 :            : 
    1058                 :         96 :     nDim -= nSourceCount;
    1059         [ +  - ]:         96 :     if (nDim < static_cast<long>(maGroupFields.size()))
    1060                 :         96 :         return maGroupFields.at(nDim).mnGroupType;
    1061                 :            : 
    1062                 :        144 :     return 0;
    1063                 :            : }
    1064                 :            : 
    1065                 :       6953 : SCROW ScDPCache::GetOrder(long /*nDim*/, SCROW nIndex) const
    1066                 :            : {
    1067                 :       6953 :     return nIndex;
    1068                 :            : }
    1069                 :            : 
    1070                 :         20 : ScDocument* ScDPCache::GetDoc() const
    1071                 :            : {
    1072                 :         20 :     return mpDoc;
    1073                 :            : };
    1074                 :            : 
    1075                 :     129566 : long ScDPCache::GetColumnCount() const
    1076                 :            : {
    1077                 :     129566 :     return mnColumnCount;
    1078 [ +  - ][ +  - ]:        153 : }
    1079                 :            : 
    1080                 :            : #if DEBUG_PIVOT_TABLE
    1081                 :            : 
    1082                 :            : #include <iostream>
    1083                 :            : using std::cout;
    1084                 :            : using std::endl;
    1085                 :            : 
    1086                 :            : namespace {
    1087                 :            : 
    1088                 :            : std::ostream& operator<< (::std::ostream& os, const rtl::OUString& str)
    1089                 :            : {
    1090                 :            :     return os << ::rtl::OUStringToOString(str, RTL_TEXTENCODING_UTF8).getStr();
    1091                 :            : }
    1092                 :            : 
    1093                 :            : void dumpItems(const ScDPCache& rCache, long nDim, const ScDPCache::ItemsType& rItems, size_t nOffset)
    1094                 :            : {
    1095                 :            :     for (size_t i = 0; i < rItems.size(); ++i)
    1096                 :            :         cout << "      " << (i+nOffset) << ": " << rCache.GetFormattedString(nDim, rItems[i]) << endl;
    1097                 :            : }
    1098                 :            : 
    1099                 :            : }
    1100                 :            : 
    1101                 :            : void ScDPCache::Dump() const
    1102                 :            : {
    1103                 :            :     cout << "--- pivot cache dump" << endl;
    1104                 :            :     {
    1105                 :            :         FieldsType::const_iterator it = maFields.begin(), itEnd = maFields.end();
    1106                 :            :         for (size_t i = 0; it != itEnd; ++it, ++i)
    1107                 :            :         {
    1108                 :            :             const Field& fld = *it;
    1109                 :            :             cout << "* source dimension: " << GetDimensionName(i) << " (ID = " << i << ")" << endl;
    1110                 :            :             cout << "    item count: " << fld.maItems.size() << endl;
    1111                 :            :             dumpItems(*this, i, fld.maItems, 0);
    1112                 :            :             if (fld.mpGroup)
    1113                 :            :             {
    1114                 :            :                 cout << "    group item count: " << fld.mpGroup->maItems.size() << endl;
    1115                 :            :                 dumpItems(*this, i, fld.mpGroup->maItems, fld.maItems.size());
    1116                 :            :             }
    1117                 :            :         }
    1118                 :            :     }
    1119                 :            : 
    1120                 :            :     {
    1121                 :            :         struct { SCROW start; SCROW end; bool empty; } aRange;
    1122                 :            :         cout << "* empty rows: " << endl;
    1123                 :            :         mdds::flat_segment_tree<SCROW, bool>::const_iterator it = maEmptyRows.begin(), itEnd = maEmptyRows.end();
    1124                 :            :         if (it != itEnd)
    1125                 :            :         {
    1126                 :            :             aRange.start = it->first;
    1127                 :            :             aRange.empty = it->second;
    1128                 :            :             ++it;
    1129                 :            :         }
    1130                 :            : 
    1131                 :            :         for (; it != itEnd; ++it)
    1132                 :            :         {
    1133                 :            :             aRange.end = it->first-1;
    1134                 :            :             cout << "    rows " << aRange.start << "-" << aRange.end << ": " << (aRange.empty ? "empty" : "not-empty") << endl;
    1135                 :            :             aRange.start = it->first;
    1136                 :            :             aRange.empty = it->second;
    1137                 :            :         }
    1138                 :            :     }
    1139                 :            : 
    1140                 :            :     {
    1141                 :            :         GroupFieldsType::const_iterator it = maGroupFields.begin(), itEnd = maGroupFields.end();
    1142                 :            :         for (size_t i = maFields.size(); it != itEnd; ++it, ++i)
    1143                 :            :         {
    1144                 :            :             const GroupItems& gi = *it;
    1145                 :            :             cout << "* group dimension: (unnamed) (ID = " << i << ")" << endl;
    1146                 :            :             cout << "    item count: " << gi.maItems.size() << endl;
    1147                 :            :             dumpItems(*this, i, gi.maItems, 0);
    1148                 :            :         }
    1149                 :            :     }
    1150                 :            : 
    1151                 :            :     cout << "---" << endl;
    1152                 :            : }
    1153                 :            : 
    1154                 :            : #endif
    1155                 :            : 
    1156                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10