1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #ifndef FORMULA_TOKENARRAY_HXX
25 #define FORMULA_TOKENARRAY_HXX
26
27 #include "formula/token.hxx"
28 #include "formula/ExternalReferenceHelper.hxx"
29 #include <tools/solar.h>
30 #include <com/sun/star/sheet/FormulaToken.hpp>
31
32 #include <limits.h>
33
34 namespace formula
35 {
36
37 // RecalcMode access only via TokenArray SetRecalcMode / IsRecalcMode...
38
39 typedef sal_uInt8 ScRecalcMode;
40 // Only one of the exclusive bits can be set,
41 // handled by TokenArray SetRecalcMode... methods
42 #define RECALCMODE_NORMAL 0x01 // exclusive
43 #define RECALCMODE_ALWAYS 0x02 // exclusive, always
44 #define RECALCMODE_ONLOAD 0x04 // exclusive, always after load
45 #define RECALCMODE_ONLOAD_ONCE 0x08 // exclusive, once after load
46 #define RECALCMODE_FORCED 0x10 // combined, also if cell isn't visible
47 #define RECALCMODE_ONREFMOVE 0x20 // combined, if reference was moved
48 #define RECALCMODE_EMASK 0x0F // mask of exclusive bits
49 // If new bits are to be defined, AddRecalcMode has to be adjusted!
50
51 class FormulaMissingContext;
52
53 class FORMULA_DLLPUBLIC MissingConvention
54 {
55 bool mbODFF; /// TRUE: ODFF, FALSE: PODF
56 public:
MissingConvention(bool bODFF)57 explicit MissingConvention( bool bODFF ) : mbODFF(bODFF) {}
58 // Implementation and usage only in token.cxx
59 inline bool isRewriteNeeded( OpCode eOp ) const;
isODFF() const60 inline bool isODFF() const { return mbODFF; }
61 };
62
63 class FORMULA_DLLPUBLIC FormulaTokenArray
64 {
65 friend class FormulaCompiler;
66 friend class FormulaTokenIterator;
67 friend class FormulaMissingContext;
68
69 protected:
70 FormulaToken** pCode; // Token code array
71 FormulaToken** pRPN; // RPN array
72 sal_uInt16 nLen; // Length of token array
73 sal_uInt16 nRPN; // Length of RPN array
74 sal_uInt16 nIndex; // Current step index
75 sal_uInt16 nError; // Error code
76 short nRefs; // Count of cell references
77 ScRecalcMode nMode; // Flags to indicate when to recalc this code
78 sal_Bool bHyperLink; // If HYPERLINK() occurs in the formula.
79
80 protected:
81 void Assign( const FormulaTokenArray& );
82
83 /// Also used by the compiler. The token MUST had been allocated with new!
84 FormulaToken* Add( FormulaToken* );
SetCombinedBitsRecalcMode(ScRecalcMode nBits)85 inline void SetCombinedBitsRecalcMode( ScRecalcMode nBits )
86 { nMode |= (nBits & ~RECALCMODE_EMASK); }
GetCombinedBitsRecalcMode() const87 inline ScRecalcMode GetCombinedBitsRecalcMode() const
88 { return nMode & ~RECALCMODE_EMASK; }
89 /** Exclusive bits already set in nMode are
90 zero'ed, nVal may contain combined bits, but
91 only one exclusive bit may be set! */
SetMaskedRecalcMode(ScRecalcMode nBits)92 inline void SetMaskedRecalcMode( ScRecalcMode nBits )
93 { nMode = GetCombinedBitsRecalcMode() | nBits; }
94
95 public:
96 FormulaTokenArray();
97 /// Assignment with references to FormulaToken entries (not copied!)
98 FormulaTokenArray( const FormulaTokenArray& );
99 virtual ~FormulaTokenArray();
100 FormulaTokenArray* Clone() const; /// True copy!
101 void Clear();
102 void DelRPN();
First()103 FormulaToken* First() { nIndex = 0; return Next(); }
104 FormulaToken* Next();
FirstNoSpaces()105 FormulaToken* FirstNoSpaces() { nIndex = 0; return NextNoSpaces(); }
106 FormulaToken* NextNoSpaces();
107 FormulaToken* GetNextName();
108 FormulaToken* GetNextDBArea();
109 FormulaToken* GetNextReference();
110 FormulaToken* GetNextReferenceRPN();
111 FormulaToken* GetNextReferenceOrName();
112 FormulaToken* GetNextColRowName();
113 FormulaToken* GetNextOpCodeRPN( OpCode );
114 /// Peek at nIdx-1 if not out of bounds, decrements nIdx if successful. Returns NULL if not.
115 FormulaToken* PeekPrev( sal_uInt16 & nIdx );
116 FormulaToken* PeekNext();
117 FormulaToken* PeekPrevNoSpaces(); /// Only after Reset/First/Next/Last/Prev!
118 FormulaToken* PeekNextNoSpaces(); /// Only after Reset/First/Next/Last/Prev!
FirstRPN()119 FormulaToken* FirstRPN() { nIndex = 0; return NextRPN(); }
120 FormulaToken* NextRPN();
LastRPN()121 FormulaToken* LastRPN() { nIndex = nRPN; return PrevRPN(); }
122 FormulaToken* PrevRPN();
123
124 sal_Bool HasOpCode( OpCode ) const;
125 sal_Bool HasOpCodeRPN( OpCode ) const;
126 /// Token of type svIndex or opcode ocColRowName
127 sal_Bool HasNameOrColRowName() const;
128
GetArray() const129 FormulaToken** GetArray() const { return pCode; }
GetCode() const130 FormulaToken** GetCode() const { return pRPN; }
GetLen() const131 sal_uInt16 GetLen() const { return nLen; }
GetCodeLen() const132 sal_uInt16 GetCodeLen() const { return nRPN; }
Reset()133 void Reset() { nIndex = 0; }
GetCodeError() const134 sal_uInt16 GetCodeError() const { return nError; }
SetCodeError(sal_uInt16 n)135 void SetCodeError( sal_uInt16 n ) { nError = n; }
GetRefs() const136 short GetRefs() const { return nRefs; }
IncrementRefs()137 void IncrementRefs() { ++nRefs; }
SetHyperLink(sal_Bool bVal)138 void SetHyperLink( sal_Bool bVal ) { bHyperLink = bVal; }
IsHyperLink() const139 sal_Bool IsHyperLink() const { return bHyperLink; }
140
GetRecalcMode() const141 inline ScRecalcMode GetRecalcMode() const { return nMode; }
142 /** Bits aren't set directly but validated and
143 maybe handled according to priority if more
144 than one exclusive bit was set. */
145 void AddRecalcMode( ScRecalcMode nBits );
146
ClearRecalcMode()147 inline void ClearRecalcMode() { nMode = RECALCMODE_NORMAL; }
SetRecalcModeNormal()148 inline void SetRecalcModeNormal()
149 { SetMaskedRecalcMode( RECALCMODE_NORMAL ); }
SetRecalcModeAlways()150 inline void SetRecalcModeAlways()
151 { SetMaskedRecalcMode( RECALCMODE_ALWAYS ); }
SetRecalcModeOnLoad()152 inline void SetRecalcModeOnLoad()
153 { SetMaskedRecalcMode( RECALCMODE_ONLOAD ); }
SetRecalcModeOnLoadOnce()154 inline void SetRecalcModeOnLoadOnce()
155 { SetMaskedRecalcMode( RECALCMODE_ONLOAD_ONCE ); }
SetRecalcModeForced()156 inline void SetRecalcModeForced()
157 { nMode |= RECALCMODE_FORCED; }
ClearRecalcModeForced()158 inline void ClearRecalcModeForced()
159 { nMode &= ~RECALCMODE_FORCED; }
SetRecalcModeOnRefMove()160 inline void SetRecalcModeOnRefMove()
161 { nMode |= RECALCMODE_ONREFMOVE; }
ClearRecalcModeOnRefMove()162 inline void ClearRecalcModeOnRefMove()
163 { nMode &= ~RECALCMODE_ONREFMOVE; }
IsRecalcModeNormal() const164 inline sal_Bool IsRecalcModeNormal() const
165 { return (nMode & RECALCMODE_NORMAL) != 0; }
IsRecalcModeAlways() const166 inline sal_Bool IsRecalcModeAlways() const
167 { return (nMode & RECALCMODE_ALWAYS) != 0; }
IsRecalcModeOnLoad() const168 inline sal_Bool IsRecalcModeOnLoad() const
169 { return (nMode & RECALCMODE_ONLOAD) != 0; }
IsRecalcModeOnLoadOnce() const170 inline sal_Bool IsRecalcModeOnLoadOnce() const
171 { return (nMode & RECALCMODE_ONLOAD_ONCE) != 0; }
IsRecalcModeForced() const172 inline sal_Bool IsRecalcModeForced() const
173 { return (nMode & RECALCMODE_FORCED) != 0; }
IsRecalcModeOnRefMove() const174 inline sal_Bool IsRecalcModeOnRefMove() const
175 { return (nMode & RECALCMODE_ONREFMOVE) != 0; }
176
177 /** Get OpCode of the most outer function */
178 inline OpCode GetOuterFuncOpCode();
179
180 /** Operators +,-,*,/,^,&,=,<>,<,>,<=,>=
181 with DoubleRef in Formula? */
182 sal_Bool HasMatrixDoubleRefOps();
183
184 virtual FormulaToken* AddOpCode(OpCode e);
185
186 /** Adds the single token to array.
187 Derived classes must overload it when they want to support derived classes from FormulaToken.
188 @return true when an error occurs
189 */
190 virtual bool AddFormulaToken(const com::sun::star::sheet::FormulaToken& _aToken, ExternalReferenceHelper* _pRef = NULL);
191
192 /** fill the array with the tokens from the sequence.
193 It calls AddFormulaToken for each token in the list.
194 @param _aSequence the token to add
195 @return true when an error occurs
196 */
197 bool Fill(const com::sun::star::uno::Sequence< com::sun::star::sheet::FormulaToken >& _aSequence, ExternalReferenceHelper* _pRef = NULL);
198
199 FormulaToken* AddToken( const FormulaToken& );
200 FormulaToken* AddString( const sal_Unicode* pStr );
201 FormulaToken* AddString( const String& rStr );
202 FormulaToken* AddDouble( double fVal );
203 FormulaToken* AddName( sal_uInt16 n );
204 FormulaToken* AddExternal( const sal_Unicode* pStr );
205 /** Xcl import may play dirty tricks with OpCode!=ocExternal.
206 Others don't use! */
207 FormulaToken* AddExternal( const String& rStr, OpCode eOp = ocExternal );
208 FormulaToken* AddBad( const sal_Unicode* pStr ); /// ocBad with String
209 FormulaToken* AddBad( const String& rStr ); /// ocBad with String
210
211 virtual FormulaToken* MergeArray( );
212
213 /// Assignment with references to FormulaToken entries (not copied!)
214 FormulaTokenArray& operator=( const FormulaTokenArray& );
215
216 /** Determines if this formula needs any changes to convert it to something
217 previous versions of OOo could consume (Plain Old Formula). */
218 bool NeedsPofRewrite(const MissingConvention & rConv);
219
220 /** Rewrites to Plain Old Formula, substituting missing parameters. The
221 FormulaTokenArray* returned is new'ed. */
222 FormulaTokenArray* RewriteMissingToPof(const MissingConvention & rConv);
223
224 /** Determines if this formula may be followed by a reference. */
225 bool MayReferenceFollow();
226 };
227
GetOuterFuncOpCode()228 inline OpCode FormulaTokenArray::GetOuterFuncOpCode()
229 {
230 if ( pRPN && nRPN )
231 return pRPN[nRPN-1]->GetOpCode();
232 return ocNone;
233 }
234
235 struct ImpTokenIterator
236 {
237 ImpTokenIterator* pNext;
238 const FormulaTokenArray* pArr;
239 short nPC;
240 short nStop;
241
242 DECL_FIXEDMEMPOOL_NEWDEL( ImpTokenIterator );
243 };
244
245 class FORMULA_DLLPUBLIC FormulaTokenIterator
246 {
247 ImpTokenIterator* pCur;
248
249 public:
250 FormulaTokenIterator( const FormulaTokenArray& );
251 ~FormulaTokenIterator();
252 void Reset();
253 const FormulaToken* First();
254 const FormulaToken* Next();
255 const FormulaToken* PeekNextOperator();
256 bool IsEndOfPath() const; /// if a jump or subroutine path is done
HasStacked() const257 bool HasStacked() const { return pCur->pNext != 0; }
GetPC() const258 short GetPC() const { return pCur->nPC; }
259
260 /** Jump or subroutine call.
261 Program counter values will be incremented before code is executed =>
262 positions are to be passed with -1 offset.
263 @param nStart
264 Start on code at position nStart+1 (yes, pass with offset -1)
265 @param nNext
266 After subroutine continue with instruction at position nNext+1
267 @param nStop
268 Stop before reaching code at position nStop. If not specified the
269 default is to either run the entire code, or to stop if an ocSep or
270 ocClose is encountered, which are only present in ocIf or ocChose
271 jumps.
272 */
273 void Jump( short nStart, short nNext, short nStop = SHRT_MAX );
274 void Push( const FormulaTokenArray* );
275 void Pop();
276
277 private:
278 const FormulaToken* GetNonEndOfPathToken( short nIdx ) const;
279 };
280 // =============================================================================
281 } // formula
282 // =============================================================================
283
284
285 #endif // FORMULA_TOKENARRAY_HXX
286
287