/src/libreoffice/include/formula/tokenarray.hxx
Line | Count | Source |
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 | | #pragma once |
21 | | |
22 | | #include <climits> |
23 | | #include <memory> |
24 | | #include <ostream> |
25 | | #include <type_traits> |
26 | | #include <unordered_set> |
27 | | #include <vector> |
28 | | |
29 | | #include <formula/ExternalReferenceHelper.hxx> |
30 | | #include <formula/formuladllapi.h> |
31 | | #include <formula/opcode.hxx> |
32 | | #include <formula/token.hxx> |
33 | | #include <o3tl/typed_flags_set.hxx> |
34 | | #include <rtl/ustring.hxx> |
35 | | #include <sal/types.h> |
36 | | |
37 | | namespace com::sun::star { |
38 | | namespace sheet { struct FormulaToken; } |
39 | | } |
40 | | |
41 | | namespace com::sun::star::uno { template <typename > class Sequence; } |
42 | | namespace formula { class FormulaTokenArray; } |
43 | | |
44 | | namespace svl { |
45 | | |
46 | | class SharedString; |
47 | | class SharedStringPool; |
48 | | |
49 | | } |
50 | | |
51 | | // RecalcMode access only via TokenArray SetExclusiveRecalcMode...() / |
52 | | // IsRecalcMode...() |
53 | | |
54 | | // Only one of the exclusive bits can be set and one must be set, |
55 | | // handled by TokenArray SetExclusiveRecalcMode...() methods. |
56 | | // Exclusive bits are ordered by priority, AddRecalcMode() relies on that. |
57 | | enum class ScRecalcMode : sal_uInt8 |
58 | | { |
59 | | ALWAYS = 0x01, // exclusive, always |
60 | | ONLOAD_MUST = 0x02, // exclusive, always after load |
61 | | ONLOAD_ONCE = 0x04, // exclusive, once after load, import filter |
62 | | ONLOAD_LENIENT = 0x08, // exclusive, lenient after load (eg. macros not always, aliens, ...) |
63 | | NORMAL = 0x10, // exclusive |
64 | | FORCED = 0x20, // combined, also if cell isn't visible, for macros with side effects |
65 | | ONREFMOVE = 0x40, // combined, if reference was moved |
66 | | EMask = ALWAYS | ONLOAD_MUST | ONLOAD_LENIENT | ONLOAD_ONCE | NORMAL // mask of exclusive bits |
67 | | }; |
68 | | namespace o3tl |
69 | | { |
70 | | template<> struct typed_flags<ScRecalcMode> : is_typed_flags<ScRecalcMode, 0x7f> {}; |
71 | | } |
72 | | |
73 | | namespace formula |
74 | | { |
75 | | |
76 | | class FORMULA_DLLPUBLIC MissingConvention |
77 | | { |
78 | | public: |
79 | | enum Convention |
80 | | { |
81 | | FORMULA_MISSING_CONVENTION_PODF, |
82 | | FORMULA_MISSING_CONVENTION_ODFF, |
83 | | FORMULA_MISSING_CONVENTION_OOXML |
84 | | }; |
85 | 38.4k | explicit MissingConvention( Convention eConvention ) : meConvention(eConvention) {} |
86 | 27.1k | bool isPODF() const { return meConvention == FORMULA_MISSING_CONVENTION_PODF; } |
87 | 25.7k | bool isODFF() const { return meConvention == FORMULA_MISSING_CONVENTION_ODFF; } |
88 | 24.4k | bool isOOXML() const { return meConvention == FORMULA_MISSING_CONVENTION_OOXML; } |
89 | 63.5k | Convention getConvention() const { return meConvention; } |
90 | | private: |
91 | | Convention meConvention; |
92 | | }; |
93 | | |
94 | | class FORMULA_DLLPUBLIC MissingConventionODF : public MissingConvention |
95 | | { |
96 | | public: |
97 | | explicit MissingConventionODF( bool bODFF ) : |
98 | 38.4k | MissingConvention( bODFF ? |
99 | 32.6k | MissingConvention::FORMULA_MISSING_CONVENTION_ODFF : |
100 | 38.4k | MissingConvention::FORMULA_MISSING_CONVENTION_PODF) |
101 | 38.4k | { |
102 | 38.4k | } |
103 | | // Implementation and usage only in token.cxx |
104 | | inline bool isRewriteNeeded( OpCode eOp ) const; |
105 | | }; |
106 | | |
107 | | class FORMULA_DLLPUBLIC MissingConventionOOXML : public MissingConvention |
108 | | { |
109 | | public: |
110 | 0 | explicit MissingConventionOOXML() : MissingConvention( MissingConvention::FORMULA_MISSING_CONVENTION_OOXML) {} |
111 | | // Implementation and usage only in token.cxx |
112 | | static inline bool isRewriteNeeded( OpCode eOp ); |
113 | | }; |
114 | | |
115 | | typedef std::unordered_set<OpCode, std::hash<std::underlying_type<OpCode>::type> > unordered_opcode_set; |
116 | | |
117 | | class FORMULA_DLLPUBLIC FormulaTokenArrayStandardRange |
118 | | { |
119 | | private: |
120 | | FormulaToken** mpBegin; |
121 | | FormulaToken** mpEnd; |
122 | | |
123 | | public: |
124 | | FormulaTokenArrayStandardRange(FormulaToken** pBegin, sal_uInt16 nSize) : |
125 | 15.0M | mpBegin(pBegin), |
126 | 15.0M | mpEnd(pBegin + nSize) |
127 | 15.0M | { |
128 | 15.0M | } |
129 | | |
130 | | FormulaToken** begin() const |
131 | 14.9M | { |
132 | 14.9M | return mpBegin; |
133 | 14.9M | } |
134 | | |
135 | | FormulaToken** end() const |
136 | 15.0M | { |
137 | 15.0M | return mpEnd; |
138 | 15.0M | } |
139 | | }; |
140 | | |
141 | | class FORMULA_DLLPUBLIC FormulaTokenArrayReferencesIterator |
142 | | { |
143 | | private: |
144 | | FormulaToken** maIter; |
145 | | FormulaToken** maEnd; |
146 | | |
147 | | void nextReference() |
148 | 108k | { |
149 | 127k | while (maIter != maEnd) |
150 | 72.0k | { |
151 | 72.0k | switch ((*maIter)->GetType()) |
152 | 72.0k | { |
153 | 51.9k | case svSingleRef: |
154 | 53.3k | case svDoubleRef: |
155 | 53.3k | case svExternalSingleRef: |
156 | 53.3k | case svExternalDoubleRef: |
157 | 53.3k | return; |
158 | 18.6k | default: |
159 | 18.6k | ++maIter; |
160 | 72.0k | } |
161 | 72.0k | } |
162 | 108k | } |
163 | | |
164 | | enum class Dummy { Flag }; |
165 | | |
166 | | FormulaTokenArrayReferencesIterator(const FormulaTokenArrayStandardRange& rRange, Dummy) : |
167 | 55.0k | maIter(rRange.end()), |
168 | 55.0k | maEnd(rRange.end()) |
169 | 55.0k | { |
170 | 55.0k | } |
171 | | |
172 | | public: |
173 | | FormulaTokenArrayReferencesIterator(const FormulaTokenArrayStandardRange& rRange) : |
174 | 55.0k | maIter(rRange.begin()), |
175 | 55.0k | maEnd(rRange.end()) |
176 | 55.0k | { |
177 | 55.0k | nextReference(); |
178 | 55.0k | } |
179 | | |
180 | | FormulaTokenArrayReferencesIterator operator++(int) |
181 | 0 | { |
182 | 0 | FormulaTokenArrayReferencesIterator result(*this); |
183 | 0 | operator++(); |
184 | 0 | return result; |
185 | 0 | } |
186 | | |
187 | | FormulaTokenArrayReferencesIterator const & operator++() |
188 | 53.3k | { |
189 | 53.3k | assert(maIter != maEnd); |
190 | 53.3k | ++maIter; |
191 | 53.3k | nextReference(); |
192 | 53.3k | return *this; |
193 | 53.3k | } |
194 | | |
195 | | FormulaToken* operator*() const |
196 | 53.3k | { |
197 | 53.3k | return *maIter; |
198 | 53.3k | } |
199 | | |
200 | | bool operator==(const FormulaTokenArrayReferencesIterator& rhs) const |
201 | 108k | { |
202 | 108k | return maIter == rhs.maIter; |
203 | 108k | } |
204 | | |
205 | | bool operator!=(const FormulaTokenArrayReferencesIterator& rhs) const |
206 | 108k | { |
207 | 108k | return !operator==(rhs); |
208 | 108k | } |
209 | | |
210 | | static FormulaTokenArrayReferencesIterator endOf(const FormulaTokenArrayStandardRange& rRange) |
211 | 55.0k | { |
212 | 55.0k | return FormulaTokenArrayReferencesIterator(rRange, Dummy::Flag); |
213 | 55.0k | } |
214 | | }; |
215 | | |
216 | | class FORMULA_DLLPUBLIC FormulaTokenArrayReferencesRange |
217 | | { |
218 | | private: |
219 | | const FormulaTokenArray& mrFTA; |
220 | | |
221 | | public: |
222 | | FormulaTokenArrayReferencesRange(const FormulaTokenArray& rFTA) : |
223 | 55.0k | mrFTA(rFTA) |
224 | 55.0k | { |
225 | 55.0k | } |
226 | | |
227 | | FormulaTokenArrayReferencesIterator begin(); |
228 | | |
229 | | FormulaTokenArrayReferencesIterator end(); |
230 | | }; |
231 | | |
232 | | class FORMULA_DLLPUBLIC FormulaTokenArray |
233 | | { |
234 | | protected: |
235 | | std::unique_ptr<FormulaToken*[]> pCode; // Token code array |
236 | | std::unique_ptr<FormulaToken*[]> pRPN; // RPN array |
237 | | sal_uInt16 nLen; // Length of token array |
238 | | sal_uInt16 nRPN; // Length of RPN array |
239 | | FormulaError nError; // Error code |
240 | | ScRecalcMode nMode; // Flags to indicate when to recalc this code |
241 | | bool bHyperLink :1; // If HYPERLINK() occurs in the formula. |
242 | | bool mbFromRangeName :1; // If this array originates from a named expression |
243 | | bool mbShareable :1; // Whether or not it can be shared with adjacent cells. |
244 | | bool mbFinalized :1; // Whether code arrays have their final used size and no more tokens can be added. |
245 | | bool mbDynamicArrayFunction :1; // If a dynamic-array function occurs in the formula.(i.e. UNIQUE, FILTER, SORT) |
246 | | |
247 | | protected: |
248 | | void Assign( const FormulaTokenArray& ); |
249 | | void Assign( sal_uInt16 nCode, FormulaToken **pTokens ); |
250 | | void Move( FormulaTokenArray&& ); |
251 | | |
252 | | /// Also used by the compiler. The token MUST had been allocated with new! |
253 | | FormulaToken* Add( FormulaToken* ); |
254 | | |
255 | | public: |
256 | | enum ReplaceMode |
257 | | { |
258 | | CODE_ONLY, ///< replacement only in pCode |
259 | | CODE_AND_RPN ///< replacement in pCode and pRPN |
260 | | }; |
261 | | |
262 | | /** Also used by the compiler. The token MUST had been allocated with new! |
263 | | @param nOffset |
264 | | Absolute offset in pCode of the token to be replaced. |
265 | | @param eMode |
266 | | If CODE_ONLY only the token in pCode at nOffset is replaced. |
267 | | If CODE_AND_RPN the token in pCode at nOffset is replaced; |
268 | | if the original token was also referenced in the pRPN array |
269 | | then that reference is replaced with a reference to the new |
270 | | token as well. |
271 | | */ |
272 | | FormulaToken* ReplaceToken( sal_uInt16 nOffset, FormulaToken*, ReplaceMode eMode ); |
273 | | FormulaToken* ReplaceRPNToken( sal_uInt16 nOffset, FormulaToken* ); |
274 | | |
275 | | /** Remove a sequence of tokens from pCode array, and pRPN array if the |
276 | | tokens are referenced there. |
277 | | |
278 | | nLen and nRPN are adapted. |
279 | | |
280 | | @param nOffset |
281 | | Start offset into pCode. |
282 | | @param nCount |
283 | | Count of tokens to remove. |
284 | | |
285 | | @return Count of tokens removed. |
286 | | */ |
287 | | sal_uInt16 RemoveToken( sal_uInt16 nOffset, sal_uInt16 nCount ); |
288 | | |
289 | | FormulaTokenArray(); |
290 | | /** Assignment with incrementing references of FormulaToken entries |
291 | | (not copied!) */ |
292 | | FormulaTokenArray( const FormulaTokenArray& ); |
293 | | FormulaTokenArray( FormulaTokenArray&& ); |
294 | | virtual ~FormulaTokenArray(); |
295 | | |
296 | | virtual void Clear(); |
297 | | |
298 | | /** |
299 | | * The array has its final used size and no more token can be added. |
300 | | */ |
301 | | void Finalize(); |
302 | | |
303 | 46.7k | void SetFromRangeName( bool b ) { mbFromRangeName = b; } |
304 | 1.13M | bool IsFromRangeName() const { return mbFromRangeName; } |
305 | | |
306 | 4.11k | void SetShareable( bool b ) { mbShareable = b; } |
307 | | |
308 | | /** |
309 | | * Check if this token array is shareable between multiple adjacent |
310 | | * formula cells. Certain tokens may not function correctly when shared. |
311 | | * |
312 | | * @return true if the token array is shareable, false otherwise. |
313 | | */ |
314 | 15.8M | bool IsShareable() const { return mbShareable; } |
315 | | |
316 | | void DelRPN(); |
317 | | FormulaToken* FirstToken() const; |
318 | | |
319 | | /// Return pCode[nIdx], or nullptr if nIdx is out of bounds |
320 | | FormulaToken* TokenAt( sal_uInt16 nIdx) const |
321 | 1.19M | { |
322 | 1.19M | if (nIdx >= nLen) |
323 | 0 | return nullptr; |
324 | 1.19M | return pCode[nIdx]; |
325 | 1.19M | } |
326 | | |
327 | | /// Peek at nIdx-1 if not out of bounds, decrements nIdx if successful. Returns NULL if not. |
328 | | FormulaToken* PeekPrev( sal_uInt16 & nIdx ) const; |
329 | | |
330 | | /// Return the opcode at pCode[nIdx-1], ocNone if nIdx-1 is out of bounds |
331 | | OpCode OpCodeBefore( sal_uInt16 nIdx) const |
332 | 19.6M | { |
333 | 19.6M | if (nIdx == 0 || nIdx > nLen) |
334 | 1.88M | return ocNone; |
335 | | |
336 | 17.7M | return pCode[nIdx-1]->GetOpCode(); |
337 | 19.6M | } |
338 | | |
339 | | FormulaToken* FirstRPNToken() const; |
340 | | FormulaToken* LastRPNToken() const; |
341 | | |
342 | | bool HasReferences() const; |
343 | | |
344 | | bool HasExternalRef() const; |
345 | | bool HasOpCode( OpCode ) const; |
346 | | bool HasOpCodeRPN( OpCode ) const; |
347 | | /// Token of type svIndex or opcode ocColRowName |
348 | | bool HasNameOrColRowName() const; |
349 | | |
350 | | /** |
351 | | * Check if the token array contains any of specified opcode tokens. |
352 | | * |
353 | | * @param rOpCodes collection of opcodes to check against. |
354 | | * |
355 | | * @return true if the token array contains at least one of the specified |
356 | | * opcode tokens, false otherwise. |
357 | | */ |
358 | | bool HasOpCodes( const unordered_opcode_set& rOpCodes ) const; |
359 | | |
360 | | /// Assign pRPN to point to a newly created array filled with the data from pData |
361 | | void CreateNewRPNArrayFromData( FormulaToken** pData, sal_uInt16 nSize ) |
362 | 1.62M | { |
363 | 1.62M | pRPN = std::make_unique<FormulaToken*[]>(nSize); |
364 | 1.62M | nRPN = nSize; |
365 | 1.62M | memcpy( pRPN.get(), pData, nSize * sizeof( FormulaToken* ) ); |
366 | 1.62M | } |
367 | | |
368 | | // Assign pCode to point to a newly created array filled with data; the array is sized exactly |
369 | | // to size, so it is final: |
370 | 3.40k | void CreateNewCodeArrayFromData(FormulaToken ** data, sal_uInt16 size) { |
371 | 3.40k | pCode = std::make_unique<FormulaToken*[]>(size); |
372 | 3.40k | nLen = size; |
373 | 3.40k | memcpy(pCode.get(), data, size * sizeof (FormulaToken *)); |
374 | 3.40k | mbFinalized = true; |
375 | 3.40k | } |
376 | | |
377 | 233M | FormulaToken** GetArray() const { return pCode.get(); } |
378 | | |
379 | | FormulaTokenArrayStandardRange Tokens() const |
380 | 13.3M | { |
381 | 13.3M | return FormulaTokenArrayStandardRange(pCode.get(), nLen); |
382 | 13.3M | } |
383 | | |
384 | 21.6M | FormulaToken** GetCode() const { return pRPN.get(); } |
385 | | |
386 | | FormulaTokenArrayStandardRange RPNTokens() const |
387 | 1.69M | { |
388 | 1.69M | return FormulaTokenArrayStandardRange(pRPN.get(), nRPN); |
389 | 1.69M | } |
390 | | |
391 | | FormulaTokenArrayReferencesRange References() const |
392 | 55.0k | { |
393 | 55.0k | return FormulaTokenArrayReferencesRange(*this); |
394 | 55.0k | } |
395 | | |
396 | 210M | sal_uInt16 GetLen() const { return nLen; } |
397 | 54.2M | sal_uInt16 GetCodeLen() const { return nRPN; } |
398 | 75.2M | FormulaError GetCodeError() const { return nError; } |
399 | 417k | void SetCodeError( FormulaError n ) { nError = n; } |
400 | 291k | void SetHyperLink( bool bVal ) { bHyperLink = bVal; } |
401 | 257k | bool IsHyperLink() const { return bHyperLink; } |
402 | | |
403 | 39 | void SetDynamicArrayFunction(bool bValue) { mbDynamicArrayFunction = bValue; } |
404 | 0 | bool HasDynamicArrayFunction() const { return mbDynamicArrayFunction; } |
405 | | |
406 | 102k | ScRecalcMode GetRecalcMode() const { return nMode; } |
407 | | |
408 | | void SetCombinedBitsRecalcMode( ScRecalcMode nBits ) |
409 | 533k | { nMode |= nBits & ~ScRecalcMode::EMask; } |
410 | | ScRecalcMode GetCombinedBitsRecalcMode() const |
411 | 454k | { return nMode & ~ScRecalcMode::EMask; } |
412 | | |
413 | | /** Exclusive bits already set in nMode are zero'ed, nBits |
414 | | may contain combined bits, but only one exclusive bit |
415 | | may be set! */ |
416 | | void SetMaskedRecalcMode( ScRecalcMode nBits ) |
417 | 454k | { nMode = GetCombinedBitsRecalcMode() | nBits; } |
418 | | |
419 | | /** Bits aren't set directly but validated and handled |
420 | | according to priority if more than one exclusive bit |
421 | | was set. */ |
422 | | void AddRecalcMode( ScRecalcMode nBits ); |
423 | | |
424 | 14.4M | void ClearRecalcMode() { nMode = ScRecalcMode::NORMAL; } |
425 | | void SetExclusiveRecalcModeNormal() |
426 | 7.43k | { SetMaskedRecalcMode( ScRecalcMode::NORMAL ); } |
427 | | void SetExclusiveRecalcModeAlways() |
428 | 44.2k | { SetMaskedRecalcMode( ScRecalcMode::ALWAYS ); } |
429 | | void SetRecalcModeForced() |
430 | 104k | { nMode |= ScRecalcMode::FORCED; } |
431 | | void SetRecalcModeOnRefMove() |
432 | 6.82k | { nMode |= ScRecalcMode::ONREFMOVE; } |
433 | | bool IsRecalcModeNormal() const |
434 | 7.41M | { return bool(nMode & ScRecalcMode::NORMAL); } |
435 | | bool IsRecalcModeAlways() const |
436 | 8.85M | { return bool(nMode & ScRecalcMode::ALWAYS); } |
437 | | bool IsRecalcModeForced() const |
438 | 2.25M | { return bool(nMode & ScRecalcMode::FORCED); } |
439 | | bool IsRecalcModeOnRefMove() const |
440 | 0 | { return bool(nMode & ScRecalcMode::ONREFMOVE); } |
441 | | /** Whether recalculation must happen after import, for |
442 | | example OOXML. */ |
443 | | bool IsRecalcModeMustAfterImport() const |
444 | 1.57M | { return (nMode & ScRecalcMode::EMask) <= ScRecalcMode::ONLOAD_ONCE; } |
445 | | void ClearRecalcModeMustAfterImport() |
446 | 350k | { |
447 | 350k | if (IsRecalcModeMustAfterImport() && !IsRecalcModeAlways()) |
448 | 5.12k | SetExclusiveRecalcModeNormal(); |
449 | 350k | } |
450 | | |
451 | | /** Get OpCode of the most outer function */ |
452 | | inline OpCode GetOuterFuncOpCode() const; |
453 | | |
454 | | /** Operators +,-,*,/,^,&,=,<>,<,>,<=,>= |
455 | | with DoubleRef in Formula? */ |
456 | | bool HasMatrixDoubleRefOps() const; |
457 | | |
458 | | virtual FormulaToken* AddOpCode(OpCode e); |
459 | | |
460 | | /** Adds the single token to array. |
461 | | Derived classes must override it when they want to support derived classes from FormulaToken. |
462 | | @return true when an error occurs |
463 | | */ |
464 | | virtual bool AddFormulaToken( |
465 | | const css::sheet::FormulaToken& rToken, svl::SharedStringPool& rSPool, |
466 | | ExternalReferenceHelper* pExtRef ); |
467 | | |
468 | | /** fill the array with the tokens from the sequence. |
469 | | It calls AddFormulaToken for each token in the list. |
470 | | @param _aSequence the token to add |
471 | | @return true when an error occurs |
472 | | */ |
473 | | bool Fill( |
474 | | const css::uno::Sequence<css::sheet::FormulaToken>& rSequence, |
475 | | svl::SharedStringPool& rSPool, ExternalReferenceHelper* pExtRef ); |
476 | | |
477 | | /** |
478 | | * Do some checking based on the individual tokens. For now, we use this |
479 | | * only to check whether we can vectorize the token array. |
480 | | */ |
481 | | virtual void CheckToken( const FormulaToken& t ); |
482 | | |
483 | | /** |
484 | | * Call CheckToken() for all RPN tokens. |
485 | | */ |
486 | | void CheckAllRPNTokens(); |
487 | | |
488 | | /** Clones the token and then adds the clone to the pCode array. |
489 | | For just new'ed tokens use Add() instead of cloning it again. |
490 | | Use this AddToken() when adding a token from another origin. |
491 | | */ |
492 | | FormulaToken* AddToken( const FormulaToken& ); |
493 | | |
494 | | FormulaToken* AddString( const svl::SharedString& rStr ); |
495 | | FormulaToken* AddStringName(const svl::SharedString& rString, bool bOptional = false); |
496 | | FormulaToken* AddDPFieldName( const svl::SharedString& rStr ); |
497 | | FormulaToken* AddDouble( double fVal ); |
498 | | void AddExternal( const sal_Unicode* pStr ); |
499 | | /** Xcl import may play dirty tricks with OpCode!=ocExternal. |
500 | | Others don't use! */ |
501 | | FormulaToken* AddExternal( const OUString& rStr, OpCode eOp = ocExternal ); |
502 | | FormulaToken* AddBad( const OUString& rStr ); /// ocBad with OUString |
503 | | FormulaToken* AddStringXML( const OUString& rStr ); /// ocStringXML with OUString, temporary during import |
504 | | FormulaToken* AddStringName( const OUString& rStr ); /// ocStringName with OUString - Lambda functions |
505 | | FormulaToken* AddDPFieldName( const OUString& rStr ); /// ocDPFieldName with OUString - Pivot Table DataPilot field names |
506 | | FormulaToken* AddError( FormulaError nErr ); |
507 | | |
508 | | virtual FormulaToken* MergeArray( ); |
509 | | |
510 | | /** Assignment with incrementing references of FormulaToken entries |
511 | | (not copied!) */ |
512 | | FormulaTokenArray& operator=( const FormulaTokenArray& ); |
513 | | FormulaTokenArray& operator=( FormulaTokenArray&& ); |
514 | | |
515 | | /** Determines if this formula needs any changes to convert it to something |
516 | | previous versions of OOo could consume (Plain Old Formula, pre-ODFF, or |
517 | | also ODFF) */ |
518 | | bool NeedsPodfRewrite( const MissingConventionODF & rConv ); |
519 | | |
520 | | /** Determines if this formula needs any changes to convert it to OOXML. */ |
521 | | bool NeedsOoxmlRewrite(); |
522 | | |
523 | | /** Rewrites to Plain Old Formula or OOXML, substituting missing parameters. The |
524 | | FormulaTokenArray* returned is new'ed. */ |
525 | | FormulaTokenArray* RewriteMissing( const MissingConvention & rConv ); |
526 | | |
527 | | /** Determines if this formula may be followed by a reference. */ |
528 | | bool MayReferenceFollow(); |
529 | | |
530 | | /** Re-intern SharedString in case the SharedStringPool differs. */ |
531 | | void ReinternStrings( svl::SharedStringPool& rPool ); |
532 | | }; |
533 | | |
534 | | inline OpCode FormulaTokenArray::GetOuterFuncOpCode() const |
535 | 0 | { |
536 | 0 | if ( pRPN && nRPN ) |
537 | 0 | return pRPN[nRPN-1]->GetOpCode(); |
538 | 0 | return ocNone; |
539 | 0 | } |
540 | | |
541 | | inline FormulaTokenArrayReferencesIterator FormulaTokenArrayReferencesRange::begin() |
542 | 55.0k | { |
543 | 55.0k | return FormulaTokenArrayReferencesIterator(mrFTA.Tokens()); |
544 | 55.0k | } |
545 | | |
546 | | inline FormulaTokenArrayReferencesIterator FormulaTokenArrayReferencesRange::end() |
547 | 55.0k | { |
548 | 55.0k | return FormulaTokenArrayReferencesIterator::endOf(mrFTA.Tokens()); |
549 | 55.0k | } |
550 | | |
551 | | class FORMULA_DLLPUBLIC FormulaTokenIterator |
552 | | { |
553 | | struct Item |
554 | | { |
555 | | public: |
556 | | const FormulaTokenArray* pArr; |
557 | | short nPC; |
558 | | short nStop; |
559 | | bool bLambda; |
560 | | |
561 | | Item(const FormulaTokenArray* arr, short pc, short stop, bool lambda); |
562 | | }; |
563 | | |
564 | | std::vector<Item> maStack; |
565 | | |
566 | | public: |
567 | | FormulaTokenIterator( const FormulaTokenArray& ); |
568 | | ~FormulaTokenIterator(); |
569 | | void Reset(); |
570 | | const FormulaToken* Next(); |
571 | | const FormulaToken* PeekNextOperator(); |
572 | | bool IsEndOfPath() const; /// if a jump or subroutine path is done |
573 | 25.2k | bool HasStacked() const { return maStack.size() > 1; } |
574 | 142 | short GetPC() const { return maStack.back().nPC; } |
575 | | |
576 | | /** Jump or subroutine call. |
577 | | Program counter values will be incremented before code is executed => |
578 | | positions are to be passed with -1 offset. |
579 | | @param nStart |
580 | | Start on code at position nStart+1 (yes, pass with offset -1) |
581 | | @param nNext |
582 | | After subroutine continue with instruction at position nNext+1 |
583 | | @param nStop |
584 | | Stop before reaching code at position nStop. If not specified the |
585 | | default is to either run the entire code, or to stop if an ocSep or |
586 | | ocClose is encountered, which are only present in ocIf or ocChoose |
587 | | jumps. |
588 | | */ |
589 | | void Jump( short nStart, short nNext, short nStop = SHRT_MAX ); |
590 | | void Push( const FormulaTokenArray* ); |
591 | | void Pop(); |
592 | | void FrontPop(); |
593 | | void Lambda( bool bOpt ); |
594 | | bool IsLambda() const; |
595 | | |
596 | | /** Reconstruct the iterator afresh from a token array |
597 | | */ |
598 | | void ReInit( const FormulaTokenArray& ); |
599 | | |
600 | | private: |
601 | | SAL_DLLPRIVATE const FormulaToken* GetNonEndOfPathToken( short nIdx ) const; |
602 | | }; |
603 | | |
604 | | // For use in SAL_INFO, SAL_WARN etc |
605 | | |
606 | | template<typename charT, typename traits> |
607 | | inline std::basic_ostream<charT, traits> & operator <<(std::basic_ostream<charT, traits> & stream, const FormulaTokenArray& point) |
608 | | { |
609 | | stream << |
610 | | static_cast<const void*>(&point) << |
611 | | ":{nLen=" << point.GetLen() << |
612 | | ",nRPN=" << point.GetCodeLen() << |
613 | | ",pCode=" << static_cast<void*>(point.GetArray()) << |
614 | | ",pRPN=" << static_cast<void*>(point.GetCode()) << |
615 | | "}"; |
616 | | |
617 | | return stream; |
618 | | } |
619 | | |
620 | | class FORMULA_DLLPUBLIC FormulaTokenArrayPlainIterator |
621 | | { |
622 | | private: |
623 | | const FormulaTokenArray* mpFTA; |
624 | | sal_uInt16 mnIndex; // Current step index |
625 | | |
626 | | public: |
627 | | FormulaTokenArrayPlainIterator( const FormulaTokenArray& rFTA ) : |
628 | 19.7M | mpFTA( &rFTA ), |
629 | 19.7M | mnIndex( 0 ) |
630 | 19.7M | { |
631 | 19.7M | } |
632 | | |
633 | | void Reset() |
634 | 3.89M | { |
635 | 3.89M | mnIndex = 0; |
636 | 3.89M | } |
637 | | |
638 | | sal_uInt16 GetIndex() const |
639 | 19.6M | { |
640 | 19.6M | return mnIndex; |
641 | 19.6M | } |
642 | | |
643 | | FormulaToken* First() |
644 | 39.4k | { |
645 | 39.4k | mnIndex = 0; |
646 | 39.4k | return Next(); |
647 | 39.4k | } |
648 | | |
649 | | void Jump(sal_uInt16 nIndex) |
650 | 102k | { |
651 | 102k | mnIndex = nIndex; |
652 | 102k | } |
653 | | |
654 | | void StepBack() |
655 | 138 | { |
656 | 138 | assert(mnIndex > 0); |
657 | 138 | mnIndex--; |
658 | 138 | } |
659 | | |
660 | | FormulaToken* Next(); |
661 | | FormulaToken* NextNoSpaces(); |
662 | | FormulaToken* GetNextName(); |
663 | | FormulaToken* GetNextStringNameRPN(); |
664 | | FormulaToken* GetNextDPFieldNameRPN(); |
665 | | FormulaToken* GetNextReference(); |
666 | | FormulaToken* GetNextReferenceRPN(); |
667 | | FormulaToken* GetNextReferenceOrName(); |
668 | | FormulaToken* GetNextColRowName(); |
669 | | FormulaToken* PeekNext(); |
670 | | FormulaToken* PeekPrevNoSpaces() const; /// Only after Reset/First/Next/Last/Prev! |
671 | | FormulaToken* PeekNextNoSpaces() const; /// Only after Reset/First/Next/Last/Prev! |
672 | | |
673 | | FormulaToken* FirstRPN() |
674 | 45.6k | { |
675 | 45.6k | mnIndex = 0; |
676 | 45.6k | return NextRPN(); |
677 | 45.6k | } |
678 | | |
679 | | FormulaToken* NextRPN(); |
680 | | |
681 | | FormulaToken* LastRPN() |
682 | 0 | { |
683 | 0 | mnIndex = mpFTA->GetCodeLen(); |
684 | 0 | return PrevRPN(); |
685 | 0 | } |
686 | | |
687 | | FormulaToken* PrevRPN(); |
688 | | |
689 | | void AfterRemoveToken( sal_uInt16 nOffset, sal_uInt16 nCount ); |
690 | | }; |
691 | | |
692 | | |
693 | | } // formula |
694 | | |
695 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |