Coverage Report

Created: 2026-10-14 09:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/include/formula/tokenarray.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 <climits>
23
#include <memory>
24
#include <ostream>
25
#include <type_traits>
26
#include <unordered_set>
27
#include <vector>
28
29
#include <formula/ExternalReferenceHelper.hxx>
30
#include <formula/formuladllapi.h>
31
#include <formula/opcode.hxx>
32
#include <formula/token.hxx>
33
#include <o3tl/typed_flags_set.hxx>
34
#include <rtl/ustring.hxx>
35
#include <sal/types.h>
36
37
namespace com::sun::star {
38
    namespace sheet { struct FormulaToken; }
39
}
40
41
namespace com::sun::star::uno { template <typename > class Sequence; }
42
namespace formula { class FormulaTokenArray; }
43
44
namespace svl {
45
46
class SharedString;
47
class SharedStringPool;
48
49
}
50
51
// RecalcMode access only via TokenArray SetExclusiveRecalcMode...() /
52
// IsRecalcMode...()
53
54
// Only one of the exclusive bits can be set and one must be set,
55
// handled by TokenArray SetExclusiveRecalcMode...() methods.
56
// Exclusive bits are ordered by priority, AddRecalcMode() relies on that.
57
enum class ScRecalcMode : sal_uInt8
58
{
59
    ALWAYS         = 0x01,  // exclusive, always
60
    ONLOAD_MUST    = 0x02,  // exclusive, always after load
61
    ONLOAD_ONCE    = 0x04,  // exclusive, once after load, import filter
62
    ONLOAD_LENIENT = 0x08,  // exclusive, lenient after load (eg. macros not always, aliens, ...)
63
    NORMAL         = 0x10,  // exclusive
64
    FORCED         = 0x20,  // combined, also if cell isn't visible, for macros with side effects
65
    ONREFMOVE      = 0x40,  // combined, if reference was moved
66
    EMask          = ALWAYS | ONLOAD_MUST | ONLOAD_LENIENT | ONLOAD_ONCE | NORMAL   // mask of exclusive bits
67
};
68
namespace o3tl
69
{
70
    template<> struct typed_flags<ScRecalcMode> : is_typed_flags<ScRecalcMode, 0x7f> {};
71
}
72
73
namespace formula
74
{
75
76
class FORMULA_DLLPUBLIC MissingConvention
77
{
78
public:
79
    enum Convention
80
    {
81
        FORMULA_MISSING_CONVENTION_PODF,
82
        FORMULA_MISSING_CONVENTION_ODFF,
83
        FORMULA_MISSING_CONVENTION_OOXML
84
    };
85
0
    explicit            MissingConvention( Convention eConvention ) : meConvention(eConvention) {}
86
0
    bool        isPODF() const  { return meConvention == FORMULA_MISSING_CONVENTION_PODF; }
87
0
    bool        isODFF() const  { return meConvention == FORMULA_MISSING_CONVENTION_ODFF; }
88
0
    bool        isOOXML() const  { return meConvention == FORMULA_MISSING_CONVENTION_OOXML; }
89
0
    Convention  getConvention() const { return meConvention; }
90
private:
91
    Convention meConvention;
92
};
93
94
class FORMULA_DLLPUBLIC MissingConventionODF : public MissingConvention
95
{
96
public:
97
    explicit    MissingConventionODF( bool bODFF ) :
98
0
        MissingConvention( bODFF ?
99
0
                MissingConvention::FORMULA_MISSING_CONVENTION_ODFF :
100
0
                MissingConvention::FORMULA_MISSING_CONVENTION_PODF)
101
0
        {
102
0
        }
103
    // Implementation and usage only in token.cxx
104
    inline  bool    isRewriteNeeded( OpCode eOp ) const;
105
};
106
107
class FORMULA_DLLPUBLIC MissingConventionOOXML : public MissingConvention
108
{
109
public:
110
0
    explicit    MissingConventionOOXML() : MissingConvention( MissingConvention::FORMULA_MISSING_CONVENTION_OOXML) {}
111
    // Implementation and usage only in token.cxx
112
    static inline bool isRewriteNeeded( OpCode eOp );
113
};
114
115
typedef std::unordered_set<OpCode, std::hash<std::underlying_type<OpCode>::type> > unordered_opcode_set;
116
117
class FORMULA_DLLPUBLIC FormulaTokenArrayStandardRange
118
{
119
private:
120
    FormulaToken** mpBegin;
121
    FormulaToken** mpEnd;
122
123
public:
124
    FormulaTokenArrayStandardRange(FormulaToken** pBegin, sal_uInt16 nSize) :
125
24.9M
        mpBegin(pBegin),
126
24.9M
        mpEnd(pBegin + nSize)
127
24.9M
    {
128
24.9M
    }
129
130
    FormulaToken** begin() const
131
24.8M
    {
132
24.8M
        return mpBegin;
133
24.8M
    }
134
135
    FormulaToken** end() const
136
24.9M
    {
137
24.9M
        return mpEnd;
138
24.9M
    }
139
};
140
141
class FORMULA_DLLPUBLIC FormulaTokenArrayReferencesIterator
142
{
143
private:
144
    FormulaToken** maIter;
145
    FormulaToken** maEnd;
146
147
    void nextReference()
148
102k
    {
149
120k
        while (maIter != maEnd)
150
68.6k
        {
151
68.6k
            switch ((*maIter)->GetType())
152
68.6k
            {
153
48.9k
            case svSingleRef:
154
50.2k
            case svDoubleRef:
155
50.2k
            case svExternalSingleRef:
156
50.3k
            case svExternalDoubleRef:
157
50.3k
                return;
158
18.2k
            default:
159
18.2k
                ++maIter;
160
68.6k
            }
161
68.6k
        }
162
102k
    }
163
164
    enum class Dummy { Flag };
165
166
    FormulaTokenArrayReferencesIterator(const FormulaTokenArrayStandardRange& rRange, Dummy) :
167
51.9k
        maIter(rRange.end()),
168
51.9k
        maEnd(rRange.end())
169
51.9k
    {
170
51.9k
    }
171
172
public:
173
    FormulaTokenArrayReferencesIterator(const FormulaTokenArrayStandardRange& rRange) :
174
51.9k
        maIter(rRange.begin()),
175
51.9k
        maEnd(rRange.end())
176
51.9k
    {
177
51.9k
        nextReference();
178
51.9k
    }
179
180
    FormulaTokenArrayReferencesIterator operator++(int)
181
0
    {
182
0
        FormulaTokenArrayReferencesIterator result(*this);
183
0
        operator++();
184
0
        return result;
185
0
    }
186
187
    FormulaTokenArrayReferencesIterator const & operator++()
188
50.3k
    {
189
50.3k
        assert(maIter != maEnd);
190
50.3k
        ++maIter;
191
50.3k
        nextReference();
192
50.3k
        return *this;
193
50.3k
    }
194
195
    FormulaToken* operator*() const
196
50.3k
    {
197
50.3k
        return *maIter;
198
50.3k
    }
199
200
    bool operator==(const FormulaTokenArrayReferencesIterator& rhs) const
201
102k
    {
202
102k
        return maIter == rhs.maIter;
203
102k
    }
204
205
    bool operator!=(const FormulaTokenArrayReferencesIterator& rhs) const
206
102k
    {
207
102k
        return !operator==(rhs);
208
102k
    }
209
210
    static FormulaTokenArrayReferencesIterator endOf(const FormulaTokenArrayStandardRange& rRange)
211
51.9k
    {
212
51.9k
        return FormulaTokenArrayReferencesIterator(rRange, Dummy::Flag);
213
51.9k
    }
214
};
215
216
class FORMULA_DLLPUBLIC FormulaTokenArrayReferencesRange
217
{
218
private:
219
    const FormulaTokenArray& mrFTA;
220
221
public:
222
    FormulaTokenArrayReferencesRange(const FormulaTokenArray& rFTA) :
223
51.9k
        mrFTA(rFTA)
224
51.9k
    {
225
51.9k
    }
226
227
    FormulaTokenArrayReferencesIterator begin();
228
229
    FormulaTokenArrayReferencesIterator end();
230
};
231
232
class FORMULA_DLLPUBLIC FormulaTokenArray
233
{
234
protected:
235
    std::unique_ptr<FormulaToken*[]> pCode; // Token code array
236
    std::unique_ptr<FormulaToken*[]> pRPN;                   // RPN array
237
    sal_uInt16      nLen;                   // Length of token array
238
    sal_uInt16      nRPN;                   // Length of RPN array
239
    FormulaError    nError;                 // Error code
240
    ScRecalcMode    nMode;                  // Flags to indicate when to recalc this code
241
    bool            bHyperLink      :1;     // If HYPERLINK() occurs in the formula.
242
    bool            mbFromRangeName :1;     // If this array originates from a named expression
243
    bool            mbShareable     :1;     // Whether or not it can be shared with adjacent cells.
244
    bool            mbFinalized     :1;     // Whether code arrays have their final used size and no more tokens can be added.
245
    bool mbDynamicArrayFunction :1; // If a dynamic-array function occurs in the formula (i.e. UNIQUE, FILTER, SORT)
246
247
protected:
248
    void                    Assign( const FormulaTokenArray& );
249
    void                    Assign( sal_uInt16 nCode, FormulaToken **pTokens );
250
    void                    Move( FormulaTokenArray&& );
251
252
    /// Also used by the compiler. The token MUST have been allocated with new!
253
    FormulaToken*           Add( FormulaToken* );
254
255
public:
256
    enum ReplaceMode
257
    {
258
        CODE_ONLY,      ///< replacement only in pCode
259
        CODE_AND_RPN    ///< replacement in pCode and pRPN
260
    };
261
262
    /** Also used by the compiler. The token MUST have been allocated with new!
263
        @param  nOffset
264
                Absolute offset in pCode of the token to be replaced.
265
        @param  eMode
266
                If CODE_ONLY only the token in pCode at nOffset is replaced.
267
                If CODE_AND_RPN the token in pCode at nOffset is replaced;
268
                if the original token was also referenced in the pRPN array
269
                then that reference is replaced with a reference to the new
270
                token as well.
271
     */
272
    FormulaToken*           ReplaceToken( sal_uInt16 nOffset, FormulaToken*, ReplaceMode eMode );
273
    FormulaToken*           ReplaceRPNToken( sal_uInt16 nOffset, FormulaToken* );
274
275
    /** Remove a sequence of tokens from pCode array, and pRPN array if the
276
        tokens are referenced there.
277
278
        nLen and nRPN are adapted.
279
280
        @param  nOffset
281
                Start offset into pCode.
282
        @param  nCount
283
                Count of tokens to remove.
284
285
        @return Count of tokens removed.
286
     */
287
    sal_uInt16              RemoveToken( sal_uInt16 nOffset, sal_uInt16 nCount );
288
289
    FormulaTokenArray();
290
    /** Assignment with incrementing references of FormulaToken entries
291
        (not copied!) */
292
    FormulaTokenArray( const FormulaTokenArray& );
293
    FormulaTokenArray( FormulaTokenArray&& );
294
    virtual ~FormulaTokenArray();
295
296
    virtual void Clear();
297
298
    /**
299
     * The array has its final used size and no more token can be added.
300
     */
301
    void Finalize();
302
303
45.8k
    void SetFromRangeName( bool b ) { mbFromRangeName = b; }
304
1.09M
    bool IsFromRangeName() const { return mbFromRangeName; }
305
306
3
    void SetShareable( bool b ) { mbShareable = b; }
307
308
    /**
309
     * Check if this token array is shareable between multiple adjacent
310
     * formula cells. Certain tokens may not function correctly when shared.
311
     *
312
     * @return true if the token array is shareable, false otherwise.
313
     */
314
34.7M
    bool IsShareable() const { return mbShareable; }
315
316
    void DelRPN();
317
    FormulaToken* FirstToken() const;
318
319
    /// Return pCode[nIdx], or nullptr if nIdx is out of bounds
320
    FormulaToken* TokenAt( sal_uInt16 nIdx) const
321
1.21M
    {
322
1.21M
        if (nIdx >= nLen)
323
0
            return nullptr;
324
1.21M
        return pCode[nIdx];
325
1.21M
    }
326
327
    /// Peek at nIdx-1 if not out of bounds, decrements nIdx if successful. Returns nullptr if not.
328
    FormulaToken* PeekPrev( sal_uInt16 & nIdx ) const;
329
330
    /// Return the opcode at pCode[nIdx-1], ocNone if nIdx-1 is out of bounds
331
    OpCode OpCodeBefore( sal_uInt16 nIdx) const
332
21.0M
    {
333
21.0M
        if (nIdx == 0 || nIdx > nLen)
334
2.01M
            return ocNone;
335
336
19.0M
        return pCode[nIdx-1]->GetOpCode();
337
21.0M
    }
338
339
    FormulaToken* FirstRPNToken() const;
340
341
    bool HasReferences() const;
342
343
    bool    HasExternalRef() const;
344
    bool    HasOpCode( OpCode ) const;
345
    bool    HasOpCodeRPN( OpCode ) const;
346
    /// Token of type svIndex or opcode ocColRowName
347
    bool    HasNameOrColRowName() const;
348
349
    /**
350
     * Check if the token array contains any of specified opcode tokens.
351
     *
352
     * @param rOpCodes collection of opcodes to check against.
353
     *
354
     * @return true if the token array contains at least one of the specified
355
     *         opcode tokens, false otherwise.
356
     */
357
    bool HasOpCodes( const unordered_opcode_set& rOpCodes ) const;
358
359
    /// Assign pRPN to point to a newly created array filled with the data from pData
360
    void CreateNewRPNArrayFromData( FormulaToken** pData, sal_uInt16 nSize )
361
1.83M
    {
362
1.83M
        pRPN = std::make_unique<FormulaToken*[]>(nSize);
363
1.83M
        nRPN = nSize;
364
1.83M
        memcpy( pRPN.get(), pData, nSize * sizeof( FormulaToken* ) );
365
1.83M
    }
366
367
    // Assign pCode to point to a newly created array filled with data; the array is sized exactly
368
    // to size, so it is final:
369
231
    void CreateNewCodeArrayFromData(FormulaToken ** data, sal_uInt16 size) {
370
231
        pCode = std::make_unique<FormulaToken*[]>(size);
371
231
        nLen = size;
372
231
        memcpy(pCode.get(), data, size * sizeof (FormulaToken *));
373
231
        mbFinalized = true;
374
231
    }
375
376
269M
    FormulaToken** GetArray() const  { return pCode.get(); }
377
378
    FormulaTokenArrayStandardRange Tokens() const
379
23.2M
    {
380
23.2M
        return FormulaTokenArrayStandardRange(pCode.get(), nLen);
381
23.2M
    }
382
383
39.9M
    FormulaToken** GetCode()  const  { return pRPN.get(); }
384
385
    FormulaTokenArrayStandardRange RPNTokens() const
386
1.66M
    {
387
1.66M
        return FormulaTokenArrayStandardRange(pRPN.get(), nRPN);
388
1.66M
    }
389
390
    FormulaTokenArrayReferencesRange References() const
391
51.9k
    {
392
51.9k
        return FormulaTokenArrayReferencesRange(*this);
393
51.9k
    }
394
395
245M
    sal_uInt16     GetLen() const     { return nLen; }
396
77.2M
    sal_uInt16     GetCodeLen() const { return nRPN; }
397
82.8M
    FormulaError   GetCodeError() const      { return nError; }
398
8.41M
    void      SetCodeError( FormulaError n )  { nError = n; }
399
210k
    void      SetHyperLink( bool bVal ) { bHyperLink = bVal; }
400
126k
    bool      IsHyperLink() const       { return bHyperLink; }
401
402
162
    void SetDynamicArrayFunction(bool bValue) { mbDynamicArrayFunction = bValue; }
403
0
    bool HasDynamicArrayFunction() const { return mbDynamicArrayFunction; }
404
405
103k
    ScRecalcMode    GetRecalcMode() const { return nMode; }
406
407
    void            SetCombinedBitsRecalcMode( ScRecalcMode nBits )
408
545k
                                { nMode |= nBits & ~ScRecalcMode::EMask; }
409
    ScRecalcMode    GetCombinedBitsRecalcMode() const
410
468k
                                { return nMode & ~ScRecalcMode::EMask; }
411
412
                    /** Exclusive bits already set in nMode are zero'ed, nBits
413
                        may contain combined bits, but only one exclusive bit
414
                        may be set! */
415
    void            SetMaskedRecalcMode( ScRecalcMode nBits )
416
468k
                                { nMode = GetCombinedBitsRecalcMode() | nBits; }
417
418
                    /** Bits aren't set directly but validated and handled
419
                        according to priority if more than one exclusive bit
420
                        was set. */
421
    void            AddRecalcMode( ScRecalcMode nBits );
422
423
24.3M
    void            ClearRecalcMode() { nMode = ScRecalcMode::NORMAL; }
424
    void            SetExclusiveRecalcModeNormal()
425
7.95k
                                { SetMaskedRecalcMode( ScRecalcMode::NORMAL ); }
426
    void            SetExclusiveRecalcModeAlways()
427
47.3k
                                { SetMaskedRecalcMode( ScRecalcMode::ALWAYS ); }
428
    void            SetRecalcModeForced()
429
235k
                                { nMode |= ScRecalcMode::FORCED; }
430
    void            SetRecalcModeOnRefMove()
431
6.82k
                                { nMode |= ScRecalcMode::ONREFMOVE; }
432
    bool            IsRecalcModeNormal() const
433
8.78M
                                { return bool(nMode & ScRecalcMode::NORMAL); }
434
    bool            IsRecalcModeAlways() const
435
10.0M
                                { return bool(nMode & ScRecalcMode::ALWAYS); }
436
    bool            IsRecalcModeForced() const
437
2.14M
                                { return bool(nMode & ScRecalcMode::FORCED); }
438
    bool            IsRecalcModeOnRefMove() const
439
0
                                { return bool(nMode & ScRecalcMode::ONREFMOVE); }
440
                    /** Whether recalculation must happen after import, for
441
                        example OOXML. */
442
    bool            IsRecalcModeMustAfterImport() const
443
236k
                                { return (nMode & ScRecalcMode::EMask) <= ScRecalcMode::ONLOAD_ONCE; }
444
    void            ClearRecalcModeMustAfterImport()
445
236k
                                {
446
236k
                                    if (IsRecalcModeMustAfterImport() && !IsRecalcModeAlways())
447
5.58k
                                        SetExclusiveRecalcModeNormal();
448
236k
                                }
449
450
                            /** Get OpCode of the most outer function */
451
    inline OpCode           GetOuterFuncOpCode() const;
452
453
                            /** Operators +,-,*,/,^,&,=,<>,<,>,<=,>=
454
                                with DoubleRef in Formula? */
455
    bool                    HasMatrixDoubleRefOps() const;
456
457
    virtual FormulaToken* AddOpCode(OpCode e);
458
459
    /** Adds the single token to array.
460
        Derived classes must override it when they want to support derived classes from FormulaToken.
461
        @return true        when an error occurs
462
    */
463
    virtual bool AddFormulaToken(
464
        const css::sheet::FormulaToken& rToken, svl::SharedStringPool& rSPool,
465
        ExternalReferenceHelper* pExtRef );
466
467
    /** fill the array with the tokens from the sequence.
468
        It calls AddFormulaToken for each token in the list.
469
        @param  _aSequence  the token to add
470
        @return true        when an error occurs
471
    */
472
    bool Fill(
473
        const css::uno::Sequence<css::sheet::FormulaToken>& rSequence,
474
        svl::SharedStringPool& rSPool, ExternalReferenceHelper* pExtRef );
475
476
    /**
477
     * Do some checking based on the individual tokens. For now, we use this
478
     * only to check whether we can vectorize the token array.
479
     */
480
    virtual void CheckToken( const FormulaToken& t );
481
482
    /**
483
     * Call CheckToken() for all RPN tokens.
484
     */
485
    void CheckAllRPNTokens();
486
487
    /** Clones the token and then adds the clone to the pCode array.
488
        For just new'ed tokens use Add() instead of cloning it again.
489
        Use this AddToken() when adding a token from another origin.
490
     */
491
    FormulaToken* AddToken( const FormulaToken& );
492
493
    FormulaToken* AddString( const svl::SharedString& rStr );
494
    FormulaToken* AddStringName(const svl::SharedString& rString, bool bOptional = false);
495
    FormulaToken* AddDPFieldName( const svl::SharedString& rStr );
496
    FormulaToken* AddDouble( double fVal );
497
    void          AddExternal( const sal_Unicode* pStr );
498
    /** Xcl import may play dirty tricks with OpCode!=ocExternal.
499
        Others don't use! */
500
    FormulaToken* AddExternal( const OUString& rStr, OpCode eOp = ocExternal );
501
    FormulaToken* AddBad( const OUString& rStr );          /// ocBad with OUString
502
    FormulaToken* AddStringXML( const OUString& rStr );    /// ocStringXML with OUString, temporary during import
503
    FormulaToken* AddStringName( const OUString& rStr );   /// ocStringName with OUString - Lambda functions
504
    FormulaToken* AddDPFieldName( const OUString& rStr );   /// ocDPFieldName with OUString - Pivot Table DataPilot field names
505
    FormulaToken* AddError( FormulaError nErr );
506
507
    virtual FormulaToken* MergeArray( );
508
509
    /** Assignment with incrementing references of FormulaToken entries
510
        (not copied!) */
511
    FormulaTokenArray& operator=( const FormulaTokenArray& );
512
    FormulaTokenArray& operator=( FormulaTokenArray&& );
513
514
    /** Determines if this formula needs any changes to convert it to something
515
        previous versions of OOo could consume (Plain Old Formula, pre-ODFF, or
516
        also ODFF) */
517
    bool                NeedsPodfRewrite( const MissingConventionODF & rConv );
518
519
    /** Determines if this formula needs any changes to convert it to OOXML. */
520
    bool                NeedsOoxmlRewrite();
521
522
    /** Rewrites to Plain Old Formula or OOXML, substituting missing parameters. The
523
        FormulaTokenArray* returned is new'ed. */
524
    FormulaTokenArray*  RewriteMissing( const MissingConvention & rConv );
525
526
    /** Determines if this formula may be followed by a reference. */
527
    bool                MayReferenceFollow();
528
529
    /** Re-intern SharedString in case the SharedStringPool differs. */
530
    void ReinternStrings( svl::SharedStringPool& rPool );
531
};
532
533
inline OpCode FormulaTokenArray::GetOuterFuncOpCode() const
534
0
{
535
0
    if ( pRPN && nRPN )
536
0
        return pRPN[nRPN-1]->GetOpCode();
537
0
    return ocNone;
538
0
}
539
540
inline FormulaTokenArrayReferencesIterator FormulaTokenArrayReferencesRange::begin()
541
51.9k
{
542
51.9k
    return FormulaTokenArrayReferencesIterator(mrFTA.Tokens());
543
51.9k
}
544
545
inline FormulaTokenArrayReferencesIterator FormulaTokenArrayReferencesRange::end()
546
51.9k
{
547
51.9k
    return FormulaTokenArrayReferencesIterator::endOf(mrFTA.Tokens());
548
51.9k
}
549
550
class FORMULA_DLLPUBLIC FormulaTokenIterator
551
{
552
    struct Item
553
    {
554
    public:
555
        const FormulaTokenArray* pArr;
556
        short nPC;
557
        short nStop;
558
        bool bLambda;
559
560
        Item(const FormulaTokenArray* arr, short pc, short stop, bool lambda);
561
    };
562
563
    std::vector<Item> maStack;
564
565
public:
566
    FormulaTokenIterator( const FormulaTokenArray& );
567
   ~FormulaTokenIterator();
568
    void    Reset();
569
    const   FormulaToken* Next();
570
    const   FormulaToken* PeekNextOperator();
571
    bool    IsEndOfPath() const;    /// if a jump or subroutine path is done
572
24.3k
    bool    HasStacked() const { return maStack.size() > 1; }
573
123
    short   GetPC() const { return maStack.back().nPC; }
574
575
    /** Jump or subroutine call.
576
        Program counter values will be incremented before code is executed =>
577
        positions are to be passed with -1 offset.
578
        @param nStart
579
            Start on code at position nStart+1 (yes, pass with offset -1)
580
        @param nNext
581
            After subroutine continue with instruction at position nNext+1
582
        @param nStop
583
            Stop before reaching code at position nStop. If not specified the
584
            default is to either run the entire code, or to stop if an ocSep or
585
            ocClose is encountered, which are only present in ocIf or ocChoose
586
            jumps.
587
      */
588
    void Jump( short nStart, short nNext, short nStop = SHRT_MAX );
589
    void Push( const FormulaTokenArray* );
590
    void Pop();
591
    void Lambda( bool bOpt );
592
    bool IsLambda() const;
593
594
    /** Reconstruct the iterator afresh from a token array
595
    */
596
    void ReInit( const FormulaTokenArray& );
597
598
private:
599
    SAL_DLLPRIVATE const FormulaToken* GetNonEndOfPathToken( short nIdx ) const;
600
};
601
602
// For use in SAL_INFO, SAL_WARN etc
603
604
template<typename charT, typename traits>
605
inline std::basic_ostream<charT, traits> & operator <<(std::basic_ostream<charT, traits> & stream, const FormulaTokenArray& point)
606
{
607
    stream <<
608
        static_cast<const void*>(&point) <<
609
        ":{nLen=" << point.GetLen() <<
610
        ",nRPN=" << point.GetCodeLen() <<
611
        ",pCode=" << static_cast<void*>(point.GetArray()) <<
612
        ",pRPN=" << static_cast<void*>(point.GetCode()) <<
613
        "}";
614
615
    return stream;
616
}
617
618
class FORMULA_DLLPUBLIC FormulaTokenArrayPlainIterator
619
{
620
private:
621
    const FormulaTokenArray* mpFTA;
622
    sal_uInt16 mnIndex;                 // Current step index
623
624
public:
625
    FormulaTokenArrayPlainIterator( const FormulaTokenArray& rFTA ) :
626
23.0M
        mpFTA( &rFTA ),
627
23.0M
        mnIndex( 0 )
628
23.0M
    {
629
23.0M
    }
630
631
    void Reset()
632
4.05M
    {
633
4.05M
        mnIndex = 0;
634
4.05M
    }
635
636
    sal_uInt16 GetIndex() const
637
21.1M
    {
638
21.1M
        return mnIndex;
639
21.1M
    }
640
641
    FormulaToken* First()
642
510
    {
643
510
        mnIndex = 0;
644
510
        return Next();
645
510
    }
646
647
    void Jump(sal_uInt16 nIndex)
648
103k
    {
649
103k
        mnIndex = nIndex;
650
103k
    }
651
652
    void StepBack()
653
193
    {
654
193
        assert(mnIndex > 0);
655
193
        mnIndex--;
656
193
    }
657
658
    FormulaToken* Next();
659
    FormulaToken* NextNoSpaces();
660
    FormulaToken* GetNextName();
661
    FormulaToken* GetNextDPFieldNameRPN();
662
    FormulaToken* GetNextReference();
663
    FormulaToken* GetNextReferenceRPN();
664
    FormulaToken* GetNextReferenceOrName();
665
    FormulaToken* GetNextColRowName();
666
    FormulaToken* PeekNext();
667
    FormulaToken* PeekPrevNoSpaces() const;    /// Only after Reset/First/Next/Last/Prev!
668
    FormulaToken* PeekNextNoSpaces() const;    /// Only after Reset/First/Next/Last/Prev!
669
670
    FormulaToken* FirstRPN()
671
19.7k
    {
672
19.7k
        mnIndex = 0;
673
19.7k
        return NextRPN();
674
19.7k
    }
675
676
    FormulaToken* NextRPN();
677
678
    FormulaToken* LastRPN()
679
0
    {
680
0
        mnIndex = mpFTA->GetCodeLen();
681
0
        return PrevRPN();
682
0
    }
683
684
    FormulaToken* PrevRPN();
685
686
    void AfterRemoveToken( sal_uInt16 nOffset, sal_uInt16 nCount );
687
};
688
689
690
} // formula
691
692
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */