Coverage Report

Created: 2026-06-30 11:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/inc/token.hxx
Line
Count
Source
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
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#pragma once
21
22
#include <memory>
23
#include <vector>
24
25
#include <formula/opcode.hxx>
26
#include "refdata.hxx"
27
#include "scdllapi.h"
28
#include <formula/token.hxx>
29
#include "calcmacros.hxx"
30
#include "types.hxx"
31
32
class ScJumpMatrix;
33
class ScMatrix;
34
struct ScSheetLimits;
35
36
typedef ::std::vector< ScComplexRefData > ScRefList;
37
38
#if DEBUG_FORMULA_COMPILER
39
void DumpToken(formula::FormulaToken const & rToken);
40
#endif
41
42
/** If rTok1 and rTok2 both are SingleRef or DoubleRef tokens, extend/merge
43
    ranges as needed for ocRange.
44
    @param rPos
45
        The formula's position, used to calculate absolute positions from
46
        relative references.
47
    @param bReuseDoubleRef
48
        If true, a DoubleRef token is reused if passed as rTok1 or rTok2,
49
        else a new DoubleRef token is created and returned.
50
    @return
51
        A reused or new'ed ScDoubleRefToken, or a NULL TokenRef if rTok1 or
52
        rTok2 are not of sv(Single|Double)Ref
53
*/
54
formula::FormulaTokenRef extendRangeReference( ScSheetLimits& rLimits, formula::FormulaToken & rTok1, formula::FormulaToken & rTok2, const ScAddress & rPos, bool bReuseDoubleRef );
55
56
class SAL_DLLPUBLIC_RTTI ScSingleRefToken final : public formula::FormulaToken
57
{
58
private:
59
    ScSheetLimits&    mrSheetLimits; // don't use rtl::Reference to avoid ref-counting traffic
60
    ScSingleRefData   aSingleRef;
61
public:
62
                                ScSingleRefToken( ScSheetLimits& rLimits, const ScSingleRefData& r, OpCode e = ocPush ) :
63
2.24M
                                    FormulaToken( formula::svSingleRef, e ), mrSheetLimits(rLimits), aSingleRef( r ) {}
64
2.47M
    const ScSingleRefData&      GetSingleRef() const { return aSingleRef; }
65
116M
    ScSingleRefData&            GetSingleRef() { return aSingleRef; }
66
    virtual bool                TextEqual( const formula::FormulaToken& rToken ) const override;
67
    virtual bool                operator==( const formula::FormulaToken& rToken ) const override;
68
24.3M
    virtual FormulaToken*       Clone() const override { return new ScSingleRefToken(*this); }
69
};
70
71
class SAL_DLLPUBLIC_RTTI ScDoubleRefToken final : public formula::FormulaToken
72
{
73
private:
74
    ScSheetLimits&    mrSheetLimits; // don't use rtl::Reference to avoid ref-counting traffic
75
    ScComplexRefData  aDoubleRef;
76
public:
77
                                ScDoubleRefToken( ScSheetLimits& rLimits, const ScComplexRefData& r, OpCode e = ocPush  ) :
78
1.28M
                                    FormulaToken( formula::svDoubleRef, e ), mrSheetLimits(rLimits), aDoubleRef( r ) {}
79
357k
    const ScSingleRefData&      GetSingleRef() const { return aDoubleRef.Ref1; }
80
1.57M
    ScSingleRefData&            GetSingleRef() { return aDoubleRef.Ref1; }
81
530k
    const ScComplexRefData&     GetDoubleRef() const { return aDoubleRef; }
82
422k
    ScComplexRefData&           GetDoubleRef() { return aDoubleRef; }
83
357k
    const ScSingleRefData&      GetSingleRef2() const { return aDoubleRef.Ref2; }
84
1.56M
    ScSingleRefData&            GetSingleRef2() { return aDoubleRef.Ref2; }
85
    virtual bool                TextEqual( const formula::FormulaToken& rToken ) const override;
86
    virtual bool                operator==( const formula::FormulaToken& rToken ) const override;
87
590k
    virtual FormulaToken*       Clone() const override { return new ScDoubleRefToken(*this); }
88
};
89
90
class SAL_DLLPUBLIC_RTTI ScMatrixToken : public formula::FormulaToken
91
{
92
private:
93
            ScMatrixRef         pMatrix;
94
public:
95
    ScMatrixToken( ScMatrixRef p );
96
    ScMatrixToken( const ScMatrixToken& );
97
98
    SC_DLLPUBLIC const ScMatrix* GetMatrix() const;
99
    ScMatrix*                   GetMatrix();
100
    virtual bool                operator==( const formula::FormulaToken& rToken ) const override;
101
366
    virtual FormulaToken*       Clone() const override { return new ScMatrixToken(*this); }
102
452
    virtual bool IsMatrixRangeToken() const { return false; }
103
};
104
105
/**
106
 * Token storing matrix that represents values in sheet range. It stores
107
 * both the values in matrix form, and the range address the matrix
108
 * represents.
109
 */
110
class ScMatrixRangeToken final : public ScMatrixToken
111
{
112
    ScComplexRefData maRef;
113
public:
114
    ScMatrixRangeToken( const sc::RangeMatrix& rMat );
115
    ScMatrixRangeToken( const ScMatrixRangeToken& );
116
117
0
    const ScComplexRefData& GetDoubleRef() const { return maRef; }
118
    virtual FormulaToken* Clone() const override;
119
0
    virtual bool IsMatrixRangeToken() const override { return true; }
120
};
121
122
class SC_DLLPUBLIC ScExternalToken : public formula::FormulaToken
123
{
124
    sal_uInt16                  mnFileId;
125
protected:
126
    ScExternalToken( formula::StackVar eTypeP, OpCode e, sal_uInt16 nFileId );
127
public:
128
    ScExternalToken() = delete;
129
    virtual ~ScExternalToken() override;
130
131
1.72k
    ScExternalToken(ScExternalToken const &) = default;
132
    ScExternalToken(ScExternalToken &&) = default;
133
    ScExternalToken & operator =(ScExternalToken const &) = delete; // due to FormulaToken
134
    ScExternalToken & operator =(ScExternalToken &&) = delete; // due to FormulaToken
135
136
2.44k
    sal_uInt16                  GetFileId() const { return mnFileId; }
137
    virtual bool                operator==( const formula::FormulaToken& rToken ) const override;
138
};
139
140
class SC_DLLPUBLIC ScExternalSingleRefToken final : public ScExternalToken
141
{
142
    svl::SharedString           maTabName;
143
    ScSingleRefData             maSingleRef;
144
145
public:
146
    ScExternalSingleRefToken( sal_uInt16 nFileId, svl::SharedString aTabName, const ScSingleRefData& r );
147
    ScExternalSingleRefToken() = delete;
148
    virtual ~ScExternalSingleRefToken() override;
149
150
418
    ScExternalSingleRefToken(ScExternalSingleRefToken const &) = default;
151
    ScExternalSingleRefToken(ScExternalSingleRefToken &&) = default;
152
    ScExternalSingleRefToken & operator =(ScExternalSingleRefToken const &) = delete; // due to FormulaToken
153
    ScExternalSingleRefToken & operator =(ScExternalSingleRefToken &&) = delete; // due to FormulaToken
154
155
2.29k
    const svl::SharedString & GetTableName() const { return maTabName; }
156
79
    const ScSingleRefData&      GetSingleRef() const { return maSingleRef; }
157
4.80k
    ScSingleRefData&            GetSingleRef() { return maSingleRef; }
158
    virtual bool                operator==( const formula::FormulaToken& rToken ) const override;
159
418
    virtual FormulaToken*       Clone() const override { return new ScExternalSingleRefToken(*this); }
160
};
161
162
class SC_DLLPUBLIC ScExternalDoubleRefToken final : public ScExternalToken
163
{
164
    svl::SharedString           maTabName;  // name of the first sheet
165
    ScComplexRefData            maDoubleRef;
166
167
public:
168
    ScExternalDoubleRefToken() = delete;
169
    ScExternalDoubleRefToken( sal_uInt16 nFileId, svl::SharedString aTabName, const ScComplexRefData& r );
170
    virtual ~ScExternalDoubleRefToken() override;
171
172
1.30k
    ScExternalDoubleRefToken(ScExternalDoubleRefToken const &) = default;
173
    ScExternalDoubleRefToken(ScExternalDoubleRefToken &&) = default;
174
    ScExternalDoubleRefToken & operator =(ScExternalDoubleRefToken const &) = delete; // due to FormulaToken
175
    ScExternalDoubleRefToken & operator =(ScExternalDoubleRefToken &&) = delete; // due to FormulaToken
176
177
53
    const svl::SharedString & GetTableName() const { return maTabName; }
178
106
    const ScSingleRefData&      GetSingleRef() const { return maDoubleRef.Ref1; }
179
44
    ScSingleRefData&            GetSingleRef() { return maDoubleRef.Ref1; }
180
106
    const ScSingleRefData&      GetSingleRef2() const { return maDoubleRef.Ref2; }
181
0
    const ScComplexRefData&     GetDoubleRef() const { return maDoubleRef; }
182
5.53k
    ScComplexRefData&           GetDoubleRef() { return maDoubleRef; }
183
    virtual bool                operator==( const formula::FormulaToken& rToken ) const override;
184
1.30k
    virtual FormulaToken*       Clone() const override { return new ScExternalDoubleRefToken(*this); }
185
};
186
187
class SAL_DLLPUBLIC_RTTI ScExternalNameToken final : public ScExternalToken
188
{
189
    svl::SharedString           maName;
190
191
public:
192
    ScExternalNameToken() = delete;
193
    ScExternalNameToken( sal_uInt16 nFileId, svl::SharedString aName );
194
    virtual ~ScExternalNameToken() override;
195
196
0
    ScExternalNameToken(ScExternalNameToken const &) = default;
197
    ScExternalNameToken(ScExternalNameToken &&) = default;
198
    ScExternalNameToken & operator =(ScExternalNameToken const &) = delete; // due to FormulaToken
199
    ScExternalNameToken & operator =(ScExternalNameToken &&) = delete; // due to FormulaToken
200
201
3
    const svl::SharedString & GetName() const { return maName; }
202
    virtual bool                operator==( const formula::FormulaToken& rToken ) const override;
203
0
    virtual FormulaToken*       Clone() const override { return new ScExternalNameToken(*this); }
204
};
205
206
/** Special token to remember details of ocTableRef "structured references". */
207
class ScTableRefToken final : public formula::FormulaToken
208
{
209
public:
210
211
    enum Item
212
    {
213
        TABLE    =   0,
214
        ALL      =   1,
215
        HEADERS  =   2,
216
        DATA     =   4,
217
        TOTALS   =   8,
218
        THIS_ROW =  16,
219
        HEADERS_DATA = HEADERS | DATA,
220
        DATA_TOTALS = DATA | TOTALS
221
    };
222
223
    ScTableRefToken() = delete;
224
    ScTableRefToken( sal_uInt16 nIndex, Item eItem );
225
    ScTableRefToken( const ScTableRefToken& r );
226
    virtual ~ScTableRefToken() override;
227
228
    sal_uInt16                  GetIndex() const;
229
    void                        SetIndex( sal_uInt16 n );
230
    virtual bool                operator==( const formula::FormulaToken& rToken ) const override;
231
2.83k
    virtual FormulaToken*       Clone() const override { return new ScTableRefToken(*this); }
232
233
            Item                GetItem() const;
234
            void                AddItem( Item );
235
            void                SetAreaRefRPN( formula::FormulaToken* pToken );
236
            formula::FormulaToken*  GetAreaRefRPN() const;
237
238
private:
239
240
    formula::FormulaTokenRef    mxAreaRefRPN;   ///< resulting RPN area
241
    sal_uInt16                  mnIndex;    ///< index into table / database range collection
242
    Item                        meItem;
243
};
244
245
// Only created from within the interpreter, no conversion from ScRawToken,
246
// never added to ScTokenArray!
247
class ScJumpMatrixToken final : public formula::FormulaToken
248
{
249
private:
250
    std::shared_ptr<ScJumpMatrix> mpJumpMatrix;
251
public:
252
                                ScJumpMatrixToken( std::shared_ptr<ScJumpMatrix> p );
253
                                ScJumpMatrixToken( const ScJumpMatrixToken & );
254
    virtual                     ~ScJumpMatrixToken() override;
255
    ScJumpMatrix*               GetJumpMatrix() const;
256
    virtual bool                operator==( const formula::FormulaToken& rToken ) const override;
257
0
    virtual ScJumpMatrixToken*  Clone() const override { return new ScJumpMatrixToken(*this); }
258
};
259
260
// Only created from within the interpreter, no conversion from ScRawToken,
261
// never added to ScTokenArray!
262
class ScRefListToken final : public formula::FormulaToken
263
{
264
private:
265
            ScRefList           aRefList;
266
            bool                mbArrayResult;  // whether RefList is an array result
267
public:
268
                                ScRefListToken() :
269
107
                                    FormulaToken( formula::svRefList ), mbArrayResult(false) {}
270
            explicit            ScRefListToken( bool bArrayResult ) :
271
111
                                    FormulaToken( formula::svRefList ), mbArrayResult( bArrayResult ) {}
272
            bool                IsArrayResult() const;
273
    const ScRefList*            GetRefList() const;
274
    ScRefList*                  GetRefList();
275
    virtual bool                operator==( const formula::FormulaToken& rToken ) const override;
276
0
    virtual ScRefListToken*     Clone() const override { return new ScRefListToken(*this); }
277
};
278
279
class ScEmptyCellToken final : public formula::FormulaToken
280
{
281
            bool                bInherited          :1;
282
            bool                bDisplayedAsString  :1;
283
public:
284
    explicit                    ScEmptyCellToken( bool bInheritedP, bool bDisplayAsString ) :
285
12.9k
                                    FormulaToken( formula::svEmptyCell ),
286
12.9k
                                    bInherited( bInheritedP ),
287
12.9k
                                    bDisplayedAsString( bDisplayAsString ) {}
288
0
            bool                IsInherited() const { return bInherited; }
289
22.8k
            bool                IsDisplayedAsString() const { return bDisplayedAsString; }
290
    virtual bool                operator==( const formula::FormulaToken& rToken ) const override;
291
0
    virtual FormulaToken*       Clone() const override { return new ScEmptyCellToken(*this); }
292
};
293
294
/**  Transports the result from the interpreter to the formula cell. */
295
class ScMatrixCellResultToken : public formula::FormulaToken
296
{
297
protected:
298
    ScConstMatrixRef xMatrix;
299
    formula::FormulaConstTokenRef     xUpperLeft;
300
public:
301
    ScMatrixCellResultToken( ScConstMatrixRef pMat, const formula::FormulaToken* pUL );
302
    ScMatrixCellResultToken( const ScMatrixCellResultToken& );
303
    virtual ~ScMatrixCellResultToken() override;
304
    const ScMatrix*             GetMatrix() const;
305
    virtual bool                operator==( const formula::FormulaToken& rToken ) const override;
306
    virtual FormulaToken*       Clone() const override;
307
    formula::StackVar           GetUpperLeftType() const
308
2.84k
                                    {
309
2.84k
                                        return xUpperLeft ?
310
2.84k
                                            xUpperLeft->GetType() :
311
2.84k
                                            formula::svUnknown;
312
2.84k
                                    }
313
2.22k
    const formula::FormulaConstTokenRef& GetUpperLeftToken() const { return xUpperLeft; }
314
    void Assign( const ScMatrixCellResultToken & r );
315
};
316
317
/** Stores the matrix result at the formula cell, additionally the range the
318
    matrix formula occupies. */
319
class ScMatrixFormulaCellToken final : public ScMatrixCellResultToken
320
{
321
private:
322
            SCROW               nRows;
323
            SCCOL               nCols;
324
public:
325
    ScMatrixFormulaCellToken( SCCOL nC, SCROW nR, const ScConstMatrixRef& pMat, const formula::FormulaToken* pUL );
326
    ScMatrixFormulaCellToken( SCCOL nC, SCROW nR );
327
    ScMatrixFormulaCellToken( const ScMatrixFormulaCellToken& r );
328
    virtual ~ScMatrixFormulaCellToken() override;
329
330
    virtual bool                operator==( const formula::FormulaToken& rToken ) const override;
331
0
    virtual FormulaToken*       Clone() const override { return new ScMatrixFormulaCellToken(*this); }
332
            void                SetMatColsRows( SCCOL nC, SCROW nR )
333
0
                                    {
334
0
                                        nRows = nR;
335
0
                                        nCols = nC;
336
0
                                    }
337
            void                GetMatColsRows( SCCOL & nC, SCROW & nR ) const
338
139
                                    {
339
139
                                        nR = nRows;
340
139
                                        nC = nCols;
341
139
                                    }
342
0
            SCCOL               GetMatCols() const  { return nCols; }
343
0
            SCROW               GetMatRows() const  { return nRows; }
344
345
    /** Assign matrix result, keep matrix formula
346
        dimension. */
347
    void Assign( const ScMatrixCellResultToken & r );
348
349
                                /** Assign any result, keep matrix formula
350
                                    dimension. If token is of type
351
                                    ScMatrixCellResultToken uses the
352
                                    appropriate Assign() call, other tokens
353
                                    are assigned to xUpperLeft and xMatrix will
354
                                    be assigned NULL. */
355
            void                Assign( const formula::FormulaToken & r );
356
357
                                /** Modify xUpperLeft if formula::svDouble, or create
358
                                    new formula::FormulaDoubleToken if not set yet. Does
359
                                    nothing if xUpperLeft is of different type! */
360
            void                SetUpperLeftDouble( double f);
361
362
    /** Reset matrix and upper left, keep matrix
363
        formula dimension. */
364
    void ResetResult();
365
366
private:
367
368
    /** xUpperLeft is modifiable through SetUpperLeftDouble(), so clone it
369
        whenever an svDouble token is assigned to. */
370
    void CloneUpperLeftIfNecessary();
371
};
372
373
class ScHybridCellToken final : public formula::FormulaToken
374
{
375
private:
376
    double mfDouble;
377
    svl::SharedString maString;
378
    OUString maFormula;
379
    bool mbEmptyDisplayedAsString;
380
public:
381
    ScHybridCellToken(
382
        double f, const svl::SharedString & rStr, OUString aFormula, bool bEmptyDisplayedAsString );
383
384
0
    const OUString& GetFormula() const  { return maFormula; }
385
10.8k
    bool IsEmptyDisplayedAsString() const   { return mbEmptyDisplayedAsString; }
386
    double GetDouble() const;
387
388
871
    const svl::SharedString & GetString() const { return maString; }
389
    virtual bool operator==( const formula::FormulaToken& rToken ) const override;
390
0
    virtual FormulaToken* Clone() const override { return new ScHybridCellToken(*this); }
391
};
392
393
// Simplify argument passing to RefUpdate methods with ScSingleRefToken or
394
// ScDoubleRefToken
395
class SingleDoubleRefModifier
396
{
397
    ScComplexRefData    aDub;
398
    ScSingleRefData*  pS;
399
    ScComplexRefData*   pD;
400
401
                SingleDoubleRefModifier( const SingleDoubleRefModifier& ) = delete;
402
        SingleDoubleRefModifier& operator=( const SingleDoubleRefModifier& ) = delete;
403
404
public:
405
        SingleDoubleRefModifier( formula::FormulaToken& rT )
406
0
                    {
407
0
                        formula::StackVar eType = rT.GetType();
408
0
                        if ( eType == formula::svSingleRef )
409
0
                        {
410
0
                            pS = &static_cast<ScSingleRefToken&>(rT).GetSingleRef();
411
0
                            aDub.Ref1 = aDub.Ref2 = *pS;
412
0
                            pD = &aDub;
413
0
                        }
414
0
                        else if ( eType == formula::svExternalSingleRef )
415
0
                        {
416
0
                            pS = &static_cast<ScExternalSingleRefToken&>(rT).GetSingleRef();
417
0
                            aDub.Ref1 = aDub.Ref2 = *pS;
418
0
                            pD = &aDub;
419
0
                        }
420
0
                        else
421
0
                        {
422
0
                            pS = nullptr;
423
0
                            pD = &static_cast<ScDoubleRefToken&>(rT).GetDoubleRef();
424
                            // coverity[uninit_member] - aDub intentionally not initialized, unnecessary because unused.
425
0
                        }
426
0
                    }
427
                SingleDoubleRefModifier( ScSingleRefData& rS )
428
23.0k
                    {
429
23.0k
                        pS = &rS;
430
23.0k
                        aDub.Ref1 = aDub.Ref2 = *pS;
431
23.0k
                        pD = &aDub;
432
23.0k
                    }
433
                ~SingleDoubleRefModifier()
434
23.0k
                    {
435
23.0k
                        if ( pS )
436
23.0k
                            *pS = (*pD).Ref1;
437
23.0k
                    }
438
23.0k
    ScComplexRefData& Ref() { return *pD; }
439
};
440
441
class SingleDoubleRefProvider
442
{
443
public:
444
445
    const ScSingleRefData&    Ref1;
446
    const ScSingleRefData&    Ref2;
447
448
                SingleDoubleRefProvider( const formula::FormulaToken& r )
449
0
                        : Ref1( r.GetType() == formula::svSingleRef
450
0
                                ? static_cast<const ScSingleRefToken&>(r).GetSingleRef()
451
0
                                : r.GetType() == formula::svExternalSingleRef
452
0
                                ? static_cast<const ScExternalSingleRefToken&>(r).GetSingleRef()
453
0
                                : r.GetType() == formula::svDoubleRef
454
0
                                ? static_cast<const ScDoubleRefToken&>(r).GetSingleRef()
455
0
                                : static_cast<const ScExternalDoubleRefToken&>(r).GetSingleRef()
456
                                ),
457
0
                          Ref2( r.GetType() == formula::svDoubleRef
458
0
                                ? static_cast<const ScDoubleRefToken&>(r).GetDoubleRef().Ref2
459
0
                                : r.GetType() == formula::svExternalDoubleRef
460
0
                                ? static_cast<const ScExternalDoubleRefToken&>(r).GetDoubleRef().Ref2
461
0
                                : Ref1 )
462
0
                    {}
463
};
464
465
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */