Coverage Report

Created: 2025-12-08 09:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/include/formula/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 <sal/config.h>
23
24
#include <cstring>
25
#include <memory>
26
#include <utility>
27
#include <vector>
28
29
#include <formula/formuladllapi.h>
30
#include <formula/opcode.hxx>
31
#include <formula/types.hxx>
32
#include <formula/paramclass.hxx>
33
#include <osl/interlck.h>
34
#include <rtl/ustring.hxx>
35
#include <sal/types.h>
36
#include <svl/sharedstring.hxx>
37
38
class ScJumpMatrix;
39
class ScMatrix;
40
struct ScComplexRefData;
41
struct ScSingleRefData;
42
enum class FormulaError : sal_uInt16;
43
44
namespace formula
45
{
46
47
enum StackVar : sal_uInt8
48
{
49
    svByte,
50
    svDouble,
51
    svString,
52
    svStringName,
53
    svSingleRef,
54
    svDoubleRef,
55
    svMatrix,
56
    svIndex,
57
    svJump,
58
    svExternal,                         // Byte + String
59
    svFAP,                              // FormulaAutoPilot only, ever exported
60
    svJumpMatrix,
61
    svRefList,                          // ocUnion result
62
    svEmptyCell,                        // Result is an empty cell, e.g. in LOOKUP()
63
64
    svMatrixCell,                       // Result is a matrix with bells and
65
                                        // whistles as needed for _the_ matrix
66
                                        // formula result.
67
68
    svHybridCell,                       // A temporary condition of a formula
69
                                        // cell during import, having a double
70
                                        // and/or string result and a formula
71
                                        // string to be compiled.
72
73
    svExternalSingleRef,
74
    svExternalDoubleRef,
75
    svExternalName,
76
    svSingleVectorRef,
77
    svDoubleVectorRef,
78
    svError,                            // error token
79
    svMissing,                          // 0 or ""
80
    svSep,                              // separator, ocSep, ocOpen, ocClose
81
    svUnknown                           // unknown StackType
82
};
83
84
// Only to be used for debugging output. No guarantee of stability of the
85
// return value.
86
87
// Turn this into an operator<< when StackVar becomes a scoped enum
88
89
inline std::string StackVarEnumToString(StackVar const e)
90
0
{
91
0
    switch (e)
92
0
    {
93
0
        case svByte:              return "Byte";
94
0
        case svDouble:            return "Double";
95
0
        case svString:            return "String";
96
0
        case svStringName:        return "StringName";
97
0
        case svSingleRef:         return "SingleRef";
98
0
        case svDoubleRef:         return "DoubleRef";
99
0
        case svMatrix:            return "Matrix";
100
0
        case svIndex:             return "Index";
101
0
        case svJump:              return "Jump";
102
0
        case svExternal:          return "External";
103
0
        case svFAP:               return "FAP";
104
0
        case svJumpMatrix:        return "JumpMatrix";
105
0
        case svRefList:           return "RefList";
106
0
        case svEmptyCell:         return "EmptyCell";
107
0
        case svMatrixCell:        return "MatrixCell";
108
0
        case svHybridCell:        return "HybridCell";
109
0
        case svExternalSingleRef: return "ExternalSingleRef";
110
0
        case svExternalDoubleRef: return "ExternalDoubleRef";
111
0
        case svExternalName:      return "ExternalName";
112
0
        case svSingleVectorRef:   return "SingleVectorRef";
113
0
        case svDoubleVectorRef:   return "DoubleVectorRef";
114
0
        case svError:             return "Error";
115
0
        case svMissing:           return "Missing";
116
0
        case svSep:               return "Sep";
117
0
        case svUnknown:           return "Unknown";
118
0
    }
119
0
    std::ostringstream os;
120
0
    os << static_cast<int>(e);
121
0
    return os.str();
122
0
}
123
124
enum class RefCntPolicy : sal_uInt8
125
{
126
    ThreadSafe, // refcounting via thread-safe oslInterlockedCount
127
    UnsafeRef,  // refcounting done with no locking/guarding against concurrent access
128
    None        // no ref counting done
129
};
130
131
class FORMULA_DLLPUBLIC FormulaToken
132
{
133
    OpCode                      eOp;
134
    const StackVar              eType;           // type of data
135
    RefCntPolicy                eRefCntPolicy;   // style of reference counting
136
    mutable oslInterlockedCount mnRefCnt;        // reference count
137
138
    FormulaToken&            operator=( const FormulaToken& ) = delete;
139
public:
140
    FormulaToken( StackVar eTypeP,OpCode e = ocPush );
141
    FormulaToken( const FormulaToken& r );
142
143
    virtual                     ~FormulaToken();
144
145
109M
    void                Delete()                { delete this; }
146
569k
    void                DeleteIfZeroRef()       { if (mnRefCnt == 0) delete this; }
147
720M
    StackVar            GetType() const         { return eType; }
148
    bool                IsFunction() const; // pure functions, no operators
149
150
    bool IsExternalRef() const;
151
    bool IsRef() const;
152
153
            sal_uInt8           GetParamCount() const;
154
155
    void IncRef() const
156
254M
    {
157
254M
        switch (eRefCntPolicy)
158
254M
        {
159
252M
            case RefCntPolicy::ThreadSafe:
160
252M
            default:
161
252M
                osl_atomic_increment(&mnRefCnt);
162
252M
                break;
163
1.94M
            case RefCntPolicy::UnsafeRef:
164
1.94M
                ++mnRefCnt;
165
1.94M
                break;
166
0
            case RefCntPolicy::None:
167
0
                break;
168
254M
        }
169
254M
    }
170
171
    void DecRef() const
172
254M
    {
173
254M
        switch (eRefCntPolicy)
174
254M
        {
175
252M
            case RefCntPolicy::ThreadSafe:
176
252M
            default:
177
252M
                if (!osl_atomic_decrement(&mnRefCnt))
178
109M
                    const_cast<FormulaToken*>(this)->Delete();
179
252M
                break;
180
1.94M
            case RefCntPolicy::UnsafeRef:
181
1.94M
                if (!--mnRefCnt)
182
510k
                    const_cast<FormulaToken*>(this)->Delete();
183
1.94M
                break;
184
0
            case RefCntPolicy::None:
185
0
                break;
186
254M
        }
187
254M
    }
188
189
510k
    void SetRefCntPolicy(RefCntPolicy ePolicy) { eRefCntPolicy = ePolicy; }
190
659k
    RefCntPolicy GetRefCntPolicy() const { return eRefCntPolicy; }
191
192
104M
    oslInterlockedCount GetRef() const       { return mnRefCnt; }
193
837M
    OpCode              GetOpCode() const    { return eOp; }
194
195
    bool                IsInForceArray() const;
196
197
    /**
198
        Dummy methods to avoid switches and casts where possible,
199
        the real token classes have to override the appropriate method[s].
200
        The only methods valid anytime if not overridden are:
201
202
        - GetByte() since this represents the count of parameters to a function
203
          which of course is 0 on non-functions. FormulaByteToken and ScExternal do
204
          override it.
205
206
        - GetInForceArray() since also this is only used for operators and
207
          functions and is ParamClass::Unknown for other tokens.
208
209
        Any other non-overridden method pops up an assertion.
210
     */
211
212
    virtual sal_uInt8           GetByte() const;
213
    virtual void                SetByte( sal_uInt8 n );
214
    virtual ParamClass          GetInForceArray() const;
215
    virtual void                SetInForceArray( ParamClass c );
216
    virtual double              GetDouble() const;
217
    virtual void                SetDouble(double fValue);
218
    virtual sal_Int16           GetDoubleType() const;
219
    virtual void                SetDoubleType( sal_Int16 nType );
220
    virtual const svl::SharedString & GetString() const;
221
    virtual void                SetString( const svl::SharedString& rStr );
222
    virtual sal_uInt16          GetIndex() const;
223
    virtual void                SetIndex( sal_uInt16 n );
224
    virtual sal_Int16           GetSheet() const;
225
    virtual void                SetSheet( sal_Int16 n );
226
    virtual sal_Unicode         GetChar() const;
227
    virtual short*              GetJump() const;
228
    virtual const OUString&     GetExternal() const;
229
    virtual FormulaToken*       GetFAPOrigToken() const;
230
    virtual FormulaError        GetError() const;
231
    virtual void                SetError( FormulaError );
232
233
    virtual const ScSingleRefData*  GetSingleRef() const;
234
    virtual ScSingleRefData*        GetSingleRef();
235
    virtual const ScComplexRefData* GetDoubleRef() const;
236
    virtual ScComplexRefData*       GetDoubleRef();
237
    virtual const ScSingleRefData*  GetSingleRef2() const;
238
    virtual ScSingleRefData*        GetSingleRef2();
239
    virtual const ScMatrix*     GetMatrix() const;
240
    virtual ScMatrix*           GetMatrix();
241
    virtual ScJumpMatrix*       GetJumpMatrix() const;
242
    virtual const std::vector<ScComplexRefData>* GetRefList() const;
243
    virtual       std::vector<ScComplexRefData>* GetRefList();
244
245
38.1M
    virtual FormulaToken*       Clone() const { return new FormulaToken(*this); }
246
247
    virtual bool                TextEqual( const formula::FormulaToken& rToken ) const;
248
    virtual bool                operator==( const FormulaToken& rToken ) const;
249
250
    /** This is dirty and only the compiler should use it! */
251
4.56k
    struct PrivateAccess { friend class FormulaCompiler; private: PrivateAccess() { }  };
252
4.56k
    void                NewOpCode( OpCode e, const PrivateAccess&  ) { eOp = e; }
253
};
254
255
inline void intrusive_ptr_add_ref(const FormulaToken* p)
256
89.1M
{
257
89.1M
    p->IncRef();
258
89.1M
}
259
260
inline void intrusive_ptr_release(const FormulaToken* p)
261
89.1M
{
262
89.1M
    p->DecRef();
263
89.1M
}
264
265
class FORMULA_DLLPUBLIC FormulaSpaceToken final : public FormulaToken
266
{
267
private:
268
            sal_uInt8           nByte;
269
            sal_Unicode         cChar;
270
public:
271
                                FormulaSpaceToken( sal_uInt8 n, sal_Unicode c ) :
272
42.8k
                                    FormulaToken( svByte, ocWhitespace ),
273
42.8k
                                    nByte( n ), cChar( c ) {}
274
                                FormulaSpaceToken( const FormulaSpaceToken& r ) :
275
1.37k
                                    FormulaToken( r ),
276
1.37k
                                    nByte( r.nByte ), cChar( r.cChar ) {}
277
278
1.37k
    virtual FormulaToken*       Clone() const override { return new FormulaSpaceToken(*this); }
279
    virtual sal_uInt8           GetByte() const override;
280
    virtual sal_Unicode         GetChar() const override;
281
    virtual bool                operator==( const FormulaToken& rToken ) const override;
282
};
283
284
class FORMULA_DLLPUBLIC FormulaByteToken : public FormulaToken
285
{
286
private:
287
            sal_uInt8           nByte;
288
            ParamClass          eInForceArray;
289
protected:
290
                                FormulaByteToken( OpCode e, sal_uInt8 n, StackVar v, ParamClass c ) :
291
3.67M
                                    FormulaToken( v,e ), nByte( n ),
292
3.67M
                                    eInForceArray( c ) {}
293
public:
294
                                FormulaByteToken( OpCode e, sal_uInt8 n, ParamClass c ) :
295
7.04M
                                    FormulaToken( svByte,e ), nByte( n ),
296
7.04M
                                    eInForceArray( c ) {}
297
                                FormulaByteToken( OpCode e, sal_uInt8 n ) :
298
169k
                                    FormulaToken( svByte,e ), nByte( n ),
299
169k
                                    eInForceArray( ParamClass::Unknown ) {}
300
                                FormulaByteToken( OpCode e ) :
301
1.49M
                                    FormulaToken( svByte,e ), nByte( 0 ),
302
1.49M
                                    eInForceArray( ParamClass::Unknown ) {}
303
                                FormulaByteToken( const FormulaByteToken& r ) :
304
11.4M
                                    FormulaToken( r ), nByte( r.nByte ),
305
11.4M
                                    eInForceArray( r.eInForceArray ) {}
306
307
8.92M
    virtual FormulaToken*       Clone() const override { return new FormulaByteToken(*this); }
308
    virtual sal_uInt8           GetByte() const override final;
309
    virtual void                SetByte( sal_uInt8 n ) override final;
310
    virtual ParamClass          GetInForceArray() const override final;
311
    virtual void                SetInForceArray( ParamClass c ) override final;
312
    virtual bool                operator==( const FormulaToken& rToken ) const override;
313
};
314
315
316
// A special token for the FormulaAutoPilot only. Keeps a reference pointer of
317
// the token of which it was created for comparison.
318
class FORMULA_DLLPUBLIC FormulaFAPToken final : public FormulaByteToken
319
{
320
private:
321
            FormulaTokenRef     pOrigToken;
322
public:
323
                                FormulaFAPToken( OpCode e, sal_uInt8 n, FormulaToken* p ) :
324
0
                                    FormulaByteToken( e, n, svFAP, ParamClass::Unknown ),
325
0
                                    pOrigToken( p ) {}
326
                                FormulaFAPToken( const FormulaFAPToken& r ) :
327
0
                                    FormulaByteToken( r ), pOrigToken( r.pOrigToken ) {}
328
329
0
    virtual FormulaToken*       Clone() const override { return new FormulaFAPToken(*this); }
330
    virtual FormulaToken*       GetFAPOrigToken() const override;
331
    virtual bool                operator==( const FormulaToken& rToken ) const override;
332
};
333
334
class FORMULA_DLLPUBLIC FormulaDoubleToken : public FormulaToken
335
{
336
private:
337
            double              fDouble;
338
public:
339
                                FormulaDoubleToken( double f ) :
340
2.36M
                                    FormulaToken( svDouble ), fDouble( f ) {}
341
                                FormulaDoubleToken( const FormulaDoubleToken& r ) :
342
196k
                                    FormulaToken( r ), fDouble( r.fDouble ) {}
343
344
196k
    virtual FormulaToken*       Clone() const override { return new FormulaDoubleToken(*this); }
345
3.28M
    virtual double              GetDouble() const override final { return fDouble; }
346
523k
    virtual void                SetDouble(double fValue) override final { fDouble = fValue; }
347
    virtual sal_Int16           GetDoubleType() const override;     ///< always returns 0 for "not typed"
348
    virtual bool                operator==( const FormulaToken& rToken ) const override;
349
};
350
351
class FORMULA_DLLPUBLIC FormulaTypedDoubleToken final : public FormulaDoubleToken
352
{
353
private:
354
            sal_Int16           mnType;     /**< Can hold, for example, a value
355
                                              of SvNumFormatType, or by
356
                                              contract any other
357
                                              classification. */
358
public:
359
                                FormulaTypedDoubleToken( double f, sal_Int16 nType ) :
360
510k
                                    FormulaDoubleToken( f ), mnType( nType ) {}
361
                                FormulaTypedDoubleToken( const FormulaTypedDoubleToken& r ) :
362
190
                                    FormulaDoubleToken( r ), mnType( r.mnType ) {}
363
364
190
    virtual FormulaToken*       Clone() const override { return new FormulaTypedDoubleToken(*this); }
365
    virtual sal_Int16           GetDoubleType() const override;
366
    virtual void                SetDoubleType( sal_Int16 nType ) override;
367
    virtual bool                operator==( const FormulaToken& rToken ) const override;
368
};
369
370
371
class FORMULA_DLLPUBLIC FormulaStringToken final : public FormulaToken
372
{
373
    svl::SharedString maString;
374
public:
375
    FormulaStringToken( svl::SharedString r );
376
    FormulaStringToken( const FormulaStringToken& r );
377
378
    virtual FormulaToken* Clone() const override;
379
    virtual const svl::SharedString & GetString() const override;
380
    virtual void SetString( const svl::SharedString& rStr ) override;
381
    virtual bool operator==( const FormulaToken& rToken ) const override;
382
};
383
384
385
/** Identical to FormulaStringToken, but with explicit OpCode instead of implicit
386
    ocPush, and an optional sal_uInt8 for ocBad tokens. */
387
class FORMULA_DLLPUBLIC FormulaStringOpToken final : public FormulaByteToken
388
{
389
    svl::SharedString maString;
390
public:
391
    FormulaStringOpToken( OpCode e, svl::SharedString r );
392
    FormulaStringOpToken( const FormulaStringOpToken& r );
393
394
    virtual FormulaToken* Clone() const override;
395
    virtual const svl::SharedString & GetString() const override;
396
    virtual void SetString( const svl::SharedString& rStr ) override;
397
    virtual bool operator==( const FormulaToken& rToken ) const override;
398
};
399
400
// FormulaStringNameToken
401
class FORMULA_DLLPUBLIC FormulaStringNameToken final : public FormulaToken
402
{
403
    svl::SharedString maString;
404
public:
405
    FormulaStringNameToken(svl::SharedString r);
406
    FormulaStringNameToken(const FormulaStringNameToken& r);
407
408
    virtual FormulaToken* Clone() const override;
409
    virtual const svl::SharedString& GetString() const override;
410
    virtual void SetString(const svl::SharedString& rStr) override;
411
    virtual bool operator==(const FormulaToken& rToken) const override;
412
};
413
414
415
class FORMULA_DLLPUBLIC FormulaIndexToken final : public FormulaToken
416
{
417
private:
418
            sal_uInt16          nIndex;
419
            sal_Int16           mnSheet;
420
public:
421
                                FormulaIndexToken( OpCode e, sal_uInt16 n, sal_Int16 nSheet = -1 ) :
422
25.0k
                                    FormulaToken(  svIndex, e ), nIndex( n ), mnSheet( nSheet ) {}
423
                                FormulaIndexToken( const FormulaIndexToken& r ) :
424
5.67k
                                    FormulaToken( r ), nIndex( r.nIndex ), mnSheet( r.mnSheet ) {}
425
426
5.67k
    virtual FormulaToken*       Clone() const override { return new FormulaIndexToken(*this); }
427
    virtual sal_uInt16          GetIndex() const override;
428
    virtual void                SetIndex( sal_uInt16 n ) override;
429
    virtual sal_Int16           GetSheet() const override;
430
    virtual void                SetSheet( sal_Int16 n ) override;
431
    virtual bool                operator==( const FormulaToken& rToken ) const override;
432
};
433
434
435
class FORMULA_DLLPUBLIC FormulaExternalToken final : public FormulaByteToken
436
{
437
private:
438
            OUString            aExternal;
439
public:
440
                                FormulaExternalToken( OpCode e, sal_uInt8 n, OUString  r ) :
441
735
                                    FormulaByteToken( e, n, svExternal, ParamClass::Unknown ),
442
735
                                    aExternal(std::move( r )) {}
443
                                FormulaExternalToken( OpCode e, OUString  r ) :
444
541k
                                    FormulaByteToken( e, 0, svExternal, ParamClass::Unknown ),
445
541k
                                    aExternal(std::move( r )) {}
446
                                FormulaExternalToken( const FormulaExternalToken& r ) :
447
81.5k
                                    FormulaByteToken( r ), aExternal( r.aExternal ) {}
448
449
81.5k
    virtual FormulaToken*       Clone() const override { return new FormulaExternalToken(*this); }
450
    virtual const OUString&     GetExternal() const override;
451
    virtual bool                operator==( const FormulaToken& rToken ) const override;
452
};
453
454
455
class FORMULA_DLLPUBLIC FormulaMissingToken final : public FormulaToken
456
{
457
public:
458
                                FormulaMissingToken() :
459
1.05M
                                    FormulaToken( svMissing,ocMissing ) {}
460
                                FormulaMissingToken( const FormulaMissingToken& r ) :
461
123k
                                    FormulaToken( r ) {}
462
463
123k
    virtual FormulaToken*       Clone() const override { return new FormulaMissingToken(*this); }
464
    virtual double              GetDouble() const override;
465
    virtual const svl::SharedString & GetString() const override;
466
    virtual bool                operator==( const FormulaToken& rToken ) const override;
467
};
468
469
class FORMULA_DLLPUBLIC FormulaJumpToken final : public FormulaToken
470
{
471
private:
472
            std::unique_ptr<short[]>
473
                                pJump;
474
            ParamClass          eInForceArray;
475
public:
476
                                FormulaJumpToken( OpCode e, short const * p ) :
477
120k
                                    FormulaToken( formula::svJump , e),
478
120k
                                    eInForceArray( ParamClass::Unknown)
479
120k
                                {
480
120k
                                    pJump.reset( new short[ p[0] + 1 ] );
481
120k
                                    memcpy( pJump.get(), p, (p[0] + 1) * sizeof(short) );
482
120k
                                }
483
                                FormulaJumpToken( const FormulaJumpToken& r ) :
484
59.2k
                                    FormulaToken( r ),
485
59.2k
                                    eInForceArray( r.eInForceArray)
486
59.2k
                                {
487
59.2k
                                    pJump.reset( new short[ r.pJump[0] + 1 ] );
488
59.2k
                                    memcpy( pJump.get(), r.pJump.get(), (r.pJump[0] + 1) * sizeof(short) );
489
59.2k
                                }
490
    virtual                     ~FormulaJumpToken() override;
491
    virtual short*              GetJump() const override;
492
    virtual bool                operator==( const formula::FormulaToken& rToken ) const override;
493
59.2k
    virtual FormulaToken*       Clone() const override { return new FormulaJumpToken(*this); }
494
    virtual ParamClass          GetInForceArray() const override;
495
    virtual void                SetInForceArray( ParamClass c ) override;
496
};
497
498
499
class FORMULA_DLLPUBLIC FormulaUnknownToken final : public FormulaToken
500
{
501
public:
502
                                FormulaUnknownToken( OpCode e ) :
503
0
                                    FormulaToken( svUnknown, e ) {}
504
                                FormulaUnknownToken( const FormulaUnknownToken& r ) :
505
0
                                    FormulaToken( r ) {}
506
507
0
    virtual FormulaToken*       Clone() const override { return new FormulaUnknownToken(*this); }
508
    virtual bool                operator==( const FormulaToken& rToken ) const override;
509
};
510
511
512
class FORMULA_DLLPUBLIC FormulaErrorToken final : public FormulaToken
513
{
514
         FormulaError          nError;
515
public:
516
                                FormulaErrorToken( FormulaError nErr ) :
517
235k
                                    FormulaToken( svError ), nError( nErr) {}
518
                                FormulaErrorToken( const FormulaErrorToken& r ) :
519
2.12k
                                    FormulaToken( r ), nError( r.nError) {}
520
521
2.12k
    virtual FormulaToken*       Clone() const override { return new FormulaErrorToken(*this); }
522
    virtual FormulaError        GetError() const override;
523
    virtual void                SetError( FormulaError nErr ) override;
524
    virtual bool                operator==( const FormulaToken& rToken ) const override;
525
};
526
527
528
} // formula
529
530
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */