Coverage Report

Created: 2026-08-14 10:22

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
38.4k
    explicit            MissingConvention( Convention eConvention ) : meConvention(eConvention) {}
86
27.1k
    bool        isPODF() const  { return meConvention == FORMULA_MISSING_CONVENTION_PODF; }
87
25.7k
    bool        isODFF() const  { return meConvention == FORMULA_MISSING_CONVENTION_ODFF; }
88
24.4k
    bool        isOOXML() const  { return meConvention == FORMULA_MISSING_CONVENTION_OOXML; }
89
63.5k
    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
38.4k
        MissingConvention( bODFF ?
99
32.6k
                MissingConvention::FORMULA_MISSING_CONVENTION_ODFF :
100
38.4k
                MissingConvention::FORMULA_MISSING_CONVENTION_PODF)
101
38.4k
        {
102
38.4k
        }
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
15.0M
        mpBegin(pBegin),
126
15.0M
        mpEnd(pBegin + nSize)
127
15.0M
    {
128
15.0M
    }
129
130
    FormulaToken** begin() const
131
14.9M
    {
132
14.9M
        return mpBegin;
133
14.9M
    }
134
135
    FormulaToken** end() const
136
15.0M
    {
137
15.0M
        return mpEnd;
138
15.0M
    }
139
};
140
141
class FORMULA_DLLPUBLIC FormulaTokenArrayReferencesIterator
142
{
143
private:
144
    FormulaToken** maIter;
145
    FormulaToken** maEnd;
146
147
    void nextReference()
148
108k
    {
149
127k
        while (maIter != maEnd)
150
72.0k
        {
151
72.0k
            switch ((*maIter)->GetType())
152
72.0k
            {
153
51.9k
            case svSingleRef:
154
53.3k
            case svDoubleRef:
155
53.3k
            case svExternalSingleRef:
156
53.3k
            case svExternalDoubleRef:
157
53.3k
                return;
158
18.6k
            default:
159
18.6k
                ++maIter;
160
72.0k
            }
161
72.0k
        }
162
108k
    }
163
164
    enum class Dummy { Flag };
165
166
    FormulaTokenArrayReferencesIterator(const FormulaTokenArrayStandardRange& rRange, Dummy) :
167
55.0k
        maIter(rRange.end()),
168
55.0k
        maEnd(rRange.end())
169
55.0k
    {
170
55.0k
    }
171
172
public:
173
    FormulaTokenArrayReferencesIterator(const FormulaTokenArrayStandardRange& rRange) :
174
55.0k
        maIter(rRange.begin()),
175
55.0k
        maEnd(rRange.end())
176
55.0k
    {
177
55.0k
        nextReference();
178
55.0k
    }
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
53.3k
    {
189
53.3k
        assert(maIter != maEnd);
190
53.3k
        ++maIter;
191
53.3k
        nextReference();
192
53.3k
        return *this;
193
53.3k
    }
194
195
    FormulaToken* operator*() const
196
53.3k
    {
197
53.3k
        return *maIter;
198
53.3k
    }
199
200
    bool operator==(const FormulaTokenArrayReferencesIterator& rhs) const
201
108k
    {
202
108k
        return maIter == rhs.maIter;
203
108k
    }
204
205
    bool operator!=(const FormulaTokenArrayReferencesIterator& rhs) const
206
108k
    {
207
108k
        return !operator==(rhs);
208
108k
    }
209
210
    static FormulaTokenArrayReferencesIterator endOf(const FormulaTokenArrayStandardRange& rRange)
211
55.0k
    {
212
55.0k
        return FormulaTokenArrayReferencesIterator(rRange, Dummy::Flag);
213
55.0k
    }
214
};
215
216
class FORMULA_DLLPUBLIC FormulaTokenArrayReferencesRange
217
{
218
private:
219
    const FormulaTokenArray& mrFTA;
220
221
public:
222
    FormulaTokenArrayReferencesRange(const FormulaTokenArray& rFTA) :
223
55.0k
        mrFTA(rFTA)
224
55.0k
    {
225
55.0k
    }
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 had 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 had 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
46.7k
    void SetFromRangeName( bool b ) { mbFromRangeName = b; }
304
1.13M
    bool IsFromRangeName() const { return mbFromRangeName; }
305
306
4.11k
    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
15.8M
    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.19M
    {
322
1.19M
        if (nIdx >= nLen)
323
0
            return nullptr;
324
1.19M
        return pCode[nIdx];
325
1.19M
    }
326
327
    /// Peek at nIdx-1 if not out of bounds, decrements nIdx if successful. Returns NULL 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
19.6M
    {
333
19.6M
        if (nIdx == 0 || nIdx > nLen)
334
1.88M
            return ocNone;
335
336
17.7M
        return pCode[nIdx-1]->GetOpCode();
337
19.6M
    }
338
339
    FormulaToken* FirstRPNToken() const;
340
    FormulaToken* LastRPNToken() const;
341
342
    bool HasReferences() const;
343
344
    bool    HasExternalRef() const;
345
    bool    HasOpCode( OpCode ) const;
346
    bool    HasOpCodeRPN( OpCode ) const;
347
    /// Token of type svIndex or opcode ocColRowName
348
    bool    HasNameOrColRowName() const;
349
350
    /**
351
     * Check if the token array contains any of specified opcode tokens.
352
     *
353
     * @param rOpCodes collection of opcodes to check against.
354
     *
355
     * @return true if the token array contains at least one of the specified
356
     *         opcode tokens, false otherwise.
357
     */
358
    bool HasOpCodes( const unordered_opcode_set& rOpCodes ) const;
359
360
    /// Assign pRPN to point to a newly created array filled with the data from pData
361
    void CreateNewRPNArrayFromData( FormulaToken** pData, sal_uInt16 nSize )
362
1.62M
    {
363
1.62M
        pRPN = std::make_unique<FormulaToken*[]>(nSize);
364
1.62M
        nRPN = nSize;
365
1.62M
        memcpy( pRPN.get(), pData, nSize * sizeof( FormulaToken* ) );
366
1.62M
    }
367
368
    // Assign pCode to point to a newly created array filled with data; the array is sized exactly
369
    // to size, so it is final:
370
3.40k
    void CreateNewCodeArrayFromData(FormulaToken ** data, sal_uInt16 size) {
371
3.40k
        pCode = std::make_unique<FormulaToken*[]>(size);
372
3.40k
        nLen = size;
373
3.40k
        memcpy(pCode.get(), data, size * sizeof (FormulaToken *));
374
3.40k
        mbFinalized = true;
375
3.40k
    }
376
377
233M
    FormulaToken** GetArray() const  { return pCode.get(); }
378
379
    FormulaTokenArrayStandardRange Tokens() const
380
13.3M
    {
381
13.3M
        return FormulaTokenArrayStandardRange(pCode.get(), nLen);
382
13.3M
    }
383
384
21.6M
    FormulaToken** GetCode()  const  { return pRPN.get(); }
385
386
    FormulaTokenArrayStandardRange RPNTokens() const
387
1.69M
    {
388
1.69M
        return FormulaTokenArrayStandardRange(pRPN.get(), nRPN);
389
1.69M
    }
390
391
    FormulaTokenArrayReferencesRange References() const
392
55.0k
    {
393
55.0k
        return FormulaTokenArrayReferencesRange(*this);
394
55.0k
    }
395
396
210M
    sal_uInt16     GetLen() const     { return nLen; }
397
54.2M
    sal_uInt16     GetCodeLen() const { return nRPN; }
398
75.2M
    FormulaError   GetCodeError() const      { return nError; }
399
417k
    void      SetCodeError( FormulaError n )  { nError = n; }
400
291k
    void      SetHyperLink( bool bVal ) { bHyperLink = bVal; }
401
257k
    bool      IsHyperLink() const       { return bHyperLink; }
402
403
39
    void SetDynamicArrayFunction(bool bValue) { mbDynamicArrayFunction = bValue; }
404
0
    bool HasDynamicArrayFunction() const { return mbDynamicArrayFunction; }
405
406
102k
    ScRecalcMode    GetRecalcMode() const { return nMode; }
407
408
    void            SetCombinedBitsRecalcMode( ScRecalcMode nBits )
409
533k
                                { nMode |= nBits & ~ScRecalcMode::EMask; }
410
    ScRecalcMode    GetCombinedBitsRecalcMode() const
411
454k
                                { return nMode & ~ScRecalcMode::EMask; }
412
413
                    /** Exclusive bits already set in nMode are zero'ed, nBits
414
                        may contain combined bits, but only one exclusive bit
415
                        may be set! */
416
    void            SetMaskedRecalcMode( ScRecalcMode nBits )
417
454k
                                { nMode = GetCombinedBitsRecalcMode() | nBits; }
418
419
                    /** Bits aren't set directly but validated and handled
420
                        according to priority if more than one exclusive bit
421
                        was set. */
422
    void            AddRecalcMode( ScRecalcMode nBits );
423
424
14.4M
    void            ClearRecalcMode() { nMode = ScRecalcMode::NORMAL; }
425
    void            SetExclusiveRecalcModeNormal()
426
7.43k
                                { SetMaskedRecalcMode( ScRecalcMode::NORMAL ); }
427
    void            SetExclusiveRecalcModeAlways()
428
44.2k
                                { SetMaskedRecalcMode( ScRecalcMode::ALWAYS ); }
429
    void            SetRecalcModeForced()
430
104k
                                { nMode |= ScRecalcMode::FORCED; }
431
    void            SetRecalcModeOnRefMove()
432
6.82k
                                { nMode |= ScRecalcMode::ONREFMOVE; }
433
    bool            IsRecalcModeNormal() const
434
7.41M
                                { return bool(nMode & ScRecalcMode::NORMAL); }
435
    bool            IsRecalcModeAlways() const
436
8.85M
                                { return bool(nMode & ScRecalcMode::ALWAYS); }
437
    bool            IsRecalcModeForced() const
438
2.25M
                                { return bool(nMode & ScRecalcMode::FORCED); }
439
    bool            IsRecalcModeOnRefMove() const
440
0
                                { return bool(nMode & ScRecalcMode::ONREFMOVE); }
441
                    /** Whether recalculation must happen after import, for
442
                        example OOXML. */
443
    bool            IsRecalcModeMustAfterImport() const
444
1.57M
                                { return (nMode & ScRecalcMode::EMask) <= ScRecalcMode::ONLOAD_ONCE; }
445
    void            ClearRecalcModeMustAfterImport()
446
350k
                                {
447
350k
                                    if (IsRecalcModeMustAfterImport() && !IsRecalcModeAlways())
448
5.12k
                                        SetExclusiveRecalcModeNormal();
449
350k
                                }
450
451
                            /** Get OpCode of the most outer function */
452
    inline OpCode           GetOuterFuncOpCode() const;
453
454
                            /** Operators +,-,*,/,^,&,=,<>,<,>,<=,>=
455
                                with DoubleRef in Formula? */
456
    bool                    HasMatrixDoubleRefOps() const;
457
458
    virtual FormulaToken* AddOpCode(OpCode e);
459
460
    /** Adds the single token to array.
461
        Derived classes must override it when they want to support derived classes from FormulaToken.
462
        @return true        when an error occurs
463
    */
464
    virtual bool AddFormulaToken(
465
        const css::sheet::FormulaToken& rToken, svl::SharedStringPool& rSPool,
466
        ExternalReferenceHelper* pExtRef );
467
468
    /** fill the array with the tokens from the sequence.
469
        It calls AddFormulaToken for each token in the list.
470
        @param  _aSequence  the token to add
471
        @return true        when an error occurs
472
    */
473
    bool Fill(
474
        const css::uno::Sequence<css::sheet::FormulaToken>& rSequence,
475
        svl::SharedStringPool& rSPool, ExternalReferenceHelper* pExtRef );
476
477
    /**
478
     * Do some checking based on the individual tokens. For now, we use this
479
     * only to check whether we can vectorize the token array.
480
     */
481
    virtual void CheckToken( const FormulaToken& t );
482
483
    /**
484
     * Call CheckToken() for all RPN tokens.
485
     */
486
    void CheckAllRPNTokens();
487
488
    /** Clones the token and then adds the clone to the pCode array.
489
        For just new'ed tokens use Add() instead of cloning it again.
490
        Use this AddToken() when adding a token from another origin.
491
     */
492
    FormulaToken* AddToken( const FormulaToken& );
493
494
    FormulaToken* AddString( const svl::SharedString& rStr );
495
    FormulaToken* AddStringName(const svl::SharedString& rString, bool bOptional = false);
496
    FormulaToken* AddDPFieldName( const svl::SharedString& rStr );
497
    FormulaToken* AddDouble( double fVal );
498
    void          AddExternal( const sal_Unicode* pStr );
499
    /** Xcl import may play dirty tricks with OpCode!=ocExternal.
500
        Others don't use! */
501
    FormulaToken* AddExternal( const OUString& rStr, OpCode eOp = ocExternal );
502
    FormulaToken* AddBad( const OUString& rStr );          /// ocBad with OUString
503
    FormulaToken* AddStringXML( const OUString& rStr );    /// ocStringXML with OUString, temporary during import
504
    FormulaToken* AddStringName( const OUString& rStr );   /// ocStringName with OUString - Lambda functions
505
    FormulaToken* AddDPFieldName( const OUString& rStr );   /// ocDPFieldName with OUString - Pivot Table DataPilot field names
506
    FormulaToken* AddError( FormulaError nErr );
507
508
    virtual FormulaToken* MergeArray( );
509
510
    /** Assignment with incrementing references of FormulaToken entries
511
        (not copied!) */
512
    FormulaTokenArray& operator=( const FormulaTokenArray& );
513
    FormulaTokenArray& operator=( FormulaTokenArray&& );
514
515
    /** Determines if this formula needs any changes to convert it to something
516
        previous versions of OOo could consume (Plain Old Formula, pre-ODFF, or
517
        also ODFF) */
518
    bool                NeedsPodfRewrite( const MissingConventionODF & rConv );
519
520
    /** Determines if this formula needs any changes to convert it to OOXML. */
521
    bool                NeedsOoxmlRewrite();
522
523
    /** Rewrites to Plain Old Formula or OOXML, substituting missing parameters. The
524
        FormulaTokenArray* returned is new'ed. */
525
    FormulaTokenArray*  RewriteMissing( const MissingConvention & rConv );
526
527
    /** Determines if this formula may be followed by a reference. */
528
    bool                MayReferenceFollow();
529
530
    /** Re-intern SharedString in case the SharedStringPool differs. */
531
    void ReinternStrings( svl::SharedStringPool& rPool );
532
};
533
534
inline OpCode FormulaTokenArray::GetOuterFuncOpCode() const
535
0
{
536
0
    if ( pRPN && nRPN )
537
0
        return pRPN[nRPN-1]->GetOpCode();
538
0
    return ocNone;
539
0
}
540
541
inline FormulaTokenArrayReferencesIterator FormulaTokenArrayReferencesRange::begin()
542
55.0k
{
543
55.0k
    return FormulaTokenArrayReferencesIterator(mrFTA.Tokens());
544
55.0k
}
545
546
inline FormulaTokenArrayReferencesIterator FormulaTokenArrayReferencesRange::end()
547
55.0k
{
548
55.0k
    return FormulaTokenArrayReferencesIterator::endOf(mrFTA.Tokens());
549
55.0k
}
550
551
class FORMULA_DLLPUBLIC FormulaTokenIterator
552
{
553
    struct Item
554
    {
555
    public:
556
        const FormulaTokenArray* pArr;
557
        short nPC;
558
        short nStop;
559
        bool bLambda;
560
561
        Item(const FormulaTokenArray* arr, short pc, short stop, bool lambda);
562
    };
563
564
    std::vector<Item> maStack;
565
566
public:
567
    FormulaTokenIterator( const FormulaTokenArray& );
568
   ~FormulaTokenIterator();
569
    void    Reset();
570
    const   FormulaToken* Next();
571
    const   FormulaToken* PeekNextOperator();
572
    bool    IsEndOfPath() const;    /// if a jump or subroutine path is done
573
25.2k
    bool    HasStacked() const { return maStack.size() > 1; }
574
142
    short   GetPC() const { return maStack.back().nPC; }
575
576
    /** Jump or subroutine call.
577
        Program counter values will be incremented before code is executed =>
578
        positions are to be passed with -1 offset.
579
        @param nStart
580
            Start on code at position nStart+1 (yes, pass with offset -1)
581
        @param nNext
582
            After subroutine continue with instruction at position nNext+1
583
        @param nStop
584
            Stop before reaching code at position nStop. If not specified the
585
            default is to either run the entire code, or to stop if an ocSep or
586
            ocClose is encountered, which are only present in ocIf or ocChoose
587
            jumps.
588
      */
589
    void Jump( short nStart, short nNext, short nStop = SHRT_MAX );
590
    void Push( const FormulaTokenArray* );
591
    void Pop();
592
    void FrontPop();
593
    void Lambda( bool bOpt );
594
    bool IsLambda() const;
595
596
    /** Reconstruct the iterator afresh from a token array
597
    */
598
    void ReInit( const FormulaTokenArray& );
599
600
private:
601
    SAL_DLLPRIVATE const FormulaToken* GetNonEndOfPathToken( short nIdx ) const;
602
};
603
604
// For use in SAL_INFO, SAL_WARN etc
605
606
template<typename charT, typename traits>
607
inline std::basic_ostream<charT, traits> & operator <<(std::basic_ostream<charT, traits> & stream, const FormulaTokenArray& point)
608
{
609
    stream <<
610
        static_cast<const void*>(&point) <<
611
        ":{nLen=" << point.GetLen() <<
612
        ",nRPN=" << point.GetCodeLen() <<
613
        ",pCode=" << static_cast<void*>(point.GetArray()) <<
614
        ",pRPN=" << static_cast<void*>(point.GetCode()) <<
615
        "}";
616
617
    return stream;
618
}
619
620
class FORMULA_DLLPUBLIC FormulaTokenArrayPlainIterator
621
{
622
private:
623
    const FormulaTokenArray* mpFTA;
624
    sal_uInt16 mnIndex;                 // Current step index
625
626
public:
627
    FormulaTokenArrayPlainIterator( const FormulaTokenArray& rFTA ) :
628
19.7M
        mpFTA( &rFTA ),
629
19.7M
        mnIndex( 0 )
630
19.7M
    {
631
19.7M
    }
632
633
    void Reset()
634
3.89M
    {
635
3.89M
        mnIndex = 0;
636
3.89M
    }
637
638
    sal_uInt16 GetIndex() const
639
19.6M
    {
640
19.6M
        return mnIndex;
641
19.6M
    }
642
643
    FormulaToken* First()
644
39.4k
    {
645
39.4k
        mnIndex = 0;
646
39.4k
        return Next();
647
39.4k
    }
648
649
    void Jump(sal_uInt16 nIndex)
650
102k
    {
651
102k
        mnIndex = nIndex;
652
102k
    }
653
654
    void StepBack()
655
138
    {
656
138
        assert(mnIndex > 0);
657
138
        mnIndex--;
658
138
    }
659
660
    FormulaToken* Next();
661
    FormulaToken* NextNoSpaces();
662
    FormulaToken* GetNextName();
663
    FormulaToken* GetNextStringNameRPN();
664
    FormulaToken* GetNextDPFieldNameRPN();
665
    FormulaToken* GetNextReference();
666
    FormulaToken* GetNextReferenceRPN();
667
    FormulaToken* GetNextReferenceOrName();
668
    FormulaToken* GetNextColRowName();
669
    FormulaToken* PeekNext();
670
    FormulaToken* PeekPrevNoSpaces() const;    /// Only after Reset/First/Next/Last/Prev!
671
    FormulaToken* PeekNextNoSpaces() const;    /// Only after Reset/First/Next/Last/Prev!
672
673
    FormulaToken* FirstRPN()
674
45.6k
    {
675
45.6k
        mnIndex = 0;
676
45.6k
        return NextRPN();
677
45.6k
    }
678
679
    FormulaToken* NextRPN();
680
681
    FormulaToken* LastRPN()
682
0
    {
683
0
        mnIndex = mpFTA->GetCodeLen();
684
0
        return PrevRPN();
685
0
    }
686
687
    FormulaToken* PrevRPN();
688
689
    void AfterRemoveToken( sal_uInt16 nOffset, sal_uInt16 nCount );
690
};
691
692
693
} // formula
694
695
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */