xref: /trunk/main/sc/inc/token.hxx (revision 38d50f7b)
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 SC_TOKEN_HXX
25 #define SC_TOKEN_HXX
26 
27 #include <memory>
28 #include <vector>
29 #include <boost/shared_ptr.hpp>
30 
31 #include "formula/opcode.hxx"
32 #include "refdata.hxx"
33 #include "scmatrix.hxx"
34 #include "formula/intruref.hxx"
35 #include <tools/mempool.hxx>
36 #include "scdllapi.h"
37 #include "formula/IFunctionDescription.hxx"
38 #include "formula/token.hxx"
39 
40 
41 class ScJumpMatrix;
42 class ScToken;
43 
44 typedef ::std::vector< ScComplexRefData > ScRefList;
45 typedef formula::SimpleIntrusiveReference< class ScToken > ScTokenRef;
46 
47 /**
48  * Another ref-counted token type using shared_ptr.  <b>Be extra careful
49  * not to mix use of this smart pointer type with ScTokenRef</b>, since
50  * mixing them might cause a premature object deletion because the same
51  * object may be ref-counted by two different smart pointer wrappers.
52  *
53  * You have been warned.
54  */
55 typedef ::boost::shared_ptr< ScToken > ScSharedTokenRef;
56 
57 class SC_DLLPUBLIC ScToken : public formula::FormulaToken
58 {
59 private:
60                                 // not implemented, prevent usage
61                                 ScToken();
62             ScToken&            operator=( const ScToken& );
63 
64 protected:
65 
ScToken(formula::StackVar eTypeP,OpCode e=ocPush)66     ScToken( formula::StackVar eTypeP,OpCode e = ocPush ) : formula::FormulaToken(eTypeP,e) {}
ScToken(const ScToken & r)67     ScToken( const ScToken& r ): formula::FormulaToken(r) {}
68 
69 public:
70 
71     virtual                     ~ScToken();
72 
73     /**
74         Dummy methods to avoid switches and casts where possible,
75         the real token classes have to overload the appropriate method[s].
76         The only methods valid anytime if not overloaded are:
77 
78         - GetByte() since this represents the count of parameters to a function
79           which of course is 0 on non-functions. formula::FormulaByteToken and ScExternal do
80           overload it.
81 
82         - HasForceArray() since also this is only used for operators and
83           functions and is 0 for other tokens.
84 
85         Any other non-overloaded method pops up an assertion.
86      */
87 
88     virtual const ScSingleRefData&    GetSingleRef() const;
89     virtual ScSingleRefData&      GetSingleRef();
90     virtual const ScComplexRefData& GetDoubleRef() const;
91     virtual ScComplexRefData&       GetDoubleRef();
92     virtual const ScSingleRefData&    GetSingleRef2() const;
93     virtual ScSingleRefData&      GetSingleRef2();
94     virtual void                CalcAbsIfRel( const ScAddress& );
95     virtual void                CalcRelFromAbs( const ScAddress& );
96     virtual const ScMatrix*     GetMatrix() const;
97     virtual ScMatrix*           GetMatrix();
98     virtual ScJumpMatrix*       GetJumpMatrix() const;
99     virtual const ScRefList*    GetRefList() const;
100     virtual       ScRefList*    GetRefList();
101 
102     virtual sal_Bool                TextEqual( const formula::FormulaToken& rToken ) const;
103     virtual sal_Bool                Is3DRef() const;    // reference with 3D flag set
104 
105     /** If rTok1 and rTok2 both are SingleRef or DoubleRef tokens, extend/merge
106         ranges as needed for ocRange.
107         @param rPos
108             The formula's position, used to calculate absolute positions from
109             relative references.
110         @param bReuseDoubleRef
111             If sal_True, a DoubleRef token is reused if passed as rTok1 or rTok2,
112             else a new DoubleRef token is created and returned.
113         @return
114             A reused or new'ed ScDoubleRefToken, or a NULL TokenRef if rTok1 or
115             rTok2 are not of sv(Single|Double)Ref
116      */
117     static  formula::FormulaTokenRef          ExtendRangeReference( formula::FormulaToken & rTok1, formula::FormulaToken & rTok2, const ScAddress & rPos, bool bReuseDoubleRef );
118 };
119 
120 class ScSingleRefToken : public ScToken
121 {
122 private:
123             ScSingleRefData       aSingleRef;
124 public:
ScSingleRefToken(const ScSingleRefData & r,OpCode e=ocPush)125                                 ScSingleRefToken( const ScSingleRefData& r, OpCode e = ocPush ) :
126                                     ScToken( formula::svSingleRef, e ), aSingleRef( r ) {}
ScSingleRefToken(const ScSingleRefToken & r)127                                 ScSingleRefToken( const ScSingleRefToken& r ) :
128                                     ScToken( r ), aSingleRef( r.aSingleRef ) {}
129     virtual const ScSingleRefData&    GetSingleRef() const;
130     virtual ScSingleRefData&      GetSingleRef();
131     virtual void                CalcAbsIfRel( const ScAddress& );
132     virtual void                CalcRelFromAbs( const ScAddress& );
133     virtual sal_Bool                operator==( const formula::FormulaToken& rToken ) const;
Clone() const134     virtual FormulaToken*       Clone() const { return new ScSingleRefToken(*this); }
135 
136     DECL_FIXEDMEMPOOL_NEWDEL( ScSingleRefToken );
137 };
138 
139 class ScDoubleRefToken : public ScToken
140 {
141 private:
142             ScComplexRefData        aDoubleRef;
143 public:
ScDoubleRefToken(const ScComplexRefData & r,OpCode e=ocPush)144                                 ScDoubleRefToken( const ScComplexRefData& r, OpCode e = ocPush  ) :
145                                     ScToken( formula::svDoubleRef, e ), aDoubleRef( r ) {}
ScDoubleRefToken(const ScSingleRefData & r,OpCode e=ocPush)146                                 ScDoubleRefToken( const ScSingleRefData& r, OpCode e = ocPush  ) :
147                                     ScToken( formula::svDoubleRef, e )
148                                 {
149                                     aDoubleRef.Ref1 = r;
150                                     aDoubleRef.Ref2 = r;
151                                 }
ScDoubleRefToken(const ScDoubleRefToken & r)152                                 ScDoubleRefToken( const ScDoubleRefToken& r ) :
153                                     ScToken( r ), aDoubleRef( r.aDoubleRef ) {}
154     virtual const ScSingleRefData&    GetSingleRef() const;
155     virtual ScSingleRefData&      GetSingleRef();
156     virtual const ScComplexRefData& GetDoubleRef() const;
157     virtual ScComplexRefData&       GetDoubleRef();
158     virtual const ScSingleRefData&    GetSingleRef2() const;
159     virtual ScSingleRefData&      GetSingleRef2();
160     virtual void                CalcAbsIfRel( const ScAddress& );
161     virtual void                CalcRelFromAbs( const ScAddress& );
162     virtual sal_Bool                operator==( const formula::FormulaToken& rToken ) const;
Clone() const163     virtual FormulaToken*       Clone() const { return new ScDoubleRefToken(*this); }
164 
165     DECL_FIXEDMEMPOOL_NEWDEL( ScDoubleRefToken );
166 };
167 
168 class ScMatrixToken : public ScToken
169 {
170 private:
171             ScMatrixRef         pMatrix;
172 public:
ScMatrixToken(ScMatrix * p)173                                 ScMatrixToken( ScMatrix* p ) :
174                                     ScToken( formula::svMatrix ), pMatrix( p ) {}
ScMatrixToken(const ScMatrixToken & r)175                                 ScMatrixToken( const ScMatrixToken& r ) :
176                                     ScToken( r ), pMatrix( r.pMatrix ) {}
177     virtual const ScMatrix*     GetMatrix() const;
178     virtual ScMatrix*           GetMatrix();
179     virtual sal_Bool                operator==( const formula::FormulaToken& rToken ) const;
Clone() const180     virtual FormulaToken*       Clone() const { return new ScMatrixToken(*this); }
181 };
182 
183 
184 class ScExternalSingleRefToken : public ScToken
185 {
186 private:
187     sal_uInt16                  mnFileId;
188     String                      maTabName;
189     ScSingleRefData             maSingleRef;
190 
191                                 ScExternalSingleRefToken(); // disabled
192 public:
193                                 ScExternalSingleRefToken( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& r );
194                                 ScExternalSingleRefToken( const ScExternalSingleRefToken& r );
195     virtual                     ~ScExternalSingleRefToken();
196 
197     virtual sal_uInt16              GetIndex() const;
198     virtual const String&           GetString() const;
199     virtual const ScSingleRefData&  GetSingleRef() const;
200     virtual ScSingleRefData&        GetSingleRef();
201     virtual void                    CalcAbsIfRel( const ScAddress& );
202     virtual void                    CalcRelFromAbs( const ScAddress& );
203     virtual sal_Bool                operator==( const formula::FormulaToken& rToken ) const;
Clone() const204     virtual FormulaToken*           Clone() const { return new ScExternalSingleRefToken(*this); }
205 };
206 
207 
208 class ScExternalDoubleRefToken : public ScToken
209 {
210 private:
211     sal_uInt16                  mnFileId;
212     String                      maTabName;  // name of the first sheet
213     ScComplexRefData            maDoubleRef;
214 
215                                 ScExternalDoubleRefToken(); // disabled
216 public:
217                                 ScExternalDoubleRefToken( sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& r );
218                                 ScExternalDoubleRefToken( const ScExternalDoubleRefToken& r );
219     explicit                    ScExternalDoubleRefToken( const ScExternalSingleRefToken& r );
220     virtual                     ~ScExternalDoubleRefToken();
221 
222     virtual sal_uInt16              GetIndex() const;
223     virtual const String&           GetString() const;
224     virtual const ScSingleRefData&  GetSingleRef() const;
225     virtual ScSingleRefData&        GetSingleRef();
226     virtual const ScSingleRefData&  GetSingleRef2() const;
227     virtual ScSingleRefData&        GetSingleRef2();
228     virtual const ScComplexRefData& GetDoubleRef() const;
229     virtual ScComplexRefData&       GetDoubleRef();
230     virtual void                    CalcAbsIfRel( const ScAddress& );
231     virtual void                    CalcRelFromAbs( const ScAddress& );
232     virtual sal_Bool                operator==( const formula::FormulaToken& rToken ) const;
Clone() const233     virtual FormulaToken*           Clone() const { return new ScExternalDoubleRefToken(*this); }
234 };
235 
236 
237 class ScExternalNameToken : public ScToken
238 {
239 private:
240     sal_uInt16                  mnFileId;
241     String                      maName;
242 private:
243                                 ScExternalNameToken(); // disabled
244 public:
245                                 ScExternalNameToken( sal_uInt16 nFileId, const String& rName );
246                                 ScExternalNameToken( const ScExternalNameToken& r );
247     virtual                     ~ScExternalNameToken();
248     virtual sal_uInt16              GetIndex() const;
249     virtual const String&       GetString() const;
250     virtual sal_Bool                operator==( const formula::FormulaToken& rToken ) const;
Clone() const251     virtual FormulaToken*       Clone() const { return new ScExternalNameToken(*this); }
252 };
253 
254 
255 // Only created from within the interpreter, no conversion from ScRawToken,
256 // never added to ScTokenArray!
257 class ScJumpMatrixToken : public ScToken
258 {
259 private:
260             ScJumpMatrix*       pJumpMatrix;
261 public:
ScJumpMatrixToken(ScJumpMatrix * p)262                                 ScJumpMatrixToken( ScJumpMatrix* p ) :
263                                     ScToken( formula::svJumpMatrix ), pJumpMatrix( p ) {}
ScJumpMatrixToken(const ScJumpMatrixToken & r)264                                 ScJumpMatrixToken( const ScJumpMatrixToken& r ) :
265                                     ScToken( r ), pJumpMatrix( r.pJumpMatrix ) {}
266     virtual                     ~ScJumpMatrixToken();
267     virtual ScJumpMatrix*       GetJumpMatrix() const;
268     virtual sal_Bool                operator==( const formula::FormulaToken& rToken ) const;
Clone() const269     virtual FormulaToken*       Clone() const { return new ScJumpMatrixToken(*this); }
270 };
271 
272 
273 // Only created from within the interpreter, no conversion from ScRawToken,
274 // never added to ScTokenArray!
275 class ScRefListToken : public ScToken
276 {
277 private:
278             ScRefList           aRefList;
279 public:
ScRefListToken()280                                 ScRefListToken() :
281                                     ScToken( formula::svRefList ) {}
ScRefListToken(const ScRefListToken & r)282                                 ScRefListToken( const ScRefListToken & r ) :
283                                     ScToken( r ), aRefList( r.aRefList ) {}
284     virtual void                CalcAbsIfRel( const ScAddress& );
285     virtual void                CalcRelFromAbs( const ScAddress& );
286     virtual const ScRefList*    GetRefList() const;
287     virtual       ScRefList*    GetRefList();
288     virtual sal_Bool                operator==( const formula::FormulaToken& rToken ) const;
Clone() const289     virtual FormulaToken*       Clone() const { return new ScRefListToken(*this); }
290 };
291 
292 
293 class SC_DLLPUBLIC ScEmptyCellToken : public ScToken
294 {
295             bool                bInherited          :1;
296             bool                bDisplayedAsString  :1;
297 public:
ScEmptyCellToken(bool bInheritedP,bool bDisplayAsString)298     explicit                    ScEmptyCellToken( bool bInheritedP, bool bDisplayAsString ) :
299                                     ScToken( formula::svEmptyCell ),
300                                     bInherited( bInheritedP ),
301                                     bDisplayedAsString( bDisplayAsString ) {}
ScEmptyCellToken(const ScEmptyCellToken & r)302                                 ScEmptyCellToken( const ScEmptyCellToken& r ) :
303                                     ScToken( r ),
304                                     bInherited( r.bInherited ),
305                                     bDisplayedAsString( r.bDisplayedAsString ) {}
IsInherited() const306             bool                IsInherited() const { return bInherited; }
IsDisplayedAsString() const307             bool                IsDisplayedAsString() const { return bDisplayedAsString; }
308     virtual double              GetDouble() const;
309     virtual const String &      GetString() const;
310     virtual sal_Bool                operator==( const formula::FormulaToken& rToken ) const;
Clone() const311     virtual FormulaToken*       Clone() const { return new ScEmptyCellToken(*this); }
312 };
313 
314 
315 /**  Transports the result from the interpreter to the formula cell. */
316 class SC_DLLPUBLIC ScMatrixCellResultToken : public ScToken
317 {
318     // No non-const access implemented, silence down unxsols4 complaining about
319     // the public GetMatrix() hiding the one from ScToken.
320     virtual ScMatrix*           GetMatrix();
321 
322 protected:
323             ScConstMatrixRef    xMatrix;
324             formula::FormulaConstTokenRef     xUpperLeft;
325 public:
ScMatrixCellResultToken(ScMatrix * pMat,formula::FormulaToken * pUL)326                                 ScMatrixCellResultToken( ScMatrix* pMat, formula::FormulaToken* pUL ) :
327                                     ScToken( formula::svMatrixCell ),
328                                     xMatrix( pMat), xUpperLeft( pUL) {}
ScMatrixCellResultToken(const ScMatrixCellResultToken & r)329                                 ScMatrixCellResultToken( const ScMatrixCellResultToken& r ) :
330                                     ScToken( r ), xMatrix( r.xMatrix ),
331                                     xUpperLeft( r.xUpperLeft ) {}
332     virtual double              GetDouble() const;
333     virtual const String &      GetString() const;
334     virtual const ScMatrix*     GetMatrix() const;
335     virtual sal_Bool                operator==( const formula::FormulaToken& rToken ) const;
Clone() const336     virtual FormulaToken*       Clone() const { return new ScMatrixCellResultToken(*this); }
GetUpperLeftType() const337     formula::StackVar           GetUpperLeftType() const
338                                     {
339                                         return xUpperLeft ?
340                                             xUpperLeft->GetType() :
341                                             static_cast<formula::StackVar>(formula::svUnknown);
342                                     }
GetUpperLeftToken() const343     inline formula::FormulaConstTokenRef     GetUpperLeftToken() const   { return xUpperLeft; }
Assign(const ScMatrixCellResultToken & r)344             void                Assign( const ScMatrixCellResultToken & r )
345                                     {
346                                         xMatrix = r.xMatrix;
347                                         xUpperLeft = r.xUpperLeft;
348                                     }
349 };
350 
351 
352 /** Stores the matrix result at the formula cell, additionally the range the
353     matrix formula occupies. */
354 class SC_DLLPUBLIC ScMatrixFormulaCellToken : public ScMatrixCellResultToken
355 {
356 private:
357             SCROW               nRows;
358             SCCOL               nCols;
359 public:
ScMatrixFormulaCellToken(SCCOL nC,SCROW nR)360                                 ScMatrixFormulaCellToken( SCCOL nC, SCROW nR ) :
361                                     ScMatrixCellResultToken( NULL, NULL ),
362                                     nRows( nR ), nCols( nC ) {}
ScMatrixFormulaCellToken(const ScMatrixFormulaCellToken & r)363                                 ScMatrixFormulaCellToken( const ScMatrixFormulaCellToken& r ) :
364                                     ScMatrixCellResultToken( r ),
365                                     nRows( r.nRows ), nCols( r.nCols )
366                                     {
367                                         // xUpperLeft is modifiable through
368                                         // SetUpperLeftDouble(), so clone it.
369                                         if (xUpperLeft)
370                                             xUpperLeft = xUpperLeft->Clone();
371                                     }
372     virtual sal_Bool                operator==( const formula::FormulaToken& rToken ) const;
Clone() const373     virtual FormulaToken*       Clone() const { return new ScMatrixFormulaCellToken(*this); }
SetMatColsRows(SCCOL nC,SCROW nR)374             void                SetMatColsRows( SCCOL nC, SCROW nR )
375                                     {
376                                         nRows = nR;
377                                         nCols = nC;
378                                     }
GetMatColsRows(SCCOL & nC,SCROW & nR) const379             void                GetMatColsRows( SCCOL & nC, SCROW & nR ) const
380                                     {
381                                         nR = nRows;
382                                         nC = nCols;
383                                     }
GetMatCols() const384             SCCOL               GetMatCols() const  { return nCols; }
GetMatRows() const385             SCROW               GetMatRows() const  { return nRows; }
386 
387                                 /** Assign matrix result, keep matrix formula
388                                     dimension. */
Assign(const ScMatrixCellResultToken & r)389             void                Assign( const ScMatrixCellResultToken & r )
390                                     {
391                                         ScMatrixCellResultToken::Assign( r);
392                                     }
393 
394                                 /** Assign any result, keep matrix formula
395                                     dimension. If token is of type
396                                     ScMatrixCellResultToken uses the
397                                     appropriate Assign() call, other tokens
398                                     are assigned to xUpperLeft and xMatrix will
399                                     be assigned NULL. */
400             void                Assign( const formula::FormulaToken & r );
401 
402                                 /** Modify xUpperLeft if formula::svDouble, or create
403                                     new formula::FormulaDoubleToken if not set yet. Does
404                                     nothing if xUpperLeft is of different type! */
405             void                SetUpperLeftDouble( double f);
406 
407                                 /** Reset matrix and upper left, keep matrix
408                                     formula dimension. */
ResetResult()409             void                ResetResult()
410                                     {
411                                         xMatrix = NULL;
412                                         xUpperLeft = NULL;
413                                     }
414 };
415 
416 
417 class SC_DLLPUBLIC ScHybridCellToken : public ScToken
418 {
419 private:
420             double              fDouble;
421             String              aString;
422             String              aFormula;
423 public:
ScHybridCellToken(double f,const String & rStr,const String & rFormula)424                                 ScHybridCellToken( double f,
425                                         const String & rStr,
426                                         const String & rFormula ) :
427                                     ScToken( formula::svHybridCell ),
428                                     fDouble( f ), aString( rStr ),
429                                     aFormula( rFormula ) {}
ScHybridCellToken(const ScHybridCellToken & r)430                                 ScHybridCellToken( const ScHybridCellToken& r ) :
431                                     ScToken( r ), fDouble( r.fDouble),
432                                     aString( r.aString), aFormula( r.aFormula) {}
GetFormula() const433             const String &      GetFormula() const  { return aFormula; }
434     virtual double              GetDouble() const;
435     virtual const String &      GetString() const;
436     virtual sal_Bool                operator==( const formula::FormulaToken& rToken ) const;
Clone() const437     virtual FormulaToken*       Clone() const { return new ScHybridCellToken(*this); }
438 };
439 
440 
441 // Simplify argument passing to RefUpdate methods with ScSingleRefToken or
442 // ScDoubleRefToken
443 class SingleDoubleRefModifier
444 {
445     ScComplexRefData    aDub;
446     ScSingleRefData*  pS;
447     ScComplexRefData*   pD;
448 
449                 // not implemented, prevent usage
450                 SingleDoubleRefModifier( const SingleDoubleRefModifier& );
451         SingleDoubleRefModifier& operator=( const SingleDoubleRefModifier& );
452 
453 public:
SingleDoubleRefModifier(ScToken & rT)454                 SingleDoubleRefModifier( ScToken& rT )
455                     {
456                         if ( rT.GetType() == formula::svSingleRef )
457                         {
458                             pS = &rT.GetSingleRef();
459                             aDub.Ref1 = aDub.Ref2 = *pS;
460                             pD = &aDub;
461                         }
462                         else
463                         {
464                             pS = 0;
465                             pD = &rT.GetDoubleRef();
466                         }
467                     }
SingleDoubleRefModifier(ScSingleRefData & rS)468                 SingleDoubleRefModifier( ScSingleRefData& rS )
469                     {
470                         pS = &rS;
471                         aDub.Ref1 = aDub.Ref2 = *pS;
472                         pD = &aDub;
473                     }
~SingleDoubleRefModifier()474                 ~SingleDoubleRefModifier()
475                     {
476                         if ( pS )
477                             *pS = (*pD).Ref1;
478                     }
Ref()479     inline  ScComplexRefData& Ref() { return *pD; }
480 };
481 
482 class SingleDoubleRefProvider
483 {
484 public:
485 
486     const ScSingleRefData&    Ref1;
487     const ScSingleRefData&    Ref2;
488 
SingleDoubleRefProvider(const ScToken & r)489                 SingleDoubleRefProvider( const ScToken& r )
490                         : Ref1( r.GetSingleRef() ),
491                         Ref2( r.GetType() == formula::svDoubleRef ?
492                         r.GetDoubleRef().Ref2 : Ref1 )
493                     {}
SingleDoubleRefProvider(const ScSingleRefData & r)494                 SingleDoubleRefProvider( const ScSingleRefData& r )
495                         : Ref1( r ), Ref2( r )
496                     {}
SingleDoubleRefProvider(const ScComplexRefData & r)497                 SingleDoubleRefProvider( const ScComplexRefData& r )
498                         : Ref1( r.Ref1 ), Ref2( r.Ref2 )
499                     {}
~SingleDoubleRefProvider()500                 ~SingleDoubleRefProvider()
501                     {}
502 };
503 
504 #endif
505