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