Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #ifndef FORMULA_TOKENARRAY_HXX
21 : #define FORMULA_TOKENARRAY_HXX
22 :
23 : #include <limits.h>
24 : #include "formula/token.hxx"
25 : #include "formula/ExternalReferenceHelper.hxx"
26 : #include <tools/solar.h>
27 : #include <com/sun/star/sheet/FormulaToken.hpp>
28 :
29 : namespace formula
30 : {
31 :
32 : // RecalcMode access only via TokenArray SetRecalcMode / IsRecalcMode...
33 :
34 : typedef sal_uInt8 ScRecalcMode;
35 : // Only one of the exclusive bits can be set,
36 : // handled by TokenArray SetRecalcMode... methods
37 : #define RECALCMODE_NORMAL 0x01 // exclusive
38 : #define RECALCMODE_ALWAYS 0x02 // exclusive, always
39 : #define RECALCMODE_ONLOAD 0x04 // exclusive, always after load
40 : #define RECALCMODE_ONLOAD_ONCE 0x08 // exclusive, once after load
41 : #define RECALCMODE_FORCED 0x10 // combined, also if cell isn't visible
42 : #define RECALCMODE_ONREFMOVE 0x20 // combined, if reference was moved
43 : #define RECALCMODE_EMASK 0x0F // mask of exclusive bits
44 : // If new bits are to be defined, AddRecalcMode has to be adjusted!
45 :
46 : class FormulaMissingContext;
47 :
48 : class FORMULA_DLLPUBLIC MissingConvention
49 : {
50 : bool mbODFF; /// TRUE: ODFF, FALSE: PODF
51 : public:
52 209 : explicit MissingConvention( bool bODFF ) : mbODFF(bODFF) {}
53 : // Implementation and usage only in token.cxx
54 : inline bool isRewriteNeeded( OpCode eOp ) const;
55 0 : inline bool isODFF() const { return mbODFF; }
56 : };
57 :
58 : class FORMULA_DLLPUBLIC FormulaTokenArray
59 : {
60 : friend class FormulaCompiler;
61 : friend class FormulaTokenIterator;
62 : friend class FormulaMissingContext;
63 :
64 : protected:
65 : FormulaToken** pCode; // Token code array
66 : FormulaToken** pRPN; // RPN array
67 : sal_uInt16 nLen; // Length of token array
68 : sal_uInt16 nRPN; // Length of RPN array
69 : sal_uInt16 nIndex; // Current step index
70 : sal_uInt16 nError; // Error code
71 : short nRefs; // Count of cell references
72 : ScRecalcMode nMode; // Flags to indicate when to recalc this code
73 : bool bHyperLink; // If HYPERLINK() occurs in the formula.
74 :
75 : protected:
76 : void Assign( const FormulaTokenArray& );
77 :
78 : /// Also used by the compiler. The token MUST had been allocated with new!
79 : FormulaToken* Add( FormulaToken* );
80 269 : inline void SetCombinedBitsRecalcMode( ScRecalcMode nBits )
81 269 : { nMode |= (nBits & ~RECALCMODE_EMASK); }
82 69 : inline ScRecalcMode GetCombinedBitsRecalcMode() const
83 69 : { return nMode & ~RECALCMODE_EMASK; }
84 : /** Exclusive bits already set in nMode are
85 : zero'ed, nBits may contain combined bits, but
86 : only one exclusive bit may be set! */
87 69 : inline void SetMaskedRecalcMode( ScRecalcMode nBits )
88 69 : { nMode = GetCombinedBitsRecalcMode() | nBits; }
89 :
90 : public:
91 : FormulaTokenArray();
92 : /// Assignment with references to FormulaToken entries (not copied!)
93 : FormulaTokenArray( const FormulaTokenArray& );
94 : virtual ~FormulaTokenArray();
95 : FormulaTokenArray* Clone() const; /// True copy!
96 :
97 : void Clear();
98 : void DelRPN();
99 918 : FormulaToken* First() { nIndex = 0; return Next(); }
100 : FormulaToken* Next();
101 : FormulaToken* FirstNoSpaces() { nIndex = 0; return NextNoSpaces(); }
102 : FormulaToken* NextNoSpaces();
103 : FormulaToken* GetNextName();
104 : FormulaToken* GetNextReference();
105 : FormulaToken* GetNextReferenceRPN();
106 : FormulaToken* GetNextReferenceOrName();
107 : FormulaToken* GetNextColRowName();
108 : FormulaToken* GetNextOpCodeRPN( OpCode );
109 : /// Peek at nIdx-1 if not out of bounds, decrements nIdx if successful. Returns NULL if not.
110 : FormulaToken* PeekPrev( sal_uInt16 & nIdx );
111 : FormulaToken* PeekNext();
112 : FormulaToken* PeekPrevNoSpaces(); /// Only after Reset/First/Next/Last/Prev!
113 : FormulaToken* PeekNextNoSpaces(); /// Only after Reset/First/Next/Last/Prev!
114 193 : FormulaToken* FirstRPN() { nIndex = 0; return NextRPN(); }
115 : FormulaToken* NextRPN();
116 0 : FormulaToken* LastRPN() { nIndex = nRPN; return PrevRPN(); }
117 : FormulaToken* PrevRPN();
118 :
119 : bool HasExternalRef() const;
120 : bool HasOpCode( OpCode ) const;
121 : bool HasOpCodeRPN( OpCode ) const;
122 : /// Token of type svIndex or opcode ocColRowName
123 : bool HasNameOrColRowName() const;
124 :
125 556 : FormulaToken** GetArray() const { return pCode; }
126 3412 : FormulaToken** GetCode() const { return pRPN; }
127 14453 : sal_uInt16 GetLen() const { return nLen; }
128 27007 : sal_uInt16 GetCodeLen() const { return nRPN; }
129 14618 : void Reset() { nIndex = 0; }
130 130183 : sal_uInt16 GetCodeError() const { return nError; }
131 437 : void SetCodeError( sal_uInt16 n ) { nError = n; }
132 : short GetRefs() const { return nRefs; }
133 34 : void IncrementRefs() { ++nRefs; }
134 405 : void SetHyperLink( bool bVal ) { bHyperLink = bVal; }
135 206 : bool IsHyperLink() const { return bHyperLink; }
136 :
137 204 : inline ScRecalcMode GetRecalcMode() const { return nMode; }
138 : /** Bits aren't set directly but validated and
139 : maybe handled according to priority if more
140 : than one exclusive bit was set. */
141 : void AddRecalcMode( ScRecalcMode nBits );
142 :
143 20892 : inline void ClearRecalcMode() { nMode = RECALCMODE_NORMAL; }
144 0 : inline void SetExclusiveRecalcModeNormal()
145 0 : { SetMaskedRecalcMode( RECALCMODE_NORMAL ); }
146 24 : inline void SetExclusiveRecalcModeAlways()
147 24 : { SetMaskedRecalcMode( RECALCMODE_ALWAYS ); }
148 45 : inline void SetExclusiveRecalcModeOnLoad()
149 45 : { SetMaskedRecalcMode( RECALCMODE_ONLOAD ); }
150 0 : inline void SetExclusiveRecalcModeOnLoadOnce()
151 0 : { SetMaskedRecalcMode( RECALCMODE_ONLOAD_ONCE ); }
152 18 : inline void SetRecalcModeForced()
153 18 : { nMode |= RECALCMODE_FORCED; }
154 : inline void ClearRecalcModeForced()
155 : { nMode &= ~RECALCMODE_FORCED; }
156 57 : inline void SetRecalcModeOnRefMove()
157 57 : { nMode |= RECALCMODE_ONREFMOVE; }
158 : inline void ClearRecalcModeOnRefMove()
159 : { nMode &= ~RECALCMODE_ONREFMOVE; }
160 2695 : inline bool IsRecalcModeNormal() const
161 2695 : { return (nMode & RECALCMODE_NORMAL) != 0; }
162 22081 : inline bool IsRecalcModeAlways() const
163 22081 : { return (nMode & RECALCMODE_ALWAYS) != 0; }
164 377 : inline bool IsRecalcModeOnLoad() const
165 377 : { return (nMode & RECALCMODE_ONLOAD) != 0; }
166 359 : inline bool IsRecalcModeOnLoadOnce() const
167 359 : { return (nMode & RECALCMODE_ONLOAD_ONCE) != 0; }
168 11805 : inline bool IsRecalcModeForced() const
169 11805 : { return (nMode & RECALCMODE_FORCED) != 0; }
170 51 : inline bool IsRecalcModeOnRefMove() const
171 51 : { return (nMode & RECALCMODE_ONREFMOVE) != 0; }
172 :
173 : /** Get OpCode of the most outer function */
174 : inline OpCode GetOuterFuncOpCode();
175 :
176 : /** Operators +,-,*,/,^,&,=,<>,<,>,<=,>=
177 : with DoubleRef in Formula? */
178 : bool HasMatrixDoubleRefOps();
179 :
180 : virtual FormulaToken* AddOpCode(OpCode e);
181 :
182 : /** Adds the single token to array.
183 : Derived classes must overload it when they want to support derived classes from FormulaToken.
184 : @return true when an error occurs
185 : */
186 : virtual bool AddFormulaToken(const com::sun::star::sheet::FormulaToken& _aToken, ExternalReferenceHelper* _pRef = NULL);
187 :
188 : /** fill the array with the tokens from the sequence.
189 : It calls AddFormulaToken for each token in the list.
190 : @param _aSequence the token to add
191 : @return true when an error occurs
192 : */
193 : bool Fill(const com::sun::star::uno::Sequence< com::sun::star::sheet::FormulaToken >& _aSequence, ExternalReferenceHelper* _pRef = NULL);
194 :
195 : /**
196 : * Do some checking based on the individual tokens. For now, we use this
197 : * only to check whether we can vectorize the token array.
198 : */
199 : virtual void CheckToken( const FormulaToken& t );
200 :
201 : FormulaToken* AddToken( const FormulaToken& );
202 : FormulaToken* AddString( const sal_Unicode* pStr );
203 : FormulaToken* AddString( const String& rStr );
204 : FormulaToken* AddDouble( double fVal );
205 : FormulaToken* AddExternal( const sal_Unicode* pStr );
206 : /** Xcl import may play dirty tricks with OpCode!=ocExternal.
207 : Others don't use! */
208 : FormulaToken* AddExternal( const String& rStr, OpCode eOp = ocExternal );
209 : FormulaToken* AddBad( const String& rStr ); /// ocBad with String
210 : FormulaToken* AddStringXML( const String& rStr ); /// ocStringXML with String, temporary during import
211 :
212 : virtual FormulaToken* MergeArray( );
213 :
214 : /// Assignment with references to FormulaToken entries (not copied!)
215 : FormulaTokenArray& operator=( const FormulaTokenArray& );
216 :
217 : /** Determines if this formula needs any changes to convert it to something
218 : previous versions of OOo could consume (Plain Old Formula). */
219 : bool NeedsPofRewrite(const MissingConvention & rConv);
220 :
221 : /** Rewrites to Plain Old Formula, substituting missing parameters. The
222 : FormulaTokenArray* returned is new'ed. */
223 : FormulaTokenArray* RewriteMissingToPof(const MissingConvention & rConv);
224 :
225 : /** Determines if this formula may be followed by a reference. */
226 : bool MayReferenceFollow();
227 : };
228 :
229 0 : inline OpCode FormulaTokenArray::GetOuterFuncOpCode()
230 : {
231 0 : if ( pRPN && nRPN )
232 0 : return pRPN[nRPN-1]->GetOpCode();
233 0 : return ocNone;
234 : }
235 :
236 : struct ImpTokenIterator
237 : {
238 : ImpTokenIterator* pNext;
239 : const FormulaTokenArray* pArr;
240 : short nPC;
241 : short nStop;
242 :
243 9310 : DECL_FIXEDMEMPOOL_NEWDEL( ImpTokenIterator );
244 : };
245 :
246 : class FORMULA_DLLPUBLIC FormulaTokenIterator
247 : {
248 : ImpTokenIterator* pCur;
249 :
250 : public:
251 : FormulaTokenIterator( const FormulaTokenArray& );
252 : ~FormulaTokenIterator();
253 : void Reset();
254 : const FormulaToken* Next();
255 : const FormulaToken* PeekNextOperator();
256 : bool IsEndOfPath() const; /// if a jump or subroutine path is done
257 1 : bool HasStacked() const { return pCur->pNext != 0; }
258 0 : 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 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|