LibreOffice Module formula (master) 1
tokenarray.hxx
Go to the documentation of this file.
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#ifndef INCLUDED_FORMULA_TOKENARRAY_HXX
21#define INCLUDED_FORMULA_TOKENARRAY_HXX
22
23#include <climits>
24#include <memory>
25#include <ostream>
26#include <type_traits>
27#include <unordered_set>
28#include <unordered_map>
29#include <vector>
30
33#include <formula/opcode.hxx>
34#include <formula/token.hxx>
36#include <rtl/ustring.hxx>
37#include <sal/types.h>
38
39namespace com::sun::star {
40 namespace sheet { struct FormulaToken; }
41}
42
43namespace com::sun::star::uno { template <typename > class Sequence; }
44namespace formula { class FormulaTokenArray; }
45
46namespace svl {
47
48class SharedString;
49class SharedStringPool;
50
51}
52
53// RecalcMode access only via TokenArray SetExclusiveRecalcMode...() /
54// IsRecalcMode...()
55
56// Only one of the exclusive bits can be set and one must be set,
57// handled by TokenArray SetExclusiveRecalcMode...() methods.
58// Exclusive bits are ordered by priority, AddRecalcMode() relies on that.
60{
61 ALWAYS = 0x01, // exclusive, always
62 ONLOAD_MUST = 0x02, // exclusive, always after load
63 ONLOAD_ONCE = 0x04, // exclusive, once after load, import filter
64 ONLOAD_LENIENT = 0x08, // exclusive, lenient after load (eg. macros not always, aliens, ...)
65 NORMAL = 0x10, // exclusive
66 FORCED = 0x20, // combined, also if cell isn't visible, for macros with side effects
67 ONREFMOVE = 0x40, // combined, if reference was moved
68 EMask = ALWAYS | ONLOAD_MUST | ONLOAD_LENIENT | ONLOAD_ONCE | NORMAL // mask of exclusive bits
69};
70namespace o3tl
71{
72 template<> struct typed_flags<ScRecalcMode> : is_typed_flags<ScRecalcMode, 0x7f> {};
73}
74
75namespace formula
76{
77
79{
80public:
82 {
85 FORMULA_MISSING_CONVENTION_OOXML
86 };
87 explicit MissingConvention( Convention eConvention ) : meConvention(eConvention) {}
88 bool isPODF() const { return meConvention == FORMULA_MISSING_CONVENTION_PODF; }
89 bool isODFF() const { return meConvention == FORMULA_MISSING_CONVENTION_ODFF; }
90 bool isOOXML() const { return meConvention == FORMULA_MISSING_CONVENTION_OOXML; }
91 Convention getConvention() const { return meConvention; }
92private:
94};
95
97{
98public:
99 explicit MissingConventionODF( bool bODFF ) :
100 MissingConvention( bODFF ?
101 MissingConvention::FORMULA_MISSING_CONVENTION_ODFF :
102 MissingConvention::FORMULA_MISSING_CONVENTION_PODF)
103 {
104 }
105 // Implementation and usage only in token.cxx
106 inline bool isRewriteNeeded( OpCode eOp ) const;
107};
108
110{
111public:
112 explicit MissingConventionOOXML() : MissingConvention( MissingConvention::FORMULA_MISSING_CONVENTION_OOXML) {}
113 // Implementation and usage only in token.cxx
114 static inline bool isRewriteNeeded( OpCode eOp );
115};
116
117typedef std::unordered_set<OpCode, std::hash<std::underlying_type<OpCode>::type> > unordered_opcode_set;
118
120{
121private:
124
125public:
126 FormulaTokenArrayStandardRange(FormulaToken** pBegin, sal_uInt16 nSize) :
127 mpBegin(pBegin),
128 mpEnd(pBegin + nSize)
129 {
130 }
131
133 {
134 return mpBegin;
135 }
136
138 {
139 return mpEnd;
140 }
141};
142
144{
145private:
148
150 {
151 while (maIter != maEnd)
152 {
153 switch ((*maIter)->GetType())
154 {
155 case svSingleRef:
156 case svDoubleRef:
159 return;
160 default:
161 ++maIter;
162 }
163 }
164 }
165
166 enum class Dummy { Flag };
167
169 maIter(rRange.end()),
170 maEnd(rRange.end())
171 {
172 }
173
174public:
176 maIter(rRange.begin()),
177 maEnd(rRange.end())
178 {
179 nextReference();
180 }
181
183 {
185 operator++();
186 return result;
187 }
188
190 {
191 assert(maIter != maEnd);
192 ++maIter;
193 nextReference();
194 return *this;
195 }
196
198 {
199 return *maIter;
200 }
201
203 {
204 return maIter == rhs.maIter;
205 }
206
208 {
209 return !operator==(rhs);
210 }
211
213 {
214 return FormulaTokenArrayReferencesIterator(rRange, Dummy::Flag);
215 }
216};
217
219{
220private:
222
223public:
225 mrFTA(rFTA)
226 {
227 }
228
230
232};
233
235{
236protected:
237 std::unique_ptr<FormulaToken*[]> pCode; // Token code array
238 FormulaToken** pRPN; // RPN array
239 sal_uInt16 nLen; // Length of token array
240 sal_uInt16 nRPN; // Length of RPN array
241 FormulaError nError; // Error code
242 ScRecalcMode nMode; // Flags to indicate when to recalc this code
243 bool bHyperLink :1; // If HYPERLINK() occurs in the formula.
244 bool mbFromRangeName :1; // If this array originates from a named expression
245 bool mbShareable :1; // Whether or not it can be shared with adjacent cells.
246 bool mbFinalized :1; // Whether code arrays have their final used size and no more tokens can be added.
247
248protected:
249 void Assign( const FormulaTokenArray& );
250 void Assign( sal_uInt16 nCode, FormulaToken **pTokens );
251 void Move( FormulaTokenArray&& );
252
255
256public:
258 {
260 CODE_AND_RPN
261 };
262
273 FormulaToken* ReplaceToken( sal_uInt16 nOffset, FormulaToken*, ReplaceMode eMode );
274
287 sal_uInt16 RemoveToken( sal_uInt16 nOffset, sal_uInt16 nCount );
288
294 virtual ~FormulaTokenArray();
295
296 virtual void Clear();
297
301 void Finalize();
302
303 void SetFromRangeName( bool b ) { mbFromRangeName = b; }
304 bool IsFromRangeName() const { return mbFromRangeName; }
305
306 void SetShareable( bool b ) { mbShareable = b; }
307
314 bool IsShareable() const { return mbShareable; }
315
316 void DelRPN();
317 FormulaToken* FirstToken() const;
318
320 FormulaToken* TokenAt( sal_uInt16 nIdx) const
321 {
322 if (nIdx >= nLen)
323 return nullptr;
324 return pCode[nIdx];
325 }
326
328 FormulaToken* PeekPrev( sal_uInt16 & nIdx ) const;
329
331 OpCode OpCodeBefore( sal_uInt16 nIdx) const
332 {
333 if (nIdx == 0 || nIdx > nLen)
334 return ocNone;
335
336 return pCode[nIdx-1]->GetOpCode();
337 }
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;
348 bool HasNameOrColRowName() const;
349
358 bool HasOpCodes( const unordered_opcode_set& rOpCodes ) const;
359
361 void CreateNewRPNArrayFromData( FormulaToken** pData, sal_uInt16 nSize )
362 {
363 pRPN = new FormulaToken*[ nSize ];
364 nRPN = nSize;
365 memcpy( pRPN, pData, nSize * sizeof( FormulaToken* ) );
366 }
367
368 FormulaToken** GetArray() const { return pCode.get(); }
369
371 {
372 return FormulaTokenArrayStandardRange(pCode.get(), nLen);
373 }
374
375 FormulaToken** GetCode() const { return pRPN; }
376
378 {
379 return FormulaTokenArrayStandardRange(pRPN, nRPN);
380 }
381
383 {
385 }
386
387 sal_uInt16 GetLen() const { return nLen; }
388 sal_uInt16 GetCodeLen() const { return nRPN; }
389 FormulaError GetCodeError() const { return nError; }
390 void SetCodeError( FormulaError n ) { nError = n; }
391 void SetHyperLink( bool bVal ) { bHyperLink = bVal; }
392 bool IsHyperLink() const { return bHyperLink; }
393
394 ScRecalcMode GetRecalcMode() const { return nMode; }
395
397 { nMode |= nBits & ~ScRecalcMode::EMask; }
399 { return nMode & ~ScRecalcMode::EMask; }
400
405 { nMode = GetCombinedBitsRecalcMode() | nBits; }
406
410 void AddRecalcMode( ScRecalcMode nBits );
411
414 { SetMaskedRecalcMode( ScRecalcMode::NORMAL ); }
416 { SetMaskedRecalcMode( ScRecalcMode::ALWAYS ); }
418 { nMode |= ScRecalcMode::FORCED; }
420 { nMode |= ScRecalcMode::ONREFMOVE; }
422 { return bool(nMode & ScRecalcMode::NORMAL); }
424 { return bool(nMode & ScRecalcMode::ALWAYS); }
426 { return bool(nMode & ScRecalcMode::FORCED); }
428 { return bool(nMode & ScRecalcMode::ONREFMOVE); }
432 { return (nMode & ScRecalcMode::EMask) <= ScRecalcMode::ONLOAD_ONCE; }
434 {
435 if (IsRecalcModeMustAfterImport() && !IsRecalcModeAlways())
436 SetExclusiveRecalcModeNormal();
437 }
438
440 inline OpCode GetOuterFuncOpCode() const;
441
444 bool HasMatrixDoubleRefOps() const;
445
446 virtual FormulaToken* AddOpCode(OpCode e);
447
452 virtual bool AddFormulaToken(
453 const css::sheet::FormulaToken& rToken, svl::SharedStringPool& rSPool,
454 ExternalReferenceHelper* pExtRef );
455
461 bool Fill(
462 const css::uno::Sequence<css::sheet::FormulaToken>& rSequence,
464
469 virtual void CheckToken( const FormulaToken& t );
470
474 void CheckAllRPNTokens();
475
480 FormulaToken* AddToken( const FormulaToken& );
481
482 FormulaToken* AddString( const svl::SharedString& rStr );
483 FormulaToken* AddDouble( double fVal );
484 void AddExternal( const sal_Unicode* pStr );
487 FormulaToken* AddExternal( const OUString& rStr, OpCode eOp = ocExternal );
488 FormulaToken* AddBad( const OUString& rStr );
489 FormulaToken* AddStringXML( const OUString& rStr );
490
491 virtual FormulaToken* MergeArray( );
492
495 FormulaTokenArray& operator=( const FormulaTokenArray& );
496 FormulaTokenArray& operator=( FormulaTokenArray&& );
497
501 bool NeedsPodfRewrite( const MissingConventionODF & rConv );
502
504 bool NeedsOoxmlRewrite();
505
508 FormulaTokenArray* RewriteMissing( const MissingConvention & rConv );
509
511 bool MayReferenceFollow();
512
514 void ReinternStrings( svl::SharedStringPool& rPool );
515};
516
518{
519 if ( pRPN && nRPN )
520 return pRPN[nRPN-1]->GetOpCode();
521 return ocNone;
522}
523
525{
527}
528
530{
532}
533
535{
536 struct Item
537 {
538 public:
540 short nPC;
541 short nStop;
542
543 Item(const FormulaTokenArray* arr, short pc, short stop);
544 };
545
546 std::vector<Item> maStack;
547
548public:
551 void Reset();
552 const FormulaToken* Next();
553 const FormulaToken* PeekNextOperator();
554 bool IsEndOfPath() const;
555 bool HasStacked() const { return maStack.size() > 1; }
556 short GetPC() const { return maStack.back().nPC; }
557
571 void Jump( short nStart, short nNext, short nStop = SHRT_MAX );
572 void Push( const FormulaTokenArray* );
573 void Pop();
574
577 void ReInit( const FormulaTokenArray& );
578
579private:
580 const FormulaToken* GetNonEndOfPathToken( short nIdx ) const;
581};
582
583// For use in SAL_INFO, SAL_WARN etc
584
585template<typename charT, typename traits>
586inline std::basic_ostream<charT, traits> & operator <<(std::basic_ostream<charT, traits> & stream, const FormulaTokenArray& point)
587{
588 stream <<
589 static_cast<const void*>(&point) <<
590 ":{nLen=" << point.GetLen() <<
591 ",nRPN=" << point.GetCodeLen() <<
592 ",pCode=" << static_cast<void*>(point.GetArray()) <<
593 ",pRPN=" << static_cast<void*>(point.GetCode()) <<
594 "}";
595
596 return stream;
597}
598
600{
601private:
603 sal_uInt16 mnIndex; // Current step index
604
605public:
607 mpFTA( &rFTA ),
608 mnIndex( 0 )
609 {
610 }
611
612 void Reset()
613 {
614 mnIndex = 0;
615 }
616
617 sal_uInt16 GetIndex() const
618 {
619 return mnIndex;
620 }
621
623 {
624 mnIndex = 0;
625 return Next();
626 }
627
628 void Jump(sal_uInt16 nIndex)
629 {
630 mnIndex = nIndex;
631 }
632
633 void StepBack()
634 {
635 assert(mnIndex > 0);
636 mnIndex--;
637 }
638
640 FormulaToken* NextNoSpaces();
641 FormulaToken* GetNextName();
642 FormulaToken* GetNextReference();
643 FormulaToken* GetNextReferenceRPN();
644 FormulaToken* GetNextReferenceOrName();
645 FormulaToken* GetNextColRowName();
646 FormulaToken* PeekNext();
647 FormulaToken* PeekPrevNoSpaces() const;
648 FormulaToken* PeekNextNoSpaces() const;
649
651 {
652 mnIndex = 0;
653 return NextRPN();
654 }
655
656 FormulaToken* NextRPN();
657
659 {
660 mnIndex = mpFTA->GetCodeLen();
661 return PrevRPN();
662 }
663
664 FormulaToken* PrevRPN();
665
666 void AfterRemoveToken( sal_uInt16 nOffset, sal_uInt16 nCount );
667};
668
669
670} // formula
671
672#endif // INCLUDED_FORMULA_TOKENARRAY_HXX
673
674/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const Point maEnd
std::vector< Reference< XAnimationNode > >::iterator maIter
const B2DPoint * mpEnd
const FormulaTokenArray * mpFTA
Definition: tokenarray.hxx:602
FormulaTokenArrayPlainIterator(const FormulaTokenArray &rFTA)
Definition: tokenarray.hxx:606
FormulaToken * FirstRPN()
Only after Reset/First/Next/Last/Prev!
Definition: tokenarray.hxx:650
bool operator==(const FormulaTokenArrayReferencesIterator &rhs) const
Definition: tokenarray.hxx:202
FormulaTokenArrayReferencesIterator(const FormulaTokenArrayStandardRange &rRange, Dummy)
Definition: tokenarray.hxx:168
static FormulaTokenArrayReferencesIterator endOf(const FormulaTokenArrayStandardRange &rRange)
Definition: tokenarray.hxx:212
FormulaTokenArrayReferencesIterator(const FormulaTokenArrayStandardRange &rRange)
Definition: tokenarray.hxx:175
FormulaTokenArrayReferencesIterator operator++(int)
Definition: tokenarray.hxx:182
FormulaTokenArrayReferencesIterator const & operator++()
Definition: tokenarray.hxx:189
bool operator!=(const FormulaTokenArrayReferencesIterator &rhs) const
Definition: tokenarray.hxx:207
FormulaTokenArrayReferencesRange(const FormulaTokenArray &rFTA)
Definition: tokenarray.hxx:224
FormulaTokenArrayReferencesIterator begin()
Definition: tokenarray.hxx:524
FormulaTokenArrayReferencesIterator end()
Definition: tokenarray.hxx:529
FormulaTokenArrayStandardRange(FormulaToken **pBegin, sal_uInt16 nSize)
Definition: tokenarray.hxx:126
OpCode GetOuterFuncOpCode() const
Get OpCode of the most outer function.
Definition: tokenarray.hxx:517
FormulaToken * TokenAt(sal_uInt16 nIdx) const
Return pCode[nIdx], or nullptr if nIdx is out of bounds.
Definition: tokenarray.hxx:320
bool IsShareable() const
Check if this token array is shareable between multiple adjacent formula cells.
Definition: tokenarray.hxx:314
void SetHyperLink(bool bVal)
Definition: tokenarray.hxx:391
bool IsRecalcModeNormal() const
Definition: tokenarray.hxx:421
FormulaTokenArrayReferencesRange References() const
Definition: tokenarray.hxx:382
sal_uInt16 GetLen() const
Definition: tokenarray.hxx:387
bool IsRecalcModeAlways() const
Definition: tokenarray.hxx:423
void CreateNewRPNArrayFromData(FormulaToken **pData, sal_uInt16 nSize)
Assign pRPN to point to a newly created array filled with the data from pData.
Definition: tokenarray.hxx:361
ScRecalcMode GetCombinedBitsRecalcMode() const
Definition: tokenarray.hxx:398
void SetCombinedBitsRecalcMode(ScRecalcMode nBits)
Definition: tokenarray.hxx:396
bool IsRecalcModeForced() const
Definition: tokenarray.hxx:425
FormulaTokenArrayStandardRange Tokens() const
Definition: tokenarray.hxx:370
OpCode OpCodeBefore(sal_uInt16 nIdx) const
Return the opcode at pCode[nIdx-1], ocNone if nIdx-1 is out of bounds.
Definition: tokenarray.hxx:331
bool IsRecalcModeMustAfterImport() const
Whether recalculation must happen after import, for example OOXML.
Definition: tokenarray.hxx:431
FormulaToken ** GetArray() const
Definition: tokenarray.hxx:368
void SetCodeError(FormulaError n)
Definition: tokenarray.hxx:390
FormulaError GetCodeError() const
Definition: tokenarray.hxx:389
@ CODE_ONLY
replacement only in pCode
Definition: tokenarray.hxx:259
FormulaTokenArrayStandardRange RPNTokens() const
Definition: tokenarray.hxx:377
sal_uInt16 GetCodeLen() const
Definition: tokenarray.hxx:388
FormulaToken ** GetCode() const
Definition: tokenarray.hxx:375
void SetMaskedRecalcMode(ScRecalcMode nBits)
Exclusive bits already set in nMode are zero'ed, nBits may contain combined bits, but only one exclus...
Definition: tokenarray.hxx:404
bool IsRecalcModeOnRefMove() const
Definition: tokenarray.hxx:427
ScRecalcMode GetRecalcMode() const
Definition: tokenarray.hxx:394
std::unique_ptr< FormulaToken *[]> pCode
Definition: tokenarray.hxx:237
std::vector< Item > maStack
Definition: tokenarray.hxx:546
bool HasStacked() const
if a jump or subroutine path is done
Definition: tokenarray.hxx:555
OpCode GetOpCode() const
Definition: token.hxx:158
MissingConvention(Convention eConvention)
Definition: tokenarray.hxx:87
Convention getConvention() const
Definition: tokenarray.hxx:91
Reference< XOutputStream > stream
NORMAL
FormulaError
Definition: errorcodes.hxx:32
SotClipboardFormatId & operator++(SotClipboardFormatId &eFormat)
#define FORMULA_DLLPUBLIC
Definition: formuladllapi.h:28
sal_Int32 nIndex
sal_Int64 n
std::unique_ptr< sal_Int32[]> pData
def point()
void Clear(EHistoryType eHistory)
Fill
std::unordered_set< OpCode, std::hash< std::underlying_type< OpCode >::type > > unordered_opcode_set
Definition: tokenarray.hxx:117
@ svExternalDoubleRef
Definition: token.hxx:74
@ svDoubleRef
Definition: token.hxx:54
@ svExternalSingleRef
Definition: token.hxx:73
@ svSingleRef
Definition: token.hxx:53
std::basic_ostream< charT, traits > & operator<<(std::basic_ostream< charT, traits > &stream, const FormulaTokenArray &point)
Definition: tokenarray.hxx:586
enumrange< T >::Iterator begin(enumrange< T >)
end
OpCode
Definition: opcode.hxx:29
@ ocNone
Definition: opcode.hxx:515
@ ocExternal
Definition: opcode.hxx:34
const FormulaTokenArray * pArr
Definition: tokenarray.hxx:539
sal_uInt32 mnIndex
ScRecalcMode
Definition: tokenarray.hxx:60
unsigned char sal_uInt8
sal_uInt16 sal_Unicode
Any result
bool operator==(const XclFontData &rLeft, const XclFontData &rRight)