xref: /trunk/main/formula/inc/formula/tokenarray.hxx (revision 5116778e)
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