1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
25 #include <osl/diagnose.h>
26 #include <sal/log.hxx>
28 #include <com/sun/star/sheet/FormulaToken.hpp>
29 #include <formula/errorcodes.hxx>
30 #include <formula/token.hxx>
31 #include <formula/tokenarray.hxx>
32 #include <formula/FormulaCompiler.hxx>
33 #include <formula/compiler.hxx>
34 #include <svl/sharedstringpool.hxx>
40 using namespace com::sun::star
;
43 // --- helpers --------------------------------------------------------------
45 static bool lcl_IsReference( OpCode eOp
, StackVar eType
)
48 (eOp
== ocPush
&& (eType
== svSingleRef
|| eType
== svDoubleRef
))
49 || (eOp
== ocColRowNameAuto
&& eType
== svDoubleRef
)
50 || (eOp
== ocColRowName
&& eType
== svSingleRef
)
51 || (eOp
== ocMatRef
&& eType
== svSingleRef
)
55 // --- class FormulaToken --------------------------------------------------------
57 FormulaToken::FormulaToken( StackVar eTypeP
, OpCode e
) :
58 eOp(e
), eType( eTypeP
), eRefCntPolicy(RefCntPolicy::ThreadSafe
), mnRefCnt(0)
62 FormulaToken::FormulaToken( const FormulaToken
& r
) :
63 eOp(r
.eOp
), eType( r
.eType
), eRefCntPolicy(RefCntPolicy::ThreadSafe
), mnRefCnt(0)
67 FormulaToken::~FormulaToken()
71 bool FormulaToken::IsFunction() const
73 return (eOp
!= ocPush
&& eOp
!= ocBad
&& eOp
!= ocColRowName
&&
74 eOp
!= ocColRowNameAuto
&& eOp
!= ocName
&& eOp
!= ocDBArea
&&
76 (GetByte() != 0 // x parameters
77 || (SC_OPCODE_START_NO_PAR
<= eOp
&& eOp
< SC_OPCODE_STOP_NO_PAR
) // no parameter
78 || FormulaCompiler::IsOpCodeJumpCommand( eOp
) // @ jump commands
79 || (SC_OPCODE_START_1_PAR
<= eOp
&& eOp
< SC_OPCODE_STOP_1_PAR
) // one parameter
80 || (SC_OPCODE_START_2_PAR
<= eOp
&& eOp
< SC_OPCODE_STOP_2_PAR
) // x parameters (cByte==0 in
82 || eOp
== ocMacro
|| eOp
== ocExternal
// macros, AddIns
83 || eOp
== ocAnd
|| eOp
== ocOr
// former binary, now x parameters
84 || (eOp
>= ocInternalBegin
&& eOp
<= ocInternalEnd
) // internal
89 sal_uInt8
FormulaToken::GetParamCount() const
91 if ( eOp
< SC_OPCODE_STOP_DIV
&& eOp
!= ocExternal
&& eOp
!= ocMacro
&&
92 !FormulaCompiler::IsOpCodeJumpCommand( eOp
) &&
93 eOp
!= ocPercentSign
)
94 return 0; // parameters and specials
95 // ocIf... jump commands not for FAP, have cByte then
96 //2do: bool parameter whether FAP or not?
98 return GetByte(); // all functions, also ocExternal and ocMacro
99 else if (SC_OPCODE_START_BIN_OP
<= eOp
&& eOp
< SC_OPCODE_STOP_BIN_OP
&& eOp
!= ocAnd
&& eOp
!= ocOr
)
100 return 2; // binary operators, compiler checked; OR and AND legacy but are functions
101 else if ((SC_OPCODE_START_UN_OP
<= eOp
&& eOp
< SC_OPCODE_STOP_UN_OP
) || eOp
== ocPercentSign
)
102 return 1; // unary operators, compiler checked
103 else if (SC_OPCODE_START_NO_PAR
<= eOp
&& eOp
< SC_OPCODE_STOP_NO_PAR
)
104 return 0; // no parameter
105 else if (FormulaCompiler::IsOpCodeJumpCommand( eOp
))
106 return 1; // only the condition counts as parameter
108 return 0; // all the rest, no Parameter, or
109 // if so then it should be in cByte
112 bool FormulaToken::IsExternalRef() const
117 case svExternalSingleRef
:
118 case svExternalDoubleRef
:
129 bool FormulaToken::IsRef() const
135 case svExternalSingleRef
:
136 case svExternalDoubleRef
:
139 if (eOp
== ocTableRef
)
146 bool FormulaToken::IsInForceArray() const
148 ParamClass eParam
= GetInForceArray();
149 return eParam
== ParamClass::ForceArray
|| eParam
== ParamClass::ReferenceOrForceArray
150 || eParam
== ParamClass::ReferenceOrRefArray
|| eParam
== ParamClass::ForceArrayReturn
;
153 bool FormulaToken::operator==( const FormulaToken
& rToken
) const
155 // don't compare reference count!
156 return eType
== rToken
.eType
&& GetOpCode() == rToken
.GetOpCode();
160 // --- virtual dummy methods -------------------------------------------------
162 sal_uInt8
FormulaToken::GetByte() const
164 // ok to be called for any derived class
168 void FormulaToken::SetByte( sal_uInt8
)
170 assert( !"virtual dummy called" );
173 ParamClass
FormulaToken::GetInForceArray() const
175 // ok to be called for any derived class
176 return (eOp
== ocPush
&& eType
== svMatrix
) ? ParamClass::ForceArrayReturn
: ParamClass::Unknown
;
179 void FormulaToken::SetInForceArray( ParamClass
)
181 assert( !"virtual dummy called" );
184 double FormulaToken::GetDouble() const
186 // This Get is worth an assert.
187 assert( !"virtual dummy called" );
191 void FormulaToken::SetDouble(double)
193 // This Get is worth an assert.
194 assert( !"virtual dummy called" );
197 sal_Int16
FormulaToken::GetDoubleType() const
199 SAL_WARN( "formula.core", "FormulaToken::GetDoubleType: virtual dummy called" );
203 void FormulaToken::SetDoubleType( sal_Int16
)
205 assert( !"virtual dummy called" );
208 const svl::SharedString INVALID_STRING
;
210 const svl::SharedString
& FormulaToken::GetString() const
212 SAL_WARN( "formula.core", "FormulaToken::GetString: virtual dummy called" );
213 return INVALID_STRING
; // invalid string
216 void FormulaToken::SetString( const svl::SharedString
& )
218 assert( !"virtual dummy called" );
221 sal_uInt16
FormulaToken::GetIndex() const
223 SAL_WARN( "formula.core", "FormulaToken::GetIndex: virtual dummy called" );
227 void FormulaToken::SetIndex( sal_uInt16
)
229 assert( !"virtual dummy called" );
232 sal_Int16
FormulaToken::GetSheet() const
234 SAL_WARN( "formula.core", "FormulaToken::GetSheet: virtual dummy called" );
238 void FormulaToken::SetSheet( sal_Int16
)
240 assert( !"virtual dummy called" );
243 sal_Unicode
FormulaToken::GetChar() const
245 // This Get is worth an assert.
246 assert( !"virtual dummy called" );
250 short* FormulaToken::GetJump() const
252 SAL_WARN( "formula.core", "FormulaToken::GetJump: virtual dummy called" );
257 const OUString
& FormulaToken::GetExternal() const
259 SAL_WARN( "formula.core", "FormulaToken::GetExternal: virtual dummy called" );
260 static OUString aDummyString
;
264 FormulaToken
* FormulaToken::GetFAPOrigToken() const
266 SAL_WARN( "formula.core", "FormulaToken::GetFAPOrigToken: virtual dummy called" );
270 FormulaError
FormulaToken::GetError() const
272 SAL_WARN( "formula.core", "FormulaToken::GetError: virtual dummy called" );
273 return FormulaError::NONE
;
276 void FormulaToken::SetError( FormulaError
)
278 assert( !"virtual dummy called" );
281 const ScSingleRefData
* FormulaToken::GetSingleRef() const
283 OSL_FAIL( "FormulaToken::GetSingleRef: virtual dummy called" );
287 ScSingleRefData
* FormulaToken::GetSingleRef()
289 OSL_FAIL( "FormulaToken::GetSingleRef: virtual dummy called" );
293 const ScComplexRefData
* FormulaToken::GetDoubleRef() const
295 OSL_FAIL( "FormulaToken::GetDoubleRef: virtual dummy called" );
299 ScComplexRefData
* FormulaToken::GetDoubleRef()
301 OSL_FAIL( "FormulaToken::GetDoubleRef: virtual dummy called" );
305 const ScSingleRefData
* FormulaToken::GetSingleRef2() const
307 OSL_FAIL( "FormulaToken::GetSingleRef2: virtual dummy called" );
311 ScSingleRefData
* FormulaToken::GetSingleRef2()
313 OSL_FAIL( "FormulaToken::GetSingleRef2: virtual dummy called" );
317 const ScMatrix
* FormulaToken::GetMatrix() const
319 OSL_FAIL( "FormulaToken::GetMatrix: virtual dummy called" );
323 ScMatrix
* FormulaToken::GetMatrix()
325 OSL_FAIL( "FormulaToken::GetMatrix: virtual dummy called" );
329 ScJumpMatrix
* FormulaToken::GetJumpMatrix() const
331 OSL_FAIL( "FormulaToken::GetJumpMatrix: virtual dummy called" );
334 const std::vector
<ScComplexRefData
>* FormulaToken::GetRefList() const
336 OSL_FAIL( "FormulaToken::GetRefList: virtual dummy called" );
340 std::vector
<ScComplexRefData
>* FormulaToken::GetRefList()
342 OSL_FAIL( "FormulaToken::GetRefList: virtual dummy called" );
346 bool FormulaToken::TextEqual( const FormulaToken
& rToken
) const
348 return *this == rToken
;
351 // real implementations of virtual functions
354 sal_uInt8
FormulaSpaceToken::GetByte() const { return nByte
; }
355 sal_Unicode
FormulaSpaceToken::GetChar() const { return cChar
; }
356 bool FormulaSpaceToken::operator==( const FormulaToken
& r
) const
358 return FormulaToken::operator==( r
) && nByte
== r
.GetByte() &&
359 cChar
== r
.GetChar();
363 sal_uInt8
FormulaByteToken::GetByte() const { return nByte
; }
364 void FormulaByteToken::SetByte( sal_uInt8 n
) { nByte
= n
; }
365 ParamClass
FormulaByteToken::GetInForceArray() const { return eInForceArray
; }
366 void FormulaByteToken::SetInForceArray( ParamClass c
) { eInForceArray
= c
; }
367 bool FormulaByteToken::operator==( const FormulaToken
& r
) const
369 return FormulaToken::operator==( r
) && nByte
== r
.GetByte() &&
370 eInForceArray
== r
.GetInForceArray();
374 FormulaToken
* FormulaFAPToken::GetFAPOrigToken() const { return pOrigToken
.get(); }
375 bool FormulaFAPToken::operator==( const FormulaToken
& r
) const
377 return FormulaByteToken::operator==( r
) && pOrigToken
== r
.GetFAPOrigToken();
381 short* FormulaJumpToken::GetJump() const { return pJump
.get(); }
382 ParamClass
FormulaJumpToken::GetInForceArray() const { return eInForceArray
; }
383 void FormulaJumpToken::SetInForceArray( ParamClass c
) { eInForceArray
= c
; }
384 bool FormulaJumpToken::operator==( const FormulaToken
& r
) const
386 return FormulaToken::operator==( r
) && pJump
[0] == r
.GetJump()[0] &&
387 memcmp( pJump
.get()+1, r
.GetJump()+1, pJump
[0] * sizeof(short) ) == 0 &&
388 eInForceArray
== r
.GetInForceArray();
390 FormulaJumpToken::~FormulaJumpToken()
395 bool FormulaTokenArray::AddFormulaToken(
396 const sheet::FormulaToken
& rToken
, svl::SharedStringPool
& rSPool
, ExternalReferenceHelper
* /*pExtRef*/)
399 const OpCode eOpCode
= static_cast<OpCode
>(rToken
.OpCode
); //! assuming equal values for the moment
401 const uno::TypeClass eClass
= rToken
.Data
.getValueTypeClass();
404 case uno::TypeClass_VOID
:
405 // empty data -> use AddOpCode (does some special cases)
406 AddOpCode( eOpCode
);
408 case uno::TypeClass_DOUBLE
:
409 // double is only used for "push"
410 if ( eOpCode
== ocPush
)
411 AddDouble( rToken
.Data
.get
<double>() );
415 case uno::TypeClass_LONG
:
417 // long is svIndex, used for name / database area, or "byte" for spaces
418 sal_Int32 nValue
= rToken
.Data
.get
<sal_Int32
>();
419 if ( eOpCode
== ocDBArea
)
420 Add( new formula::FormulaIndexToken( eOpCode
, static_cast<sal_uInt16
>(nValue
) ) );
421 else if ( eOpCode
== ocSpaces
)
422 Add( new formula::FormulaByteToken( ocSpaces
, static_cast<sal_uInt8
>(nValue
) ) );
427 case uno::TypeClass_STRING
:
429 OUString
aStrVal( rToken
.Data
.get
<OUString
>() );
430 if ( eOpCode
== ocPush
)
431 AddString(rSPool
.intern(aStrVal
));
432 else if ( eOpCode
== ocBad
)
434 else if ( eOpCode
== ocStringXML
)
435 AddStringXML( aStrVal
);
436 else if ( eOpCode
== ocStringName
)
437 AddStringName( aStrVal
);
438 else if ( eOpCode
== ocExternal
|| eOpCode
== ocMacro
)
439 Add( new formula::FormulaExternalToken( eOpCode
, aStrVal
) );
440 else if ( eOpCode
== ocWhitespace
)
442 // Simply ignore empty string.
443 // Convention is one character repeated.
444 if (!aStrVal
.isEmpty())
445 Add( new formula::FormulaSpaceToken( static_cast<sal_uInt8
>(aStrVal
.getLength()), aStrVal
[0]));
448 bError
= true; // unexpected string: don't know what to do with it
453 } // switch ( eClass )
457 bool FormulaTokenArray::Fill(
458 const uno::Sequence
<sheet::FormulaToken
>& rSequence
,
459 svl::SharedStringPool
& rSPool
, ExternalReferenceHelper
* pExtRef
)
462 const sal_Int32 nCount
= rSequence
.getLength();
463 for (sal_Int32 nPos
=0; nPos
<nCount
; nPos
++)
465 bool bOneError
= AddFormulaToken(rSequence
[nPos
], rSPool
, pExtRef
);
468 AddOpCode( ocErrName
); // add something that indicates an error
475 void FormulaTokenArray::DelRPN()
479 FormulaToken
** p
= pRPN
;
480 for( sal_uInt16 i
= 0; i
< nRPN
; i
++ )
490 FormulaToken
* FormulaTokenArray::FirstToken() const
492 if (!pCode
|| nLen
== 0)
497 FormulaToken
* FormulaTokenArray::PeekPrev( sal_uInt16
& nIdx
) const
499 if (0 < nIdx
&& nIdx
<= nLen
)
500 return pCode
[--nIdx
];
504 FormulaToken
* FormulaTokenArray::FirstRPNToken() const
506 if (!pRPN
|| nRPN
== 0)
511 FormulaToken
* FormulaTokenArray::LastRPNToken() const
513 if (!pRPN
|| nRPN
== 0)
515 return pRPN
[nRPN
- 1];
518 bool FormulaTokenArray::HasReferences() const
520 for (auto i
: Tokens())
526 for (auto i
: RPNTokens())
535 bool FormulaTokenArray::HasExternalRef() const
537 for (auto i
: Tokens())
539 if (i
->IsExternalRef())
545 bool FormulaTokenArray::HasOpCode( OpCode eOp
) const
547 for (auto i
: Tokens())
549 if (i
->GetOpCode() == eOp
)
555 bool FormulaTokenArray::HasOpCodeRPN( OpCode eOp
) const
557 for (auto i
: RPNTokens())
559 if (i
->GetOpCode() == eOp
)
565 bool FormulaTokenArray::HasNameOrColRowName() const
567 for (auto i
: Tokens())
569 if (i
->GetType() == svIndex
|| i
->GetOpCode() == ocColRowName
)
575 bool FormulaTokenArray::HasOpCodes(const unordered_opcode_set
& rOpCodes
) const
577 for (auto i
: Tokens())
579 if (rOpCodes
.count(i
->GetOpCode()) > 0)
586 FormulaTokenArray::FormulaTokenArray() :
590 nError(FormulaError::NONE
),
591 nMode(ScRecalcMode::NORMAL
),
593 mbFromRangeName(false),
599 FormulaTokenArray::FormulaTokenArray( const FormulaTokenArray
& rArr
)
604 FormulaTokenArray::FormulaTokenArray( FormulaTokenArray
&& rArr
)
606 Move( std::move(rArr
) );
609 FormulaTokenArray::~FormulaTokenArray()
611 FormulaTokenArray::Clear();
614 void FormulaTokenArray::Finalize()
616 if( nLen
&& !mbFinalized
)
618 // Add() overallocates, so reallocate to the minimum needed size.
619 std::unique_ptr
<FormulaToken
*[]> newCode(new FormulaToken
*[ nLen
]);
620 std::copy(&pCode
[0], &pCode
[nLen
], newCode
.get());
621 pCode
= std::move( newCode
);
626 void FormulaTokenArray::Assign( const FormulaTokenArray
& r
)
632 bHyperLink
= r
.bHyperLink
;
633 mbFromRangeName
= r
.mbFromRangeName
;
634 mbShareable
= r
.mbShareable
;
635 mbFinalized
= r
.mbFinalized
;
641 pCode
.reset(new FormulaToken
*[ nLen
]);
643 memcpy( pp
, r
.pCode
.get(), nLen
* sizeof( FormulaToken
* ) );
644 for( sal_uInt16 i
= 0; i
< nLen
; i
++ )
650 pp
= pRPN
= new FormulaToken
*[ nRPN
];
651 memcpy( pp
, r
.pRPN
, nRPN
* sizeof( FormulaToken
* ) );
652 for( sal_uInt16 i
= 0; i
< nRPN
; i
++ )
657 void FormulaTokenArray::Move( FormulaTokenArray
&& r
)
659 pCode
= std::move(r
.pCode
);
668 bHyperLink
= r
.bHyperLink
;
669 mbFromRangeName
= r
.mbFromRangeName
;
670 mbShareable
= r
.mbShareable
;
671 mbFinalized
= r
.mbFinalized
;
674 /// Optimisation for efficiently creating StringXML placeholders
675 void FormulaTokenArray::Assign( sal_uInt16 nCode
, FormulaToken
**pTokens
)
678 assert( pCode
== nullptr );
681 pCode
.reset(new FormulaToken
*[ nLen
]);
684 for( sal_uInt16 i
= 0; i
< nLen
; i
++ )
686 FormulaToken
*t
= pTokens
[ i
];
687 assert( t
->GetOpCode() == ocStringXML
);
693 FormulaTokenArray
& FormulaTokenArray::operator=( const FormulaTokenArray
& rArr
)
703 FormulaTokenArray
& FormulaTokenArray::operator=( FormulaTokenArray
&& rArr
)
706 Move( std::move(rArr
) );
710 void FormulaTokenArray::Clear()
715 FormulaToken
** p
= pCode
.get();
716 for( sal_uInt16 i
= 0; i
< nLen
; i
++ )
723 nError
= FormulaError::NONE
;
726 mbFromRangeName
= false;
732 void FormulaTokenArray::CheckToken( const FormulaToken
& /*r*/ )
737 void FormulaTokenArray::CheckAllRPNTokens()
741 FormulaToken
** p
= pRPN
;
742 for( sal_uInt16 i
= 0; i
< nRPN
; i
++ )
744 CheckToken( *p
[ i
] );
749 FormulaToken
* FormulaTokenArray::AddToken( const FormulaToken
& r
)
751 return Add( r
.Clone() );
754 FormulaToken
* FormulaTokenArray::MergeArray( )
759 FormulaToken
* FormulaTokenArray::ReplaceToken( sal_uInt16 nOffset
, FormulaToken
* t
,
760 FormulaTokenArray::ReplaceMode eMode
)
766 FormulaToken
* p
= pCode
[nOffset
];
768 if (eMode
== CODE_AND_RPN
&& p
->GetRef() > 1)
770 for (sal_uInt16 i
=0; i
< nRPN
; ++i
)
777 if (p
->GetRef() == 1)
782 p
->DecRef(); // may be dead now
787 t
->DeleteIfZeroRef();
792 sal_uInt16
FormulaTokenArray::RemoveToken( sal_uInt16 nOffset
, sal_uInt16 nCount
)
796 SAL_WARN_IF( nOffset
+ nCount
> nLen
, "formula.core",
797 "FormulaTokenArray::RemoveToken - nOffset " << nOffset
<< " + nCount " << nCount
<< " > nLen " << nLen
);
798 const sal_uInt16 nStop
= ::std::min( static_cast<sal_uInt16
>(nOffset
+ nCount
), nLen
);
799 nCount
= nStop
- nOffset
;
800 for (sal_uInt16 j
= nOffset
; j
< nStop
; ++j
)
802 FormulaToken
* p
= pCode
[j
];
805 for (sal_uInt16 i
=0; i
< nRPN
; ++i
)
809 // Shift remaining tokens in pRPN down.
810 for (sal_uInt16 x
=i
+1; x
< nRPN
; ++x
)
817 if (p
->GetRef() == 1)
822 p
->DecRef(); // may be dead now
825 // Shift remaining tokens in pCode down.
826 for (sal_uInt16 x
= nStop
; x
< nLen
; ++x
)
828 pCode
[x
-nCount
] = pCode
[x
];
836 SAL_WARN("formula.core","FormulaTokenArray::RemoveToken - nOffset " << nOffset
<< " >= nLen " << nLen
);
841 FormulaToken
* FormulaTokenArray::Add( FormulaToken
* t
)
843 assert(!mbFinalized
);
846 t
->DeleteIfZeroRef();
850 // Allocating an array of size FORMULA_MAXTOKENS is simple, but that results in relatively large
851 // allocations that malloc() implementations usually do not handle as efficiently as smaller
852 // sizes (not only in terms of memory usage but also speed). Since most token arrays are going
853 // to be small, start with a small array and resize only if needed. Eventually Finalize() will
854 // reallocate the memory to size exactly matching the requirements.
855 const size_t MAX_FAST_TOKENS
= 32;
857 pCode
.reset(new FormulaToken
*[ MAX_FAST_TOKENS
]);
858 if( nLen
== MAX_FAST_TOKENS
)
860 FormulaToken
** tmp
= new FormulaToken
*[ FORMULA_MAXTOKENS
];
861 std::copy(&pCode
[0], &pCode
[MAX_FAST_TOKENS
], tmp
);
864 if( nLen
< FORMULA_MAXTOKENS
- 1 )
869 if( t
->GetOpCode() == ocArrayClose
)
875 t
->DeleteIfZeroRef();
876 if ( nLen
== FORMULA_MAXTOKENS
- 1 )
878 t
= new FormulaByteToken( ocStop
);
886 FormulaToken
* FormulaTokenArray::AddString( const svl::SharedString
& rStr
)
888 return Add( new FormulaStringToken( rStr
) );
891 FormulaToken
* FormulaTokenArray::AddDouble( double fVal
)
893 return Add( new FormulaDoubleToken( fVal
) );
896 void FormulaTokenArray::AddExternal( const sal_Unicode
* pStr
)
898 AddExternal( OUString( pStr
) );
901 FormulaToken
* FormulaTokenArray::AddExternal( const OUString
& rStr
,
902 OpCode eOp
/* = ocExternal */ )
904 return Add( new FormulaExternalToken( eOp
, rStr
) );
907 FormulaToken
* FormulaTokenArray::AddBad( const OUString
& rStr
)
909 return Add( new FormulaStringOpToken( ocBad
, svl::SharedString( rStr
) ) ); // string not interned
912 FormulaToken
* FormulaTokenArray::AddStringXML( const OUString
& rStr
)
914 return Add( new FormulaStringOpToken( ocStringXML
, svl::SharedString( rStr
) ) ); // string not interned
917 FormulaToken
* FormulaTokenArray::AddStringName( const OUString
& rStr
)
919 return Add( new FormulaStringOpToken( ocStringName
, svl::SharedString( rStr
) ) ); // string not interned
922 void FormulaTokenArray::AddRecalcMode( ScRecalcMode nBits
)
924 const unsigned nExclusive
= static_cast<sal_uInt8
>(nBits
& ScRecalcMode::EMask
);
928 if (nExclusive
& (nExclusive
- 1))
930 // More than one bit set, use highest priority.
931 for (nExBit
= 1; (nExBit
& static_cast<sal_uInt8
>(ScRecalcMode::EMask
)) != 0; nExBit
<<= 1)
933 if (nExclusive
& nExBit
)
939 // Only one bit is set.
942 // Set exclusive bit if priority is higher than existing.
943 if (nExBit
< static_cast<sal_uInt8
>(nMode
& ScRecalcMode::EMask
))
944 SetMaskedRecalcMode( static_cast<ScRecalcMode
>(nExBit
));
946 SetCombinedBitsRecalcMode( nBits
);
950 bool FormulaTokenArray::HasMatrixDoubleRefOps() const
952 if ( !pRPN
|| !nRPN
)
955 // RPN-Interpreter simulation.
956 // Simply assumes a double as return value of each function.
957 std::unique_ptr
<FormulaToken
*[]> pStack(new FormulaToken
* [nRPN
]);
958 FormulaToken
* pResult
= new FormulaDoubleToken( 0.0 );
960 for ( auto t
: RPNTokens() )
962 OpCode eOp
= t
->GetOpCode();
963 sal_uInt8 nParams
= t
->GetParamCount();
978 case ocGreaterEqual
:
980 for ( sal_uInt8 k
= nParams
; k
; k
-- )
982 if ( sp
>= k
&& pStack
[sp
-k
]->GetType() == svDoubleRef
)
992 // added to avoid warnings
995 if ( eOp
== ocPush
|| lcl_IsReference( eOp
, t
->GetType() ) )
997 else if (FormulaCompiler::IsOpCodeJumpCommand( eOp
))
998 { // ignore Jumps, pop previous Result (Condition)
1003 { // pop parameters, push result
1004 sp
= sal::static_int_cast
<short>( sp
- nParams
);
1007 SAL_WARN("formula.core", "FormulaTokenArray::HasMatrixDoubleRefOps: sp < 0" );
1010 pStack
[sp
++] = pResult
;
1018 // --- Formula rewrite of a token array
1020 inline bool MissingConventionODF::isRewriteNeeded( OpCode eOp
) const
1033 return isPODF(); // rewrite only for PODF
1036 return isODFF(); // rewrite only for ODFF
1044 To be implemented yet:
1049 inline bool MissingConventionOOXML::isRewriteNeeded( OpCode eOp
)
1087 class FormulaMissingContext
1090 const FormulaToken
* mpFunc
;
1093 void Clear() { mpFunc
= nullptr; mnCurArg
= 0; }
1094 inline bool AddDefaultArg( FormulaTokenArray
* pNewArr
, int nArg
, double f
) const;
1095 bool AddMissingExternal( FormulaTokenArray
* pNewArr
) const;
1096 bool AddMissing( FormulaTokenArray
*pNewArr
, const MissingConvention
& rConv
) const;
1097 void AddMoreArgs( FormulaTokenArray
*pNewArr
, const MissingConvention
& rConv
) const;
1102 void FormulaMissingContext::AddMoreArgs( FormulaTokenArray
*pNewArr
, const MissingConvention
& rConv
) const
1107 switch (rConv
.getConvention())
1109 case MissingConvention::FORMULA_MISSING_CONVENTION_ODFF
:
1110 case MissingConvention::FORMULA_MISSING_CONVENTION_PODF
:
1112 switch (mpFunc
->GetOpCode())
1117 pNewArr
->AddOpCode( ocSep
);
1118 pNewArr
->AddDouble( 1.0 ); // 4th, Cumulative=true()
1124 pNewArr
->AddOpCode( ocSep
);
1125 pNewArr
->AddDouble( 1.0 ); // 3rd, Cumulative=true()
1129 if ( mnCurArg
== 2 )
1131 pNewArr
->AddOpCode( ocSep
);
1132 pNewArr
->AddDouble( 1.0 ); // 4th, Cumulative=true()
1137 if ( mnCurArg
== 0 )
1139 pNewArr
->AddOpCode( ocSep
);
1140 pNewArr
->AddDouble( 0.0 ); // 2nd, mean = 0.0
1142 if ( mnCurArg
<= 1 )
1144 pNewArr
->AddOpCode( ocSep
);
1145 pNewArr
->AddDouble( 1.0 ); // 3rd, standard deviation = 1.0
1149 if ( rConv
.isPODF() && mnCurArg
== 0 )
1151 pNewArr
->AddOpCode( ocSep
);
1152 pNewArr
->AddDouble( 10.0 ); // 2nd, basis 10
1160 case MissingConvention::FORMULA_MISSING_CONVENTION_OOXML
:
1162 switch (mpFunc
->GetOpCode())
1167 // Excel needs at least two parameters in IF function
1168 pNewArr
->AddOpCode( ocSep
);
1169 pNewArr
->AddOpCode( ocTrue
); // 2nd, true() as function
1170 pNewArr
->AddOpCode( ocOpen
); // so the result is of logical type
1171 pNewArr
->AddOpCode( ocClose
); // and survives roundtrip
1176 if ( mnCurArg
== 2 )
1178 pNewArr
->AddOpCode( ocSep
);
1179 pNewArr
->AddDouble( 0.0 ); // 4th, FullPrecision = false()
1186 pNewArr
->AddOpCode( ocSep
);
1187 pNewArr
->AddDouble( 1.0 ); // 3rd, Cumulative=true()
1196 pNewArr
->AddOpCode( ocSep
);
1197 pNewArr
->AddDouble( 1.0 ); // 4th, Cumulative=true()
1203 if ( mnCurArg
== 0 )
1205 pNewArr
->AddOpCode( ocSep
);
1206 pNewArr
->AddDouble( 0.0 ); // 2nd, mean = 0.0
1208 if ( mnCurArg
<= 1 )
1210 pNewArr
->AddOpCode( ocSep
);
1211 pNewArr
->AddDouble( 1.0 ); // 3rd, standard deviation = 1.0
1216 if ( mnCurArg
== 3 )
1218 pNewArr
->AddOpCode( ocSep
);
1219 pNewArr
->AddDouble( 0.0 ); // 5th, Cumulative = false()
1228 // ROUND, ROUNDUP, ROUNDDOWN functions are fixed to 2 parameters in Excel
1229 pNewArr
->AddOpCode( ocSep
);
1230 pNewArr
->AddDouble( 0.0 ); // 2nd, 0.0
1243 inline bool FormulaMissingContext::AddDefaultArg( FormulaTokenArray
* pNewArr
, int nArg
, double f
) const
1245 if (mnCurArg
== nArg
)
1247 pNewArr
->AddDouble( f
);
1253 bool FormulaMissingContext::AddMissingExternal( FormulaTokenArray
*pNewArr
) const
1255 // Only called for PODF, not ODFF. No need to distinguish.
1257 const OUString
&rName
= mpFunc
->GetExternal();
1259 // initial (fast) checks:
1260 sal_Int32 nLength
= rName
.getLength();
1264 sal_Unicode nLastChar
= rName
[ nLength
- 1];
1265 if ( nLastChar
!= 't' && nLastChar
!= 'm' )
1268 if (rName
.equalsIgnoreAsciiCase(
1269 "com.sun.star.sheet.addin.Analysis.getAccrint" ))
1271 return AddDefaultArg( pNewArr
, 4, 1000.0 );
1273 if (rName
.equalsIgnoreAsciiCase(
1274 "com.sun.star.sheet.addin.Analysis.getAccrintm" ))
1276 return AddDefaultArg( pNewArr
, 3, 1000.0 );
1281 bool FormulaMissingContext::AddMissing( FormulaTokenArray
*pNewArr
, const MissingConvention
& rConv
) const
1287 const OpCode eOp
= mpFunc
->GetOpCode();
1289 switch (rConv
.getConvention())
1291 case MissingConvention::FORMULA_MISSING_CONVENTION_ODFF
:
1297 return AddDefaultArg( pNewArr
, 2, 1.0 ); // abs
1303 case MissingConvention::FORMULA_MISSING_CONVENTION_PODF
:
1309 return AddDefaultArg( pNewArr
, 2, 1.0 ); // abs
1311 return AddDefaultArg( pNewArr
, 1, 2.0 );
1315 return AddDefaultArg( pNewArr
, 3, 0.0 );
1318 return AddDefaultArg( pNewArr
, 4, 0.0 );
1321 bRet
|= AddDefaultArg( pNewArr
, 2, 0.0 ); // pmt
1322 bRet
|= AddDefaultArg( pNewArr
, 3, 0.0 ); // [fp]v
1325 bRet
|= AddDefaultArg( pNewArr
, 1, 0.0 ); // pmt
1326 bRet
|= AddDefaultArg( pNewArr
, 3, 0.0 ); // fv
1327 bRet
|= AddDefaultArg( pNewArr
, 4, 0.0 ); // type
1330 return AddMissingExternal( pNewArr
);
1332 // --- more complex cases ---
1335 // FIXME: rather tough
1336 // if arg 3 (height) omitted, export arg1 (rows)
1343 case MissingConvention::FORMULA_MISSING_CONVENTION_OOXML
:
1348 return AddMissingExternal( pNewArr
);
1359 bool FormulaTokenArray::NeedsPodfRewrite( const MissingConventionODF
& rConv
)
1361 for ( auto i
: Tokens() )
1363 if ( rConv
.isRewriteNeeded( i
->GetOpCode()))
1369 bool FormulaTokenArray::NeedsOoxmlRewrite()
1371 for ( auto i
: Tokens() )
1373 if ( MissingConventionOOXML::isRewriteNeeded( i
->GetOpCode()))
1380 FormulaTokenArray
* FormulaTokenArray::RewriteMissing( const MissingConvention
& rConv
)
1382 const size_t nAlloc
= 256;
1383 FormulaMissingContext aCtx
[ nAlloc
];
1385 /* TODO: with some effort we might be able to merge the two almost
1386 * identical function stacks into one and generalize things, otherwise
1387 * adding yet another "omit argument" would be copypasta. */
1389 int aOpCodeAddressStack
[ nAlloc
]; // use of ADDRESS() function
1390 const int nOmitAddressArg
= 3; // ADDRESS() 4th parameter A1/R1C1
1392 int aOpCodeDcountStack
[ nAlloc
]; // use of DCOUNT()/DCOUNTA() function
1393 const int nOmitDcountArg
= 1; // DCOUNT() and DCOUNTA() 2nd parameter DatabaseField if 0
1395 sal_uInt16 nTokens
= GetLen() + 1;
1396 FormulaMissingContext
* pCtx
= (nAlloc
< nTokens
? new FormulaMissingContext
[nTokens
] : &aCtx
[0]);
1397 int* pOcas
= (nAlloc
< nTokens
? new int[nTokens
] : &aOpCodeAddressStack
[0]);
1398 int* pOcds
= (nAlloc
< nTokens
? new int[nTokens
] : &aOpCodeDcountStack
[0]);
1399 // Never go below 0, never use 0, mpFunc always NULL.
1405 FormulaTokenArray
*pNewArr
= new FormulaTokenArray
;
1406 // At least ScRecalcMode::ALWAYS needs to be set.
1407 pNewArr
->AddRecalcMode( GetRecalcMode());
1409 FormulaTokenArrayPlainIterator
aIter(*this);
1410 for ( FormulaToken
*pCur
= aIter
.First(); pCur
; pCur
= aIter
.Next() )
1413 // Don't write the expression of the new inserted ADDRESS() parameter.
1414 // Do NOT omit the new second parameter of INDIRECT() though. If that
1415 // was done for both, INDIRECT() actually could calculate different and
1416 // valid (but wrong) results with the then changed return value of
1417 // ADDRESS(). Better let it generate an error instead.
1418 for (int i
= nOcas
; i
-- > 0 && bAdd
; )
1420 if (pCtx
[ pOcas
[ i
] ].mnCurArg
== nOmitAddressArg
)
1422 // Omit everything except a trailing separator, the leading
1423 // separator is omitted below. The other way around would leave
1424 // an extraneous separator if no parameter followed.
1425 if (pOcas
[ i
] != nFn
|| pCur
->GetOpCode() != ocSep
)
1429 // Strip the 2nd argument (leaving empty) of DCOUNT() and DCOUNTA() if
1431 for (int i
= nOcds
; i
-- > 0 && bAdd
; )
1433 if (pCtx
[ pOcds
[ i
] ].mnCurArg
== nOmitDcountArg
)
1435 // Omit only a literal 0 value, nothing else.
1436 if (pOcds
[ i
] == nFn
&& pCur
->GetOpCode() == ocPush
&& pCur
->GetType() == svDouble
&&
1437 pCur
->GetDouble() == 0.0)
1439 // No other expression, between separators.
1440 FormulaToken
* p
= aIter
.PeekPrevNoSpaces();
1441 if (p
&& p
->GetOpCode() == ocSep
)
1443 p
= aIter
.PeekNextNoSpaces();
1444 if (p
&& p
->GetOpCode() == ocSep
)
1450 switch ( pCur
->GetOpCode() )
1454 ++nFn
; // all following operations on _that_ function
1455 pCtx
[ nFn
].mpFunc
= aIter
.PeekPrevNoSpaces();
1456 pCtx
[ nFn
].mnCurArg
= 0;
1457 if (rConv
.isPODF() && pCtx
[ nFn
].mpFunc
&& pCtx
[ nFn
].mpFunc
->GetOpCode() == ocAddress
)
1458 pOcas
[ nOcas
++ ] = nFn
; // entering ADDRESS() if PODF
1459 else if ((rConv
.isODFF() || rConv
.isOOXML()) && pCtx
[ nFn
].mpFunc
)
1461 OpCode eOp
= pCtx
[ nFn
].mpFunc
->GetOpCode();
1462 if (eOp
== ocDBCount
|| eOp
== ocDBCount2
)
1463 pOcds
[ nOcds
++ ] = nFn
; // entering DCOUNT() or DCOUNTA() if ODFF or OOXML
1468 pCtx
[ nFn
].AddMoreArgs( pNewArr
, rConv
);
1469 SAL_WARN_IF(nFn
<= 0, "formula.core", "FormulaTokenArray::RewriteMissing: underflow");
1470 if (nOcas
> 0 && pOcas
[ nOcas
-1 ] == nFn
)
1471 --nOcas
; // leaving ADDRESS()
1472 else if (nOcds
> 0 && pOcds
[ nOcds
-1 ] == nFn
)
1473 --nOcds
; // leaving DCOUNT() or DCOUNTA()
1478 pCtx
[ nFn
].mnCurArg
++;
1479 // Omit leading separator of ADDRESS() parameter.
1480 if (nOcas
&& pOcas
[ nOcas
-1 ] == nFn
&& pCtx
[ nFn
].mnCurArg
== nOmitAddressArg
)
1487 bAdd
= !pCtx
[ nFn
].AddMissing( pNewArr
, rConv
);
1494 OpCode eOp
= pCur
->GetOpCode();
1495 if ( ( eOp
== ocCeil
|| eOp
== ocFloor
||
1496 ( eOp
== ocLogNormDist
&& pCur
->GetByte() == 4 ) ) &&
1497 rConv
.getConvention() == MissingConvention::FORMULA_MISSING_CONVENTION_OOXML
)
1507 case ocLogNormDist
:
1508 eOp
= ocLogNormDist_MS
;
1514 FormulaToken
*pToken
= new FormulaToken( svByte
, eOp
);
1515 pNewArr
->Add( pToken
);
1517 else if ( eOp
== ocHypGeomDist
&&
1518 rConv
.getConvention() == MissingConvention::FORMULA_MISSING_CONVENTION_OOXML
)
1520 FormulaToken
*pToken
= new FormulaToken( svByte
, ocHypGeomDist_MS
);
1521 pNewArr
->Add( pToken
);
1524 pNewArr
->AddToken( *pCur
);
1528 if (pOcds
!= &aOpCodeDcountStack
[0])
1530 if (pOcas
!= &aOpCodeAddressStack
[0])
1532 if (pCtx
!= &aCtx
[0])
1539 inline bool isWhitespace( OpCode eOp
) { return eOp
== ocSpaces
|| eOp
== ocWhitespace
; }
1542 bool FormulaTokenArray::MayReferenceFollow()
1544 if ( !pCode
|| nLen
<= 0 )
1547 // ignore trailing spaces
1548 sal_uInt16 i
= nLen
- 1;
1549 while (i
> 0 && isWhitespace( pCode
[i
]->GetOpCode()))
1553 if (i
> 0 || !isWhitespace( pCode
[i
]->GetOpCode()))
1555 OpCode eOp
= pCode
[i
]->GetOpCode();
1556 if ( (SC_OPCODE_START_BIN_OP
<= eOp
&& eOp
< SC_OPCODE_STOP_BIN_OP
) ||
1557 (SC_OPCODE_START_UN_OP
<= eOp
&& eOp
< SC_OPCODE_STOP_UN_OP
) ||
1558 eOp
== SC_OPCODE_OPEN
|| eOp
== SC_OPCODE_SEP
)
1565 FormulaToken
* FormulaTokenArray::AddOpCode( OpCode eOp
)
1567 FormulaToken
* pRet
= nullptr;
1577 pRet
= new FormulaToken( svSep
,eOp
);
1585 short nJump
[FORMULA_MAXPARAMS
+ 1];
1588 else if ( eOp
== ocChoose
)
1589 nJump
[ 0 ] = FORMULA_MAXJUMPCOUNT
+ 1;
1590 else if ( eOp
== ocLet
)
1591 nJump
[ 0 ] = FORMULA_MAXPARAMS
+ 1;
1594 pRet
= new FormulaJumpToken( eOp
, nJump
);
1598 pRet
= new FormulaByteToken( eOp
, 0, ParamClass::Unknown
);
1604 void FormulaTokenArray::ReinternStrings( svl::SharedStringPool
& rPool
)
1606 for (auto i
: Tokens())
1608 switch (i
->GetType())
1611 i
->SetString( rPool
.intern( i
->GetString().getString()));
1620 /*----------------------------------------------------------------------*/
1622 FormulaTokenIterator::Item::Item(const FormulaTokenArray
* pArray
, short pc
, short stop
) :
1623 pArr(pArray
), nPC(pc
), nStop(stop
)
1627 FormulaTokenIterator::FormulaTokenIterator( const FormulaTokenArray
& rArr
)
1628 : maStack
{ FormulaTokenIterator::Item(&rArr
, -1, SHRT_MAX
) }
1632 FormulaTokenIterator::~FormulaTokenIterator()
1636 void FormulaTokenIterator::Push( const FormulaTokenArray
* pArr
)
1638 FormulaTokenIterator::Item
item(pArr
, -1, SHRT_MAX
);
1640 maStack
.push_back(item
);
1643 void FormulaTokenIterator::Pop()
1648 void FormulaTokenIterator::Reset()
1650 while( maStack
.size() > 1 )
1653 maStack
.back().nPC
= -1;
1656 FormulaToken
* FormulaTokenArrayPlainIterator::GetNextName()
1658 if( mpFTA
->GetArray() )
1660 while ( mnIndex
< mpFTA
->GetLen() )
1662 FormulaToken
* t
= mpFTA
->GetArray()[ mnIndex
++ ];
1663 if( t
->GetType() == svIndex
)
1670 FormulaToken
* FormulaTokenArrayPlainIterator::GetNextStringName()
1672 if (mpFTA
->GetArray())
1674 while (mnIndex
< mpFTA
->GetLen())
1676 FormulaToken
* t
= mpFTA
->GetArray()[mnIndex
++];
1677 if (t
->GetType() == svString
&& t
->GetOpCode() == ocStringName
)
1684 const FormulaToken
* FormulaTokenIterator::Next()
1686 const FormulaToken
* t
= GetNonEndOfPathToken( ++maStack
.back().nPC
);
1687 if( !t
&& maStack
.size() > 1 )
1695 const FormulaToken
* FormulaTokenIterator::PeekNextOperator()
1697 const FormulaToken
* t
= nullptr;
1698 short nIdx
= maStack
.back().nPC
;
1701 t
= GetNonEndOfPathToken( ++nIdx
);
1702 if (t
== nullptr || t
->GetOpCode() != ocPush
)
1703 break; // ignore operands
1705 if (!t
&& maStack
.size() > 1)
1707 FormulaTokenIterator::Item aHere
= maStack
.back();
1709 t
= PeekNextOperator();
1710 maStack
.push_back(aHere
);
1715 //! The nPC counts after a Push() are -1
1717 void FormulaTokenIterator::Jump( short nStart
, short nNext
, short nStop
)
1719 maStack
.back().nPC
= nNext
;
1720 if( nStart
!= nNext
)
1722 Push( maStack
.back().pArr
);
1723 maStack
.back().nPC
= nStart
;
1724 maStack
.back().nStop
= nStop
;
1728 void FormulaTokenIterator::ReInit( const FormulaTokenArray
& rArr
)
1734 const FormulaToken
* FormulaTokenIterator::GetNonEndOfPathToken( short nIdx
) const
1736 FormulaTokenIterator::Item cur
= maStack
.back();
1738 if (nIdx
< cur
.pArr
->GetCodeLen() && nIdx
< cur
.nStop
)
1740 const FormulaToken
* t
= cur
.pArr
->GetCode()[ nIdx
];
1741 // such an OpCode ends an IF() or CHOOSE() path
1742 return (t
->GetOpCode() == ocSep
|| t
->GetOpCode() == ocClose
) ? nullptr : t
;
1747 bool FormulaTokenIterator::IsEndOfPath() const
1749 return GetNonEndOfPathToken( maStack
.back().nPC
+ 1) == nullptr;
1752 FormulaToken
* FormulaTokenArrayPlainIterator::GetNextReference()
1754 while( mnIndex
< mpFTA
->GetLen() )
1756 FormulaToken
* t
= mpFTA
->GetArray()[ mnIndex
++ ];
1757 switch( t
->GetType() )
1761 case svExternalSingleRef
:
1762 case svExternalDoubleRef
:
1766 // added to avoid warnings
1773 FormulaToken
* FormulaTokenArrayPlainIterator::GetNextColRowName()
1775 while( mnIndex
< mpFTA
->GetLen() )
1777 FormulaToken
* t
= mpFTA
->GetArray()[ mnIndex
++ ];
1778 if ( t
->GetOpCode() == ocColRowName
)
1784 FormulaToken
* FormulaTokenArrayPlainIterator::GetNextReferenceRPN()
1786 while( mnIndex
< mpFTA
->GetCodeLen() )
1788 FormulaToken
* t
= mpFTA
->GetCode()[ mnIndex
++ ];
1789 switch( t
->GetType() )
1793 case svExternalSingleRef
:
1794 case svExternalDoubleRef
:
1798 // added to avoid warnings
1805 FormulaToken
* FormulaTokenArrayPlainIterator::GetNextReferenceOrName()
1807 if( !mpFTA
->GetArray() )
1810 while ( mnIndex
< mpFTA
->GetLen() )
1812 FormulaToken
* t
= mpFTA
->GetArray()[ mnIndex
++ ];
1813 switch( t
->GetType() )
1818 case svExternalSingleRef
:
1819 case svExternalDoubleRef
:
1820 case svExternalName
:
1824 // added to avoid warnings
1831 FormulaToken
* FormulaTokenArrayPlainIterator::Next()
1833 if( mpFTA
->GetArray() && mnIndex
< mpFTA
->GetLen() )
1834 return mpFTA
->GetArray()[ mnIndex
++ ];
1839 FormulaToken
* FormulaTokenArrayPlainIterator::NextNoSpaces()
1841 if( mpFTA
->GetArray() )
1843 while ((mnIndex
< mpFTA
->GetLen()) && isWhitespace( mpFTA
->GetArray()[ mnIndex
]->GetOpCode()))
1845 if( mnIndex
< mpFTA
->GetLen() )
1846 return mpFTA
->GetArray()[ mnIndex
++ ];
1851 FormulaToken
* FormulaTokenArrayPlainIterator::NextRPN()
1853 if( mpFTA
->GetCode() && mnIndex
< mpFTA
->GetCodeLen() )
1854 return mpFTA
->GetCode()[ mnIndex
++ ];
1859 FormulaToken
* FormulaTokenArrayPlainIterator::PrevRPN()
1861 if( mpFTA
->GetCode() && mnIndex
)
1862 return mpFTA
->GetCode()[ --mnIndex
];
1867 FormulaToken
* FormulaTokenArrayPlainIterator::PeekNext()
1869 if( mpFTA
->GetArray() && mnIndex
< mpFTA
->GetLen() )
1870 return mpFTA
->GetArray()[ mnIndex
];
1875 FormulaToken
* FormulaTokenArrayPlainIterator::PeekNextNoSpaces() const
1877 if( mpFTA
->GetArray() && mnIndex
< mpFTA
->GetLen() )
1879 sal_uInt16 j
= mnIndex
;
1880 while (j
< mpFTA
->GetLen() && isWhitespace( mpFTA
->GetArray()[j
]->GetOpCode()))
1882 if ( j
< mpFTA
->GetLen() )
1883 return mpFTA
->GetArray()[ j
];
1891 FormulaToken
* FormulaTokenArrayPlainIterator::PeekPrevNoSpaces() const
1893 if( mpFTA
->GetArray() && mnIndex
> 1 )
1895 sal_uInt16 j
= mnIndex
- 2;
1896 while (isWhitespace( mpFTA
->GetArray()[j
]->GetOpCode()) && j
> 0 )
1898 if (j
> 0 || !isWhitespace( mpFTA
->GetArray()[j
]->GetOpCode()))
1899 return mpFTA
->GetArray()[ j
];
1907 void FormulaTokenArrayPlainIterator::AfterRemoveToken( sal_uInt16 nOffset
, sal_uInt16 nCount
)
1909 const sal_uInt16 nStop
= std::min( static_cast<sal_uInt16
>(nOffset
+ nCount
), mpFTA
->GetLen());
1911 if (mnIndex
>= nOffset
)
1913 if (mnIndex
< nStop
)
1914 mnIndex
= nOffset
+ 1;
1916 mnIndex
-= nStop
- nOffset
;
1920 // real implementations of virtual functions
1922 sal_Int16
FormulaDoubleToken::GetDoubleType() const
1924 // This is a plain double value without type information, don't emit a
1925 // warning via FormulaToken::GetDoubleType().
1929 bool FormulaDoubleToken::operator==( const FormulaToken
& r
) const
1931 return FormulaToken::operator==( r
) && fDouble
== r
.GetDouble();
1934 sal_Int16
FormulaTypedDoubleToken::GetDoubleType() const
1939 void FormulaTypedDoubleToken::SetDoubleType( sal_Int16 nType
)
1944 bool FormulaTypedDoubleToken::operator==( const FormulaToken
& r
) const
1946 return FormulaDoubleToken::operator==( r
) && mnType
== r
.GetDoubleType();
1949 FormulaStringToken::FormulaStringToken( svl::SharedString r
) :
1950 FormulaToken( svString
), maString(std::move( r
))
1954 FormulaStringToken::FormulaStringToken( const FormulaStringToken
& r
) :
1955 FormulaToken( r
), maString( r
.maString
) {}
1957 FormulaToken
* FormulaStringToken::Clone() const
1959 return new FormulaStringToken(*this);
1962 const svl::SharedString
& FormulaStringToken::GetString() const
1967 void FormulaStringToken::SetString( const svl::SharedString
& rStr
)
1972 bool FormulaStringToken::operator==( const FormulaToken
& r
) const
1974 return FormulaToken::operator==( r
) && maString
== r
.GetString();
1977 FormulaStringOpToken::FormulaStringOpToken( OpCode e
, svl::SharedString r
) :
1978 FormulaByteToken( e
, 0, svString
, ParamClass::Unknown
), maString(std::move( r
)) {}
1980 FormulaStringOpToken::FormulaStringOpToken( const FormulaStringOpToken
& r
) :
1981 FormulaByteToken( r
), maString( r
.maString
) {}
1983 FormulaToken
* FormulaStringOpToken::Clone() const
1985 return new FormulaStringOpToken(*this);
1988 const svl::SharedString
& FormulaStringOpToken::GetString() const
1993 void FormulaStringOpToken::SetString( const svl::SharedString
& rStr
)
1998 bool FormulaStringOpToken::operator==( const FormulaToken
& r
) const
2000 return FormulaByteToken::operator==( r
) && maString
== r
.GetString();
2003 sal_uInt16
FormulaIndexToken::GetIndex() const { return nIndex
; }
2004 void FormulaIndexToken::SetIndex( sal_uInt16 n
) { nIndex
= n
; }
2005 sal_Int16
FormulaIndexToken::GetSheet() const { return mnSheet
; }
2006 void FormulaIndexToken::SetSheet( sal_Int16 n
) { mnSheet
= n
; }
2007 bool FormulaIndexToken::operator==( const FormulaToken
& r
) const
2009 return FormulaToken::operator==( r
) && nIndex
== r
.GetIndex() &&
2010 mnSheet
== r
.GetSheet();
2012 const OUString
& FormulaExternalToken::GetExternal() const { return aExternal
; }
2013 bool FormulaExternalToken::operator==( const FormulaToken
& r
) const
2015 return FormulaByteToken::operator==( r
) && aExternal
== r
.GetExternal();
2019 FormulaError
FormulaErrorToken::GetError() const { return nError
; }
2020 void FormulaErrorToken::SetError( FormulaError nErr
) { nError
= nErr
; }
2021 bool FormulaErrorToken::operator==( const FormulaToken
& r
) const
2023 return FormulaToken::operator==( r
) &&
2024 nError
== static_cast< const FormulaErrorToken
& >(r
).GetError();
2026 double FormulaMissingToken::GetDouble() const { return 0.0; }
2028 const svl::SharedString
& FormulaMissingToken::GetString() const
2030 return svl::SharedString::getEmptyString();
2033 bool FormulaMissingToken::operator==( const FormulaToken
& r
) const
2035 return FormulaToken::operator==( r
);
2039 bool FormulaUnknownToken::operator==( const FormulaToken
& r
) const
2041 return FormulaToken::operator==( r
);
2048 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */