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>
39 using namespace com::sun::star
;
42 // --- helpers --------------------------------------------------------------
44 static bool lcl_IsReference( OpCode eOp
, StackVar eType
)
47 (eOp
== ocPush
&& (eType
== svSingleRef
|| eType
== svDoubleRef
))
48 || (eOp
== ocColRowNameAuto
&& eType
== svDoubleRef
)
49 || (eOp
== ocColRowName
&& eType
== svSingleRef
)
50 || (eOp
== ocMatRef
&& eType
== svSingleRef
)
54 // --- class FormulaToken --------------------------------------------------------
56 FormulaToken::FormulaToken( StackVar eTypeP
, OpCode e
) :
57 eOp(e
), eType( eTypeP
), mnRefCnt(0)
61 FormulaToken::FormulaToken( const FormulaToken
& r
) :
62 eOp(r
.eOp
), eType( r
.eType
), mnRefCnt(0)
66 FormulaToken::~FormulaToken()
70 bool FormulaToken::IsFunction() const
72 return (eOp
!= ocPush
&& eOp
!= ocBad
&& eOp
!= ocColRowName
&&
73 eOp
!= ocColRowNameAuto
&& eOp
!= ocName
&& eOp
!= ocDBArea
&&
75 (GetByte() != 0 // x parameters
76 || (SC_OPCODE_START_NO_PAR
<= eOp
&& eOp
< SC_OPCODE_STOP_NO_PAR
) // no parameter
77 || FormulaCompiler::IsOpCodeJumpCommand( eOp
) // @ jump commands
78 || (SC_OPCODE_START_1_PAR
<= eOp
&& eOp
< SC_OPCODE_STOP_1_PAR
) // one parameter
79 || (SC_OPCODE_START_2_PAR
<= eOp
&& eOp
< SC_OPCODE_STOP_2_PAR
) // x parameters (cByte==0 in
81 || eOp
== ocMacro
|| eOp
== ocExternal
// macros, AddIns
82 || eOp
== ocAnd
|| eOp
== ocOr
// former binary, now x parameters
83 || (eOp
>= ocInternalBegin
&& eOp
<= ocInternalEnd
) // internal
88 sal_uInt8
FormulaToken::GetParamCount() const
90 if ( eOp
< SC_OPCODE_STOP_DIV
&& eOp
!= ocExternal
&& eOp
!= ocMacro
&&
91 !FormulaCompiler::IsOpCodeJumpCommand( eOp
) &&
92 eOp
!= ocPercentSign
)
93 return 0; // parameters and specials
94 // ocIf... jump commands not for FAP, have cByte then
95 //2do: bool parameter whether FAP or not?
97 return GetByte(); // all functions, also ocExternal and ocMacro
98 else if (SC_OPCODE_START_BIN_OP
<= eOp
&& eOp
< SC_OPCODE_STOP_BIN_OP
)
100 else if ((SC_OPCODE_START_UN_OP
<= eOp
&& eOp
< SC_OPCODE_STOP_UN_OP
)
101 || eOp
== ocPercentSign
)
103 else if (SC_OPCODE_START_NO_PAR
<= eOp
&& eOp
< SC_OPCODE_STOP_NO_PAR
)
104 return 0; // no parameter
105 else if (SC_OPCODE_START_1_PAR
<= eOp
&& eOp
< SC_OPCODE_STOP_1_PAR
)
106 return 1; // one parameter
107 else if (FormulaCompiler::IsOpCodeJumpCommand( eOp
))
108 return 1; // only the condition counts as parameter
110 return 0; // all the rest, no Parameter, or
111 // if so then it should be in cByte
114 bool FormulaToken::IsExternalRef() const
119 case svExternalSingleRef
:
120 case svExternalDoubleRef
:
131 bool FormulaToken::IsRef() const
137 case svExternalSingleRef
:
138 case svExternalDoubleRef
:
141 if (eOp
== ocTableRef
)
148 bool FormulaToken::IsInForceArray() const
150 ParamClass eParam
= GetInForceArray();
151 return eParam
== ParamClass::ForceArray
|| eParam
== ParamClass::ReferenceOrForceArray
152 || eParam
== ParamClass::ReferenceOrRefArray
|| eParam
== ParamClass::ForceArrayReturn
;
155 bool FormulaToken::operator==( const FormulaToken
& rToken
) const
157 // don't compare reference count!
158 return eType
== rToken
.eType
&& GetOpCode() == rToken
.GetOpCode();
162 // --- virtual dummy methods -------------------------------------------------
164 sal_uInt8
FormulaToken::GetByte() const
166 // ok to be called for any derived class
170 void FormulaToken::SetByte( sal_uInt8
)
172 assert( !"virtual dummy called" );
175 ParamClass
FormulaToken::GetInForceArray() const
177 // ok to be called for any derived class
178 return ParamClass::Unknown
;
181 void FormulaToken::SetInForceArray( ParamClass
)
183 assert( !"virtual dummy called" );
186 double FormulaToken::GetDouble() const
188 // This Get is worth an assert.
189 assert( !"virtual dummy called" );
193 double & FormulaToken::GetDoubleAsReference()
195 // This Get is worth an assert.
196 assert( !"virtual dummy called" );
197 static double fVal
= 0.0;
201 sal_Int16
FormulaToken::GetDoubleType() const
203 SAL_WARN( "formula.core", "FormulaToken::GetDoubleType: virtual dummy called" );
207 void FormulaToken::SetDoubleType( sal_Int16
)
209 assert( !"virtual dummy called" );
212 const svl::SharedString INVALID_STRING
;
214 const svl::SharedString
& FormulaToken::GetString() const
216 SAL_WARN( "formula.core", "FormulaToken::GetString: virtual dummy called" );
217 return INVALID_STRING
; // invalid string
220 void FormulaToken::SetString( const svl::SharedString
& )
222 assert( !"virtual dummy called" );
225 sal_uInt16
FormulaToken::GetIndex() const
227 SAL_WARN( "formula.core", "FormulaToken::GetIndex: virtual dummy called" );
231 void FormulaToken::SetIndex( sal_uInt16
)
233 assert( !"virtual dummy called" );
236 sal_Int16
FormulaToken::GetSheet() const
238 SAL_WARN( "formula.core", "FormulaToken::GetSheet: virtual dummy called" );
242 void FormulaToken::SetSheet( sal_Int16
)
244 assert( !"virtual dummy called" );
247 short* FormulaToken::GetJump() const
249 SAL_WARN( "formula.core", "FormulaToken::GetJump: virtual dummy called" );
254 const OUString
& FormulaToken::GetExternal() const
256 SAL_WARN( "formula.core", "FormulaToken::GetExternal: virtual dummy called" );
257 static OUString aDummyString
;
261 FormulaToken
* FormulaToken::GetFAPOrigToken() const
263 SAL_WARN( "formula.core", "FormulaToken::GetFAPOrigToken: virtual dummy called" );
267 FormulaError
FormulaToken::GetError() const
269 SAL_WARN( "formula.core", "FormulaToken::GetError: virtual dummy called" );
270 return FormulaError::NONE
;
273 void FormulaToken::SetError( FormulaError
)
275 assert( !"virtual dummy called" );
278 const ScSingleRefData
* FormulaToken::GetSingleRef() const
280 OSL_FAIL( "FormulaToken::GetSingleRef: virtual dummy called" );
284 ScSingleRefData
* FormulaToken::GetSingleRef()
286 OSL_FAIL( "FormulaToken::GetSingleRef: virtual dummy called" );
290 const ScComplexRefData
* FormulaToken::GetDoubleRef() const
292 OSL_FAIL( "FormulaToken::GetDoubleRef: virtual dummy called" );
296 ScComplexRefData
* FormulaToken::GetDoubleRef()
298 OSL_FAIL( "FormulaToken::GetDoubleRef: virtual dummy called" );
302 const ScSingleRefData
* FormulaToken::GetSingleRef2() const
304 OSL_FAIL( "FormulaToken::GetSingleRef2: virtual dummy called" );
308 ScSingleRefData
* FormulaToken::GetSingleRef2()
310 OSL_FAIL( "FormulaToken::GetSingleRef2: virtual dummy called" );
314 const ScMatrix
* FormulaToken::GetMatrix() const
316 OSL_FAIL( "FormulaToken::GetMatrix: virtual dummy called" );
320 ScMatrix
* FormulaToken::GetMatrix()
322 OSL_FAIL( "FormulaToken::GetMatrix: virtual dummy called" );
326 ScJumpMatrix
* FormulaToken::GetJumpMatrix() const
328 OSL_FAIL( "FormulaToken::GetJumpMatrix: virtual dummy called" );
331 const std::vector
<ScComplexRefData
>* FormulaToken::GetRefList() const
333 OSL_FAIL( "FormulaToken::GetRefList: virtual dummy called" );
337 std::vector
<ScComplexRefData
>* FormulaToken::GetRefList()
339 OSL_FAIL( "FormulaToken::GetRefList: virtual dummy called" );
343 bool FormulaToken::TextEqual( const FormulaToken
& rToken
) const
345 return *this == rToken
;
348 // real implementations of virtual functions
351 sal_uInt8
FormulaByteToken::GetByte() const { return nByte
; }
352 void FormulaByteToken::SetByte( sal_uInt8 n
) { nByte
= n
; }
353 ParamClass
FormulaByteToken::GetInForceArray() const { return eInForceArray
; }
354 void FormulaByteToken::SetInForceArray( ParamClass c
) { eInForceArray
= c
; }
355 bool FormulaByteToken::operator==( const FormulaToken
& r
) const
357 return FormulaToken::operator==( r
) && nByte
== r
.GetByte() &&
358 eInForceArray
== r
.GetInForceArray();
362 FormulaToken
* FormulaFAPToken::GetFAPOrigToken() const { return pOrigToken
.get(); }
363 bool FormulaFAPToken::operator==( const FormulaToken
& r
) const
365 return FormulaByteToken::operator==( r
) && pOrigToken
== r
.GetFAPOrigToken();
369 short* FormulaJumpToken::GetJump() const { return pJump
.get(); }
370 ParamClass
FormulaJumpToken::GetInForceArray() const { return eInForceArray
; }
371 void FormulaJumpToken::SetInForceArray( ParamClass c
) { eInForceArray
= c
; }
372 bool FormulaJumpToken::operator==( const FormulaToken
& r
) const
374 return FormulaToken::operator==( r
) && pJump
[0] == r
.GetJump()[0] &&
375 memcmp( pJump
.get()+1, r
.GetJump()+1, pJump
[0] * sizeof(short) ) == 0 &&
376 eInForceArray
== r
.GetInForceArray();
378 FormulaJumpToken::~FormulaJumpToken()
383 bool FormulaTokenArray::AddFormulaToken(
384 const sheet::FormulaToken
& rToken
, svl::SharedStringPool
& rSPool
, ExternalReferenceHelper
* /*pExtRef*/)
387 const OpCode eOpCode
= static_cast<OpCode
>(rToken
.OpCode
); //! assuming equal values for the moment
389 const uno::TypeClass eClass
= rToken
.Data
.getValueTypeClass();
392 case uno::TypeClass_VOID
:
393 // empty data -> use AddOpCode (does some special cases)
394 AddOpCode( eOpCode
);
396 case uno::TypeClass_DOUBLE
:
397 // double is only used for "push"
398 if ( eOpCode
== ocPush
)
399 AddDouble( rToken
.Data
.get
<double>() );
403 case uno::TypeClass_LONG
:
405 // long is svIndex, used for name / database area, or "byte" for spaces
406 sal_Int32 nValue
= rToken
.Data
.get
<sal_Int32
>();
407 if ( eOpCode
== ocDBArea
)
408 Add( new formula::FormulaIndexToken( eOpCode
, static_cast<sal_uInt16
>(nValue
) ) );
409 else if ( eOpCode
== ocTableRef
)
410 bError
= true; /* TODO: implementation */
411 else if ( eOpCode
== ocSpaces
)
412 Add( new formula::FormulaByteToken( ocSpaces
, static_cast<sal_uInt8
>(nValue
) ) );
417 case uno::TypeClass_STRING
:
419 OUString
aStrVal( rToken
.Data
.get
<OUString
>() );
420 if ( eOpCode
== ocPush
)
421 AddString(rSPool
.intern(aStrVal
));
422 else if ( eOpCode
== ocBad
)
424 else if ( eOpCode
== ocStringXML
)
425 AddStringXML( aStrVal
);
426 else if ( eOpCode
== ocExternal
|| eOpCode
== ocMacro
)
427 Add( new formula::FormulaExternalToken( eOpCode
, aStrVal
) );
429 bError
= true; // unexpected string: don't know what to do with it
434 } // switch ( eClass )
438 bool FormulaTokenArray::Fill(
439 const uno::Sequence
<sheet::FormulaToken
>& rSequence
,
440 svl::SharedStringPool
& rSPool
, ExternalReferenceHelper
* pExtRef
)
443 const sal_Int32 nCount
= rSequence
.getLength();
444 for (sal_Int32 nPos
=0; nPos
<nCount
; nPos
++)
446 bool bOneError
= AddFormulaToken(rSequence
[nPos
], rSPool
, pExtRef
);
449 AddOpCode( ocErrName
); // add something that indicates an error
456 void FormulaTokenArray::DelRPN()
460 FormulaToken
** p
= pRPN
;
461 for( sal_uInt16 i
= 0; i
< nRPN
; i
++ )
471 FormulaToken
* FormulaTokenArray::FirstToken() const
473 if (!pCode
|| nLen
== 0)
478 FormulaToken
* FormulaTokenArray::PeekPrev( sal_uInt16
& nIdx
) const
480 if (0 < nIdx
&& nIdx
<= nLen
)
481 return pCode
[--nIdx
];
485 FormulaToken
* FormulaTokenArray::FirstRPNToken() const
487 if (!pRPN
|| nRPN
== 0)
492 bool FormulaTokenArray::HasReferences() const
494 for (auto i
: Tokens())
500 for (auto i
: RPNTokens())
509 bool FormulaTokenArray::HasExternalRef() const
511 for (auto i
: Tokens())
513 if (i
->IsExternalRef())
519 bool FormulaTokenArray::HasOpCode( OpCode eOp
) const
521 for (auto i
: Tokens())
523 if (i
->GetOpCode() == eOp
)
529 bool FormulaTokenArray::HasOpCodeRPN( OpCode eOp
) const
531 for (auto i
: RPNTokens())
533 if (i
->GetOpCode() == eOp
)
539 bool FormulaTokenArray::HasNameOrColRowName() const
541 for (auto i
: Tokens())
543 if (i
->GetType() == svIndex
|| i
->GetOpCode() == ocColRowName
)
549 bool FormulaTokenArray::HasOpCodes(const unordered_opcode_set
& rOpCodes
) const
551 for (auto i
: Tokens())
553 if (rOpCodes
.count(i
->GetOpCode()) > 0)
560 FormulaTokenArray::FormulaTokenArray() :
564 nError(FormulaError::NONE
),
565 nMode(ScRecalcMode::NORMAL
),
567 mbFromRangeName(false),
573 FormulaTokenArray::FormulaTokenArray( const FormulaTokenArray
& rArr
)
578 FormulaTokenArray::~FormulaTokenArray()
580 FormulaTokenArray::Clear();
583 void FormulaTokenArray::Finalize()
585 if( nLen
&& !mbFinalized
)
587 // Add() overallocates, so reallocate to the minimum needed size.
588 std::unique_ptr
<FormulaToken
*[]> newCode(new FormulaToken
*[ nLen
]);
589 std::copy(&pCode
[0], &pCode
[nLen
], newCode
.get());
590 pCode
= std::move( newCode
);
595 void FormulaTokenArray::Assign( const FormulaTokenArray
& r
)
601 bHyperLink
= r
.bHyperLink
;
602 mbFromRangeName
= r
.mbFromRangeName
;
603 mbShareable
= r
.mbShareable
;
604 mbFinalized
= r
.mbFinalized
;
610 pCode
.reset(new FormulaToken
*[ nLen
]);
612 memcpy( pp
, r
.pCode
.get(), nLen
* sizeof( FormulaToken
* ) );
613 for( sal_uInt16 i
= 0; i
< nLen
; i
++ )
619 pp
= pRPN
= new FormulaToken
*[ nRPN
];
620 memcpy( pp
, r
.pRPN
, nRPN
* sizeof( FormulaToken
* ) );
621 for( sal_uInt16 i
= 0; i
< nRPN
; i
++ )
626 /// Optimisation for efficiently creating StringXML placeholders
627 void FormulaTokenArray::Assign( sal_uInt16 nCode
, FormulaToken
**pTokens
)
630 assert( pCode
== nullptr );
633 pCode
.reset(new FormulaToken
*[ nLen
]);
636 for( sal_uInt16 i
= 0; i
< nLen
; i
++ )
638 FormulaToken
*t
= pTokens
[ i
];
639 assert( t
->GetOpCode() == ocStringXML
);
645 FormulaTokenArray
& FormulaTokenArray::operator=( const FormulaTokenArray
& rArr
)
655 void FormulaTokenArray::Clear()
660 FormulaToken
** p
= pCode
.get();
661 for( sal_uInt16 i
= 0; i
< nLen
; i
++ )
668 nError
= FormulaError::NONE
;
671 mbFromRangeName
= false;
677 void FormulaTokenArray::CheckToken( const FormulaToken
& /*r*/ )
682 void FormulaTokenArray::CheckAllRPNTokens()
686 FormulaToken
** p
= pRPN
;
687 for( sal_uInt16 i
= 0; i
< nRPN
; i
++ )
689 CheckToken( *p
[ i
] );
694 FormulaToken
* FormulaTokenArray::AddToken( const FormulaToken
& r
)
696 return Add( r
.Clone() );
699 FormulaToken
* FormulaTokenArray::MergeArray( )
704 FormulaToken
* FormulaTokenArray::ReplaceToken( sal_uInt16 nOffset
, FormulaToken
* t
,
705 FormulaTokenArray::ReplaceMode eMode
)
711 FormulaToken
* p
= pCode
[nOffset
];
713 if (eMode
== CODE_AND_RPN
&& p
->GetRef() > 1)
715 for (sal_uInt16 i
=0; i
< nRPN
; ++i
)
722 if (p
->GetRef() == 1)
727 p
->DecRef(); // may be dead now
732 t
->DeleteIfZeroRef();
737 sal_uInt16
FormulaTokenArray::RemoveToken( sal_uInt16 nOffset
, sal_uInt16 nCount
)
741 SAL_WARN_IF( nOffset
+ nCount
> nLen
, "formula.core",
742 "FormulaTokenArray::RemoveToken - nOffset " << nOffset
<< " + nCount " << nCount
<< " > nLen " << nLen
);
743 const sal_uInt16 nStop
= ::std::min( static_cast<sal_uInt16
>(nOffset
+ nCount
), nLen
);
744 nCount
= nStop
- nOffset
;
745 for (sal_uInt16 j
= nOffset
; j
< nStop
; ++j
)
747 FormulaToken
* p
= pCode
[j
];
750 for (sal_uInt16 i
=0; i
< nRPN
; ++i
)
754 // Shift remaining tokens in pRPN down.
755 for (sal_uInt16 x
=i
+1; x
< nRPN
; ++x
)
762 if (p
->GetRef() == 1)
767 p
->DecRef(); // may be dead now
770 // Shift remaining tokens in pCode down.
771 for (sal_uInt16 x
= nStop
; x
< nLen
; ++x
)
773 pCode
[x
-nCount
] = pCode
[x
];
781 SAL_WARN("formula.core","FormulaTokenArray::RemoveToken - nOffset " << nOffset
<< " >= nLen " << nLen
);
786 FormulaToken
* FormulaTokenArray::Add( FormulaToken
* t
)
788 assert(!mbFinalized
);
791 t
->DeleteIfZeroRef();
795 // Allocating an array of size FORMULA_MAXTOKENS is simple, but that results in relatively large
796 // allocations that malloc() implementations usually do not handle as efficiently as smaller
797 // sizes (not only in terms of memory usage but also speed). Since most token arrays are going
798 // to be small, start with a small array and resize only if needed. Eventually Finalize() will
799 // reallocate the memory to size exactly matching the requirements.
800 const size_t MAX_FAST_TOKENS
= 32;
802 pCode
.reset(new FormulaToken
*[ MAX_FAST_TOKENS
]);
803 if( nLen
== MAX_FAST_TOKENS
)
805 FormulaToken
** tmp
= new FormulaToken
*[ FORMULA_MAXTOKENS
];
806 std::copy(&pCode
[0], &pCode
[MAX_FAST_TOKENS
], tmp
);
809 if( nLen
< FORMULA_MAXTOKENS
- 1 )
814 if( t
->GetOpCode() == ocArrayClose
)
820 t
->DeleteIfZeroRef();
821 if ( nLen
== FORMULA_MAXTOKENS
- 1 )
823 t
= new FormulaByteToken( ocStop
);
831 FormulaToken
* FormulaTokenArray::AddString( const svl::SharedString
& rStr
)
833 return Add( new FormulaStringToken( rStr
) );
836 FormulaToken
* FormulaTokenArray::AddDouble( double fVal
)
838 return Add( new FormulaDoubleToken( fVal
) );
841 void FormulaTokenArray::AddExternal( const sal_Unicode
* pStr
)
843 AddExternal( OUString( pStr
) );
846 FormulaToken
* FormulaTokenArray::AddExternal( const OUString
& rStr
,
847 OpCode eOp
/* = ocExternal */ )
849 return Add( new FormulaExternalToken( eOp
, rStr
) );
852 FormulaToken
* FormulaTokenArray::AddBad( const OUString
& rStr
)
854 return Add( new FormulaStringOpToken( ocBad
, svl::SharedString( rStr
) ) ); // string not interned
857 FormulaToken
* FormulaTokenArray::AddStringXML( const OUString
& rStr
)
859 return Add( new FormulaStringOpToken( ocStringXML
, svl::SharedString( rStr
) ) ); // string not interned
863 void FormulaTokenArray::AddRecalcMode( ScRecalcMode nBits
)
865 const unsigned nExclusive
= static_cast<sal_uInt8
>(nBits
& ScRecalcMode::EMask
);
869 if (nExclusive
& (nExclusive
- 1))
871 // More than one bit set, use highest priority.
872 for (nExBit
= 1; (nExBit
& static_cast<sal_uInt8
>(ScRecalcMode::EMask
)) != 0; nExBit
<<= 1)
874 if (nExclusive
& nExBit
)
880 // Only one bit is set.
883 // Set exclusive bit if priority is higher than existing.
884 if (nExBit
< static_cast<sal_uInt8
>(nMode
& ScRecalcMode::EMask
))
885 SetMaskedRecalcMode( static_cast<ScRecalcMode
>(nExBit
));
887 SetCombinedBitsRecalcMode( nBits
);
891 bool FormulaTokenArray::HasMatrixDoubleRefOps() const
895 // RPN-Interpreter simulation.
896 // Simply assumes a double as return value of each function.
897 std::unique_ptr
<FormulaToken
*[]> pStack(new FormulaToken
* [nRPN
]);
898 FormulaToken
* pResult
= new FormulaDoubleToken( 0.0 );
900 for ( auto t
: RPNTokens() )
902 OpCode eOp
= t
->GetOpCode();
903 sal_uInt8 nParams
= t
->GetParamCount();
918 case ocGreaterEqual
:
920 for ( sal_uInt8 k
= nParams
; k
; k
-- )
922 if ( sp
>= k
&& pStack
[sp
-k
]->GetType() == svDoubleRef
)
932 // added to avoid warnings
935 if ( eOp
== ocPush
|| lcl_IsReference( eOp
, t
->GetType() ) )
937 else if (FormulaCompiler::IsOpCodeJumpCommand( eOp
))
938 { // ignore Jumps, pop previous Result (Condition)
943 { // pop parameters, push result
944 sp
= sal::static_int_cast
<short>( sp
- nParams
);
947 SAL_WARN("formula.core", "FormulaTokenArray::HasMatrixDoubleRefOps: sp < 0" );
950 pStack
[sp
++] = pResult
;
959 // --- Formula rewrite of a token array
961 inline bool MissingConventionODF::isRewriteNeeded( OpCode eOp
) const
974 return isPODF(); // rewrite only for PODF
977 return isODFF(); // rewrite only for ODFF
985 To be implemented yet:
990 inline bool MissingConventionOOXML::isRewriteNeeded( OpCode eOp
)
1028 class FormulaMissingContext
1031 const FormulaToken
* mpFunc
;
1034 void Clear() { mpFunc
= nullptr; mnCurArg
= 0; }
1035 inline bool AddDefaultArg( FormulaTokenArray
* pNewArr
, int nArg
, double f
) const;
1036 bool AddMissingExternal( FormulaTokenArray
* pNewArr
) const;
1037 bool AddMissing( FormulaTokenArray
*pNewArr
, const MissingConvention
& rConv
) const;
1038 void AddMoreArgs( FormulaTokenArray
*pNewArr
, const MissingConvention
& rConv
) const;
1043 void FormulaMissingContext::AddMoreArgs( FormulaTokenArray
*pNewArr
, const MissingConvention
& rConv
) const
1048 switch (rConv
.getConvention())
1050 case MissingConvention::FORMULA_MISSING_CONVENTION_ODFF
:
1051 case MissingConvention::FORMULA_MISSING_CONVENTION_PODF
:
1053 switch (mpFunc
->GetOpCode())
1058 pNewArr
->AddOpCode( ocSep
);
1059 pNewArr
->AddDouble( 1.0 ); // 4th, Cumulative=true()
1065 pNewArr
->AddOpCode( ocSep
);
1066 pNewArr
->AddDouble( 1.0 ); // 3rd, Cumulative=true()
1070 if ( mnCurArg
== 2 )
1072 pNewArr
->AddOpCode( ocSep
);
1073 pNewArr
->AddDouble( 1.0 ); // 4th, Cumulative=true()
1078 if ( mnCurArg
== 0 )
1080 pNewArr
->AddOpCode( ocSep
);
1081 pNewArr
->AddDouble( 0.0 ); // 2nd, mean = 0.0
1083 if ( mnCurArg
<= 1 )
1085 pNewArr
->AddOpCode( ocSep
);
1086 pNewArr
->AddDouble( 1.0 ); // 3rd, standard deviation = 1.0
1090 if ( rConv
.isPODF() && mnCurArg
== 0 )
1092 pNewArr
->AddOpCode( ocSep
);
1093 pNewArr
->AddDouble( 10.0 ); // 2nd, basis 10
1101 case MissingConvention::FORMULA_MISSING_CONVENTION_OOXML
:
1103 switch (mpFunc
->GetOpCode())
1108 // Excel needs at least two parameters in IF function
1109 pNewArr
->AddOpCode( ocSep
);
1110 pNewArr
->AddOpCode( ocTrue
); // 2nd, true() as function
1111 pNewArr
->AddOpCode( ocOpen
); // so the result is of logical type
1112 pNewArr
->AddOpCode( ocClose
); // and survives roundtrip
1117 if ( mnCurArg
== 2 )
1119 pNewArr
->AddOpCode( ocSep
);
1120 pNewArr
->AddDouble( 0.0 ); // 4th, FullPrecision = false()
1127 pNewArr
->AddOpCode( ocSep
);
1128 pNewArr
->AddDouble( 1.0 ); // 3rd, Cumulative=true()
1137 pNewArr
->AddOpCode( ocSep
);
1138 pNewArr
->AddDouble( 1.0 ); // 4th, Cumulative=true()
1144 if ( mnCurArg
== 0 )
1146 pNewArr
->AddOpCode( ocSep
);
1147 pNewArr
->AddDouble( 0.0 ); // 2nd, mean = 0.0
1149 if ( mnCurArg
<= 1 )
1151 pNewArr
->AddOpCode( ocSep
);
1152 pNewArr
->AddDouble( 1.0 ); // 3rd, standard deviation = 1.0
1157 if ( mnCurArg
== 3 )
1159 pNewArr
->AddOpCode( ocSep
);
1160 pNewArr
->AddDouble( 0.0 ); // 5th, Cumulative = false()
1169 // ROUND, ROUNDUP, ROUNDDOWN functions are fixed to 2 parameters in Excel
1170 pNewArr
->AddOpCode( ocSep
);
1171 pNewArr
->AddDouble( 0.0 ); // 2nd, 0.0
1184 inline bool FormulaMissingContext::AddDefaultArg( FormulaTokenArray
* pNewArr
, int nArg
, double f
) const
1186 if (mnCurArg
== nArg
)
1188 pNewArr
->AddDouble( f
);
1194 bool FormulaMissingContext::AddMissingExternal( FormulaTokenArray
*pNewArr
) const
1196 // Only called for PODF, not ODFF. No need to distinguish.
1198 const OUString
&rName
= mpFunc
->GetExternal();
1200 // initial (fast) check:
1201 sal_Unicode nLastChar
= rName
[ rName
.getLength() - 1];
1202 if ( nLastChar
!= 't' && nLastChar
!= 'm' )
1205 if (rName
.equalsIgnoreAsciiCase(
1206 "com.sun.star.sheet.addin.Analysis.getAccrint" ))
1208 return AddDefaultArg( pNewArr
, 4, 1000.0 );
1210 if (rName
.equalsIgnoreAsciiCase(
1211 "com.sun.star.sheet.addin.Analysis.getAccrintm" ))
1213 return AddDefaultArg( pNewArr
, 3, 1000.0 );
1218 bool FormulaMissingContext::AddMissing( FormulaTokenArray
*pNewArr
, const MissingConvention
& rConv
) const
1224 const OpCode eOp
= mpFunc
->GetOpCode();
1226 switch (rConv
.getConvention())
1228 case MissingConvention::FORMULA_MISSING_CONVENTION_ODFF
:
1234 return AddDefaultArg( pNewArr
, 2, 1.0 ); // abs
1240 case MissingConvention::FORMULA_MISSING_CONVENTION_PODF
:
1246 return AddDefaultArg( pNewArr
, 2, 1.0 ); // abs
1248 return AddDefaultArg( pNewArr
, 1, 2.0 );
1252 return AddDefaultArg( pNewArr
, 3, 0.0 );
1255 return AddDefaultArg( pNewArr
, 4, 0.0 );
1258 bRet
|= AddDefaultArg( pNewArr
, 2, 0.0 ); // pmt
1259 bRet
|= AddDefaultArg( pNewArr
, 3, 0.0 ); // [fp]v
1262 bRet
|= AddDefaultArg( pNewArr
, 1, 0.0 ); // pmt
1263 bRet
|= AddDefaultArg( pNewArr
, 3, 0.0 ); // fv
1264 bRet
|= AddDefaultArg( pNewArr
, 4, 0.0 ); // type
1267 return AddMissingExternal( pNewArr
);
1269 // --- more complex cases ---
1272 // FIXME: rather tough
1273 // if arg 3 (height) omitted, export arg1 (rows)
1280 case MissingConvention::FORMULA_MISSING_CONVENTION_OOXML
:
1285 return AddMissingExternal( pNewArr
);
1296 bool FormulaTokenArray::NeedsPodfRewrite( const MissingConventionODF
& rConv
)
1298 for ( auto i
: Tokens() )
1300 if ( rConv
.isRewriteNeeded( i
->GetOpCode()))
1306 bool FormulaTokenArray::NeedsOoxmlRewrite()
1308 for ( auto i
: Tokens() )
1310 if ( MissingConventionOOXML::isRewriteNeeded( i
->GetOpCode()))
1317 FormulaTokenArray
* FormulaTokenArray::RewriteMissing( const MissingConvention
& rConv
)
1319 const size_t nAlloc
= 256;
1320 FormulaMissingContext aCtx
[ nAlloc
];
1322 /* TODO: with some effort we might be able to merge the two almost
1323 * identical function stacks into one and generalize things, otherwise
1324 * adding yet another "omit argument" would be copypasta. */
1326 int aOpCodeAddressStack
[ nAlloc
]; // use of ADDRESS() function
1327 const int nOmitAddressArg
= 3; // ADDRESS() 4th parameter A1/R1C1
1329 int aOpCodeDcountStack
[ nAlloc
]; // use of DCOUNT()/DCOUNTA() function
1330 const int nOmitDcountArg
= 1; // DCOUNT() and DCOUNTA() 2nd parameter DatabaseField if 0
1332 sal_uInt16 nTokens
= GetLen() + 1;
1333 FormulaMissingContext
* pCtx
= (nAlloc
< nTokens
? new FormulaMissingContext
[nTokens
] : &aCtx
[0]);
1334 int* pOcas
= (nAlloc
< nTokens
? new int[nTokens
] : &aOpCodeAddressStack
[0]);
1335 int* pOcds
= (nAlloc
< nTokens
? new int[nTokens
] : &aOpCodeDcountStack
[0]);
1336 // Never go below 0, never use 0, mpFunc always NULL.
1342 FormulaTokenArray
*pNewArr
= new FormulaTokenArray
;
1343 // At least ScRecalcMode::ALWAYS needs to be set.
1344 pNewArr
->AddRecalcMode( GetRecalcMode());
1346 FormulaTokenArrayPlainIterator
aIter(*this);
1347 for ( FormulaToken
*pCur
= aIter
.First(); pCur
; pCur
= aIter
.Next() )
1350 // Don't write the expression of the new inserted ADDRESS() parameter.
1351 // Do NOT omit the new second parameter of INDIRECT() though. If that
1352 // was done for both, INDIRECT() actually could calculate different and
1353 // valid (but wrong) results with the then changed return value of
1354 // ADDRESS(). Better let it generate an error instead.
1355 for (int i
= nOcas
; i
-- > 0 && bAdd
; )
1357 if (pCtx
[ pOcas
[ i
] ].mnCurArg
== nOmitAddressArg
)
1359 // Omit everything except a trailing separator, the leading
1360 // separator is omitted below. The other way around would leave
1361 // an extraneous separator if no parameter followed.
1362 if (pOcas
[ i
] != nFn
|| pCur
->GetOpCode() != ocSep
)
1366 // Strip the 2nd argument (leaving empty) of DCOUNT() and DCOUNTA() if
1368 for (int i
= nOcds
; i
-- > 0 && bAdd
; )
1370 if (pCtx
[ pOcds
[ i
] ].mnCurArg
== nOmitDcountArg
)
1372 // Omit only a literal 0 value, nothing else.
1373 if (pOcds
[ i
] == nFn
&& pCur
->GetOpCode() == ocPush
&& pCur
->GetType() == svDouble
&&
1374 pCur
->GetDouble() == 0.0)
1376 // No other expression, between separators.
1377 FormulaToken
* p
= aIter
.PeekPrevNoSpaces();
1378 if (p
&& p
->GetOpCode() == ocSep
)
1380 p
= aIter
.PeekNextNoSpaces();
1381 if (p
&& p
->GetOpCode() == ocSep
)
1387 switch ( pCur
->GetOpCode() )
1391 ++nFn
; // all following operations on _that_ function
1392 pCtx
[ nFn
].mpFunc
= aIter
.PeekPrevNoSpaces();
1393 pCtx
[ nFn
].mnCurArg
= 0;
1394 if (rConv
.isPODF() && pCtx
[ nFn
].mpFunc
&& pCtx
[ nFn
].mpFunc
->GetOpCode() == ocAddress
)
1395 pOcas
[ nOcas
++ ] = nFn
; // entering ADDRESS() if PODF
1396 else if ((rConv
.isODFF() || rConv
.isOOXML()) && pCtx
[ nFn
].mpFunc
)
1398 OpCode eOp
= pCtx
[ nFn
].mpFunc
->GetOpCode();
1399 if (eOp
== ocDBCount
|| eOp
== ocDBCount2
)
1400 pOcds
[ nOcds
++ ] = nFn
; // entering DCOUNT() or DCOUNTA() if ODFF or OOXML
1405 pCtx
[ nFn
].AddMoreArgs( pNewArr
, rConv
);
1406 SAL_WARN_IF(nFn
<= 0, "formula.core", "FormulaTokenArray::RewriteMissing: underflow");
1407 if (nOcas
> 0 && pOcas
[ nOcas
-1 ] == nFn
)
1408 --nOcas
; // leaving ADDRESS()
1409 else if (nOcds
> 0 && pOcds
[ nOcds
-1 ] == nFn
)
1410 --nOcds
; // leaving DCOUNT() or DCOUNTA()
1415 pCtx
[ nFn
].mnCurArg
++;
1416 // Omit leading separator of ADDRESS() parameter.
1417 if (nOcas
&& pOcas
[ nOcas
-1 ] == nFn
&& pCtx
[ nFn
].mnCurArg
== nOmitAddressArg
)
1424 bAdd
= !pCtx
[ nFn
].AddMissing( pNewArr
, rConv
);
1431 OpCode eOp
= pCur
->GetOpCode();
1432 if ( ( eOp
== ocCeil
|| eOp
== ocFloor
||
1433 ( eOp
== ocLogNormDist
&& pCur
->GetByte() == 4 ) ) &&
1434 rConv
.getConvention() == MissingConvention::FORMULA_MISSING_CONVENTION_OOXML
)
1444 case ocLogNormDist
:
1445 eOp
= ocLogNormDist_MS
;
1451 FormulaToken
*pToken
= new FormulaToken( svByte
, eOp
);
1452 pNewArr
->Add( pToken
);
1454 else if ( eOp
== ocHypGeomDist
&&
1455 rConv
.getConvention() == MissingConvention::FORMULA_MISSING_CONVENTION_OOXML
)
1457 FormulaToken
*pToken
= new FormulaToken( svByte
, ocHypGeomDist_MS
);
1458 pNewArr
->Add( pToken
);
1461 pNewArr
->AddToken( *pCur
);
1465 if (pOcds
!= &aOpCodeDcountStack
[0])
1467 if (pOcas
!= &aOpCodeAddressStack
[0])
1469 if (pCtx
!= &aCtx
[0])
1475 bool FormulaTokenArray::MayReferenceFollow()
1477 if ( pCode
&& nLen
> 0 )
1479 // ignore trailing spaces
1480 sal_uInt16 i
= nLen
- 1;
1481 while ( i
> 0 && pCode
[i
]->GetOpCode() == SC_OPCODE_SPACES
)
1485 if ( i
> 0 || pCode
[i
]->GetOpCode() != SC_OPCODE_SPACES
)
1487 OpCode eOp
= pCode
[i
]->GetOpCode();
1488 if ( (SC_OPCODE_START_BIN_OP
<= eOp
&& eOp
< SC_OPCODE_STOP_BIN_OP
) ||
1489 (SC_OPCODE_START_UN_OP
<= eOp
&& eOp
< SC_OPCODE_STOP_UN_OP
) ||
1490 eOp
== SC_OPCODE_OPEN
|| eOp
== SC_OPCODE_SEP
)
1498 FormulaToken
* FormulaTokenArray::AddOpCode( OpCode eOp
)
1500 FormulaToken
* pRet
= nullptr;
1510 pRet
= new FormulaToken( svSep
,eOp
);
1517 short nJump
[FORMULA_MAXJUMPCOUNT
+ 1];
1520 else if ( eOp
== ocChoose
)
1521 nJump
[ 0 ] = FORMULA_MAXJUMPCOUNT
+ 1;
1524 pRet
= new FormulaJumpToken( eOp
, nJump
);
1528 pRet
= new FormulaByteToken( eOp
, 0, ParamClass::Unknown
);
1534 void FormulaTokenArray::ReinternStrings( svl::SharedStringPool
& rPool
)
1536 for (auto i
: Tokens())
1538 switch (i
->GetType())
1541 i
->SetString( rPool
.intern( i
->GetString().getString()));
1550 /*----------------------------------------------------------------------*/
1552 FormulaTokenIterator::Item::Item(const FormulaTokenArray
* pArray
, short pc
, short stop
) :
1553 pArr(pArray
), nPC(pc
), nStop(stop
)
1557 FormulaTokenIterator::FormulaTokenIterator( const FormulaTokenArray
& rArr
)
1562 FormulaTokenIterator::~FormulaTokenIterator()
1566 void FormulaTokenIterator::Push( const FormulaTokenArray
* pArr
)
1568 FormulaTokenIterator::Item
item(pArr
, -1, SHRT_MAX
);
1570 maStack
.push_back(item
);
1573 void FormulaTokenIterator::Pop()
1578 void FormulaTokenIterator::Reset()
1580 while( maStack
.size() > 1 )
1583 maStack
.back().nPC
= -1;
1586 FormulaToken
* FormulaTokenArrayPlainIterator::GetNextName()
1588 if( mpFTA
->GetArray() )
1590 while ( mnIndex
< mpFTA
->GetLen() )
1592 FormulaToken
* t
= mpFTA
->GetArray()[ mnIndex
++ ];
1593 if( t
->GetType() == svIndex
)
1600 const FormulaToken
* FormulaTokenIterator::Next()
1602 const FormulaToken
* t
= GetNonEndOfPathToken( ++maStack
.back().nPC
);
1603 if( !t
&& maStack
.size() > 1 )
1611 const FormulaToken
* FormulaTokenIterator::PeekNextOperator()
1613 const FormulaToken
* t
= nullptr;
1614 short nIdx
= maStack
.back().nPC
;
1617 t
= GetNonEndOfPathToken( ++nIdx
);
1618 if (t
== nullptr || t
->GetOpCode() != ocPush
)
1619 break; // ignore operands
1621 if (!t
&& maStack
.size() > 1)
1623 FormulaTokenIterator::Item aHere
= maStack
.back();
1625 t
= PeekNextOperator();
1626 maStack
.push_back(aHere
);
1631 //! The nPC counts after a Push() are -1
1633 void FormulaTokenIterator::Jump( short nStart
, short nNext
, short nStop
)
1635 maStack
.back().nPC
= nNext
;
1636 if( nStart
!= nNext
)
1638 Push( maStack
.back().pArr
);
1639 maStack
.back().nPC
= nStart
;
1640 maStack
.back().nStop
= nStop
;
1644 void FormulaTokenIterator::ReInit( const FormulaTokenArray
& rArr
)
1650 const FormulaToken
* FormulaTokenIterator::GetNonEndOfPathToken( short nIdx
) const
1652 FormulaTokenIterator::Item cur
= maStack
.back();
1654 if (nIdx
< cur
.pArr
->GetCodeLen() && nIdx
< cur
.nStop
)
1656 const FormulaToken
* t
= cur
.pArr
->GetCode()[ nIdx
];
1657 // such an OpCode ends an IF() or CHOOSE() path
1658 return (t
->GetOpCode() == ocSep
|| t
->GetOpCode() == ocClose
) ? nullptr : t
;
1663 bool FormulaTokenIterator::IsEndOfPath() const
1665 return GetNonEndOfPathToken( maStack
.back().nPC
+ 1) == nullptr;
1668 FormulaToken
* FormulaTokenArrayPlainIterator::GetNextReference()
1670 while( mnIndex
< mpFTA
->GetLen() )
1672 FormulaToken
* t
= mpFTA
->GetArray()[ mnIndex
++ ];
1673 switch( t
->GetType() )
1677 case svExternalSingleRef
:
1678 case svExternalDoubleRef
:
1682 // added to avoid warnings
1689 FormulaToken
* FormulaTokenArrayPlainIterator::GetNextColRowName()
1691 while( mnIndex
< mpFTA
->GetLen() )
1693 FormulaToken
* t
= mpFTA
->GetArray()[ mnIndex
++ ];
1694 if ( t
->GetOpCode() == ocColRowName
)
1700 FormulaToken
* FormulaTokenArrayPlainIterator::GetNextReferenceRPN()
1702 while( mnIndex
< mpFTA
->GetCodeLen() )
1704 FormulaToken
* t
= mpFTA
->GetCode()[ mnIndex
++ ];
1705 switch( t
->GetType() )
1709 case svExternalSingleRef
:
1710 case svExternalDoubleRef
:
1714 // added to avoid warnings
1721 FormulaToken
* FormulaTokenArrayPlainIterator::GetNextReferenceOrName()
1723 if( mpFTA
->GetArray() )
1725 while ( mnIndex
< mpFTA
->GetLen() )
1727 FormulaToken
* t
= mpFTA
->GetArray()[ mnIndex
++ ];
1728 switch( t
->GetType() )
1733 case svExternalSingleRef
:
1734 case svExternalDoubleRef
:
1735 case svExternalName
:
1739 // added to avoid warnings
1747 FormulaToken
* FormulaTokenArrayPlainIterator::Next()
1749 if( mpFTA
->GetArray() && mnIndex
< mpFTA
->GetLen() )
1750 return mpFTA
->GetArray()[ mnIndex
++ ];
1755 FormulaToken
* FormulaTokenArrayPlainIterator::NextNoSpaces()
1757 if( mpFTA
->GetArray() )
1759 while( (mnIndex
< mpFTA
->GetLen()) && (mpFTA
->GetArray()[ mnIndex
]->GetOpCode() == ocSpaces
) )
1761 if( mnIndex
< mpFTA
->GetLen() )
1762 return mpFTA
->GetArray()[ mnIndex
++ ];
1767 FormulaToken
* FormulaTokenArrayPlainIterator::NextRPN()
1769 if( mpFTA
->GetCode() && mnIndex
< mpFTA
->GetCodeLen() )
1770 return mpFTA
->GetCode()[ mnIndex
++ ];
1775 FormulaToken
* FormulaTokenArrayPlainIterator::PrevRPN()
1777 if( mpFTA
->GetCode() && mnIndex
)
1778 return mpFTA
->GetCode()[ --mnIndex
];
1783 FormulaToken
* FormulaTokenArrayPlainIterator::PeekNext()
1785 if( mpFTA
->GetArray() && mnIndex
< mpFTA
->GetLen() )
1786 return mpFTA
->GetArray()[ mnIndex
];
1791 FormulaToken
* FormulaTokenArrayPlainIterator::PeekNextNoSpaces() const
1793 if( mpFTA
->GetArray() && mnIndex
< mpFTA
->GetLen() )
1795 sal_uInt16 j
= mnIndex
;
1796 while ( j
< mpFTA
->GetLen() && mpFTA
->GetArray()[j
]->GetOpCode() == ocSpaces
)
1798 if ( j
< mpFTA
->GetLen() )
1799 return mpFTA
->GetArray()[ j
];
1807 FormulaToken
* FormulaTokenArrayPlainIterator::PeekPrevNoSpaces() const
1809 if( mpFTA
->GetArray() && mnIndex
> 1 )
1811 sal_uInt16 j
= mnIndex
- 2;
1812 while ( mpFTA
->GetArray()[j
]->GetOpCode() == ocSpaces
&& j
> 0 )
1814 if ( j
> 0 || mpFTA
->GetArray()[j
]->GetOpCode() != ocSpaces
)
1815 return mpFTA
->GetArray()[ j
];
1823 void FormulaTokenArrayPlainIterator::AfterRemoveToken( sal_uInt16 nOffset
, sal_uInt16 nCount
)
1825 const sal_uInt16 nStop
= std::min( static_cast<sal_uInt16
>(nOffset
+ nCount
), mpFTA
->GetLen());
1827 if (mnIndex
>= nOffset
)
1829 if (mnIndex
< nStop
)
1830 mnIndex
= nOffset
+ 1;
1832 mnIndex
-= nStop
- nOffset
;
1836 // real implementations of virtual functions
1839 double FormulaDoubleToken::GetDouble() const { return fDouble
; }
1840 double & FormulaDoubleToken::GetDoubleAsReference() { return fDouble
; }
1842 sal_Int16
FormulaDoubleToken::GetDoubleType() const
1844 // This is a plain double value without type information, don't emit a
1845 // warning via FormulaToken::GetDoubleType().
1849 bool FormulaDoubleToken::operator==( const FormulaToken
& r
) const
1851 return FormulaToken::operator==( r
) && fDouble
== r
.GetDouble();
1854 sal_Int16
FormulaTypedDoubleToken::GetDoubleType() const
1859 void FormulaTypedDoubleToken::SetDoubleType( sal_Int16 nType
)
1864 bool FormulaTypedDoubleToken::operator==( const FormulaToken
& r
) const
1866 return FormulaDoubleToken::operator==( r
) && mnType
== r
.GetDoubleType();
1869 FormulaStringToken::FormulaStringToken( const svl::SharedString
& r
) :
1870 FormulaToken( svString
), maString( r
)
1874 FormulaStringToken::FormulaStringToken( const FormulaStringToken
& r
) :
1875 FormulaToken( r
), maString( r
.maString
) {}
1877 FormulaToken
* FormulaStringToken::Clone() const
1879 return new FormulaStringToken(*this);
1882 const svl::SharedString
& FormulaStringToken::GetString() const
1887 void FormulaStringToken::SetString( const svl::SharedString
& rStr
)
1892 bool FormulaStringToken::operator==( const FormulaToken
& r
) const
1894 return FormulaToken::operator==( r
) && maString
== r
.GetString();
1897 FormulaStringOpToken::FormulaStringOpToken( OpCode e
, const svl::SharedString
& r
) :
1898 FormulaByteToken( e
, 0, svString
, ParamClass::Unknown
), maString( r
) {}
1900 FormulaStringOpToken::FormulaStringOpToken( const FormulaStringOpToken
& r
) :
1901 FormulaByteToken( r
), maString( r
.maString
) {}
1903 FormulaToken
* FormulaStringOpToken::Clone() const
1905 return new FormulaStringOpToken(*this);
1908 const svl::SharedString
& FormulaStringOpToken::GetString() const
1913 void FormulaStringOpToken::SetString( const svl::SharedString
& rStr
)
1918 bool FormulaStringOpToken::operator==( const FormulaToken
& r
) const
1920 return FormulaByteToken::operator==( r
) && maString
== r
.GetString();
1923 sal_uInt16
FormulaIndexToken::GetIndex() const { return nIndex
; }
1924 void FormulaIndexToken::SetIndex( sal_uInt16 n
) { nIndex
= n
; }
1925 sal_Int16
FormulaIndexToken::GetSheet() const { return mnSheet
; }
1926 void FormulaIndexToken::SetSheet( sal_Int16 n
) { mnSheet
= n
; }
1927 bool FormulaIndexToken::operator==( const FormulaToken
& r
) const
1929 return FormulaToken::operator==( r
) && nIndex
== r
.GetIndex() &&
1930 mnSheet
== r
.GetSheet();
1932 const OUString
& FormulaExternalToken::GetExternal() const { return aExternal
; }
1933 bool FormulaExternalToken::operator==( const FormulaToken
& r
) const
1935 return FormulaByteToken::operator==( r
) && aExternal
== r
.GetExternal();
1939 FormulaError
FormulaErrorToken::GetError() const { return nError
; }
1940 void FormulaErrorToken::SetError( FormulaError nErr
) { nError
= nErr
; }
1941 bool FormulaErrorToken::operator==( const FormulaToken
& r
) const
1943 return FormulaToken::operator==( r
) &&
1944 nError
== static_cast< const FormulaErrorToken
& >(r
).GetError();
1946 double FormulaMissingToken::GetDouble() const { return 0.0; }
1948 const svl::SharedString
& FormulaMissingToken::GetString() const
1950 return svl::SharedString::getEmptyString();
1953 bool FormulaMissingToken::operator==( const FormulaToken
& r
) const
1955 return FormulaToken::operator==( r
);
1959 bool FormulaUnknownToken::operator==( const FormulaToken
& r
) const
1961 return FormulaToken::operator==( r
);
1968 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */