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 INCLUDED_SC_SOURCE_FILTER_INC_XLFORMULA_HXX
21 #define INCLUDED_SC_SOURCE_FILTER_INC_XLFORMULA_HXX
22 
23 #include <osl/diagnose.h>
24 #include <formula/opcode.hxx>
25 #include <address.hxx>
26 #include "ftools.hxx"
27 #include <map>
28 #include <memory>
29 
30 namespace svl {
31 
32 class SharedStringPool;
33 
34 }
35 
36 // Constants ==================================================================
37 
38 const size_t EXC_TOKARR_MAXLEN              = 4096;     /// Maximum size of a token array.
39 
40 // Token class flags ----------------------------------------------------------
41 
42 const sal_uInt8 EXC_TOKCLASS_MASK           = 0x60;
43 const sal_uInt8 EXC_TOKCLASS_NONE           = 0x00;     /// 00-1F: Base tokens.
44 const sal_uInt8 EXC_TOKCLASS_REF            = 0x20;     /// 20-3F: Reference class tokens.
45 const sal_uInt8 EXC_TOKCLASS_VAL            = 0x40;     /// 40-5F: Value class tokens.
46 const sal_uInt8 EXC_TOKCLASS_ARR            = 0x60;     /// 60-7F: Array class tokens.
47 
48 // Base tokens ----------------------------------------------------------------
49 
50 const sal_uInt8 EXC_TOKID_MASK              = 0x1F;
51 
52 const sal_uInt8 EXC_TOKID_NONE              = 0x00;     /// Placeholder for invalid token id.
53 const sal_uInt8 EXC_TOKID_EXP               = 0x01;     /// Array or shared formula reference.
54 const sal_uInt8 EXC_TOKID_TBL               = 0x02;     /// Multiple operation reference.
55 const sal_uInt8 EXC_TOKID_ADD               = 0x03;     /// Addition operator.
56 const sal_uInt8 EXC_TOKID_SUB               = 0x04;     /// Subtraction operator.
57 const sal_uInt8 EXC_TOKID_MUL               = 0x05;     /// Multiplication operator.
58 const sal_uInt8 EXC_TOKID_DIV               = 0x06;     /// Division operator.
59 const sal_uInt8 EXC_TOKID_POWER             = 0x07;     /// Power operator.
60 const sal_uInt8 EXC_TOKID_CONCAT            = 0x08;     /// String concatenation operator.
61 const sal_uInt8 EXC_TOKID_LT                = 0x09;     /// Less than operator.
62 const sal_uInt8 EXC_TOKID_LE                = 0x0A;     /// Less than or equal operator.
63 const sal_uInt8 EXC_TOKID_EQ                = 0x0B;     /// Equal operator.
64 const sal_uInt8 EXC_TOKID_GE                = 0x0C;     /// Greater than or equal operator.
65 const sal_uInt8 EXC_TOKID_GT                = 0x0D;     /// Greater than operator.
66 const sal_uInt8 EXC_TOKID_NE                = 0x0E;     /// Not equal operator.
67 const sal_uInt8 EXC_TOKID_ISECT             = 0x0F;     /// Intersection operator.
68 const sal_uInt8 EXC_TOKID_LIST              = 0x10;     /// List operator.
69 const sal_uInt8 EXC_TOKID_RANGE             = 0x11;     /// Range operator.
70 const sal_uInt8 EXC_TOKID_UPLUS             = 0x12;     /// Unary plus.
71 const sal_uInt8 EXC_TOKID_UMINUS            = 0x13;     /// Unary minus.
72 const sal_uInt8 EXC_TOKID_PERCENT           = 0x14;     /// Percent sign.
73 const sal_uInt8 EXC_TOKID_PAREN             = 0x15;     /// Parentheses.
74 const sal_uInt8 EXC_TOKID_MISSARG           = 0x16;     /// Missing argument.
75 const sal_uInt8 EXC_TOKID_STR               = 0x17;     /// String constant.
76 const sal_uInt8 EXC_TOKID_NLR               = 0x18;     /// Natural language reference (NLR).
77 const sal_uInt8 EXC_TOKID_ATTR              = 0x19;     /// Special attribute.
78 const sal_uInt8 EXC_TOKID_SHEET             = 0x1A;     /// Start of a sheet reference (BIFF2-BIFF4).
79 const sal_uInt8 EXC_TOKID_ENDSHEET          = 0x1B;     /// End of a sheet reference (BIFF2-BIFF4).
80 const sal_uInt8 EXC_TOKID_ERR               = 0x1C;     /// Error constant.
81 const sal_uInt8 EXC_TOKID_BOOL              = 0x1D;     /// Boolean constant.
82 const sal_uInt8 EXC_TOKID_INT               = 0x1E;     /// Integer constant.
83 const sal_uInt8 EXC_TOKID_NUM               = 0x1F;     /// Floating-point constant.
84 
85 // Base IDs of classified tokens ----------------------------------------------
86 
87 const sal_uInt8 EXC_TOKID_ARRAY             = 0x00;     /// Array constant.
88 const sal_uInt8 EXC_TOKID_FUNC              = 0x01;     /// Function, fixed number of arguments.
89 const sal_uInt8 EXC_TOKID_FUNCVAR           = 0x02;     /// Function, variable number of arguments.
90 const sal_uInt8 EXC_TOKID_NAME              = 0x03;     /// Defined name.
91 const sal_uInt8 EXC_TOKID_REF               = 0x04;     /// 2D cell reference.
92 const sal_uInt8 EXC_TOKID_AREA              = 0x05;     /// 2D area reference.
93 const sal_uInt8 EXC_TOKID_MEMAREA           = 0x06;     /// Constant reference subexpression.
94 const sal_uInt8 EXC_TOKID_MEMERR            = 0x07;     /// Deleted reference subexpression.
95 const sal_uInt8 EXC_TOKID_MEMNOMEM          = 0x08;     /// Constant reference subexpression without result.
96 const sal_uInt8 EXC_TOKID_MEMFUNC           = 0x09;     /// Variable reference subexpression.
97 const sal_uInt8 EXC_TOKID_REFERR            = 0x0A;     /// Deleted 2D cell reference.
98 const sal_uInt8 EXC_TOKID_AREAERR           = 0x0B;     /// Deleted 2D area reference.
99 const sal_uInt8 EXC_TOKID_REFN              = 0x0C;     /// Relative 2D cell reference (in names).
100 const sal_uInt8 EXC_TOKID_AREAN             = 0x0D;     /// Relative 2D area reference (in names).
101 const sal_uInt8 EXC_TOKID_MEMAREAN          = 0x0E;     /// Reference subexpression (in names).
102 const sal_uInt8 EXC_TOKID_MEMNOMEMN         = 0x0F;     /// Reference subexpression (in names) without result.
103 const sal_uInt8 EXC_TOKID_FUNCCE            = 0x18;
104 const sal_uInt8 EXC_TOKID_NAMEX             = 0x19;     /// External reference.
105 const sal_uInt8 EXC_TOKID_REF3D             = 0x1A;     /// 3D cell reference.
106 const sal_uInt8 EXC_TOKID_AREA3D            = 0x1B;     /// 3D area reference.
107 const sal_uInt8 EXC_TOKID_REFERR3D          = 0x1C;     /// Deleted 3D cell reference.
108 const sal_uInt8 EXC_TOKID_AREAERR3D         = 0x1D;     /// Deleted 3D area reference
109 
110 // specific token constants ---------------------------------------------------
111 
112 const sal_uInt16 EXC_TOK_STR_MAXLEN         = 255;      /// Maximum string length of a tStr token.
113 
114 const sal_uInt8 EXC_TOK_BOOL_FALSE          = 0;        /// sal_False value of a tBool token.
115 const sal_uInt8 EXC_TOK_BOOL_TRUE           = 1;        /// sal_True value of a tBool token.
116 
117 const sal_uInt8 EXC_TOK_ATTR_VOLATILE       = 0x01;     /// Volatile function.
118 const sal_uInt8 EXC_TOK_ATTR_IF             = 0x02;     /// Start of true condition in IF function.
119 const sal_uInt8 EXC_TOK_ATTR_CHOOSE         = 0x04;     /// Jump array of CHOOSE function.
120 const sal_uInt8 EXC_TOK_ATTR_GOTO           = 0x08;     /// Jump to token.
121 const sal_uInt8 EXC_TOK_ATTR_SUM            = 0x10;     /// SUM function with one parameter.
122 const sal_uInt8 EXC_TOK_ATTR_ASSIGN         = 0x20;     /// BASIC style assignment.
123 const sal_uInt8 EXC_TOK_ATTR_SPACE          = 0x40;     /// Spaces in formula representation.
124 
125 const sal_uInt8 EXC_TOK_ATTR_SPACE_SP       = 0x00;     /// Spaces before next token.
126 const sal_uInt8 EXC_TOK_ATTR_SPACE_BR       = 0x01;     /// Line breaks before next token.
127 const sal_uInt8 EXC_TOK_ATTR_SPACE_SP_OPEN  = 0x02;     /// Spaces before opening parenthesis.
128 const sal_uInt8 EXC_TOK_ATTR_SPACE_BR_OPEN  = 0x03;     /// Line breaks before opening parenthesis.
129 const sal_uInt8 EXC_TOK_ATTR_SPACE_SP_CLOSE = 0x04;     /// Spaces before closing parenthesis.
130 const sal_uInt8 EXC_TOK_ATTR_SPACE_BR_CLOSE = 0x05;     /// Line breaks before closing parenthesis.
131 const sal_uInt8 EXC_TOK_ATTR_SPACE_SP_PRE   = 0x06;     /// Spaces before formula (BIFF3).
132 
133 const sal_uInt16 EXC_TOK_FUNCVAR_CMD        = 0x8000;   /// Macro command.
134 const sal_uInt16 EXC_TOK_FUNCVAR_INDEXMASK  = 0x7FFF;   /// Mask for function/command index.
135 const sal_uInt8 EXC_TOK_FUNCVAR_PROMPT      = 0x80;     /// User prompt for macro commands.
136 const sal_uInt8 EXC_TOK_FUNCVAR_COUNTMASK   = 0x7F;     /// Mask for parameter count.
137 
138 const sal_uInt16 EXC_TOK_REF_COLREL         = 0x4000;   /// True = Column is relative.
139 const sal_uInt16 EXC_TOK_REF_ROWREL         = 0x8000;   /// True = Row is relative.
140 
141 const sal_uInt8 EXC_TOK_NLR_ERR             = 0x01;     /// NLR: Invalid/deleted.
142 const sal_uInt8 EXC_TOK_NLR_ROWR            = 0x02;     /// NLR: Row index.
143 const sal_uInt8 EXC_TOK_NLR_COLR            = 0x03;     /// NLR: Column index.
144 const sal_uInt8 EXC_TOK_NLR_ROWV            = 0x06;     /// NLR: Value in row.
145 const sal_uInt8 EXC_TOK_NLR_COLV            = 0x07;     /// NLR: Value in column.
146 const sal_uInt8 EXC_TOK_NLR_RANGE           = 0x0A;     /// NLR: Range.
147 const sal_uInt8 EXC_TOK_NLR_SRANGE          = 0x0B;     /// Stacked NLR: Range.
148 const sal_uInt8 EXC_TOK_NLR_SROWR           = 0x0C;     /// Stacked NLR: Row index.
149 const sal_uInt8 EXC_TOK_NLR_SCOLR           = 0x0D;     /// Stacked NLR: Column index.
150 const sal_uInt8 EXC_TOK_NLR_SROWV           = 0x0E;     /// Stacked NLR: Value in row.
151 const sal_uInt8 EXC_TOK_NLR_SCOLV           = 0x0F;     /// Stacked NLR: Value in column.
152 const sal_uInt8 EXC_TOK_NLR_RANGEERR        = 0x10;     /// NLR: Invalid/deleted range.
153 const sal_uInt8 EXC_TOK_NLR_SXNAME          = 0x1D;     /// NLR: Pivot table name.
154 const sal_uInt16 EXC_TOK_NLR_REL            = 0x8000;   /// True = Natural language ref is relative.
155 
156 const sal_uInt32 EXC_TOK_NLR_ADDREL         = 0x80000000;   /// NLR relative (in appended data).
157 const sal_uInt32 EXC_TOK_NLR_ADDMASK        = 0x3FFFFFFF;   /// Mask for number of appended ranges.
158 
159 /** Type of a formula. */
160 enum XclFormulaType
161 {
162     EXC_FMLATYPE_CELL,          /// Simple cell formula, also used in change tracking.
163     EXC_FMLATYPE_MATRIX,        /// Matrix (array) formula.
164     EXC_FMLATYPE_SHARED,        /// Shared formula.
165     EXC_FMLATYPE_CONDFMT,       /// Conditional format.
166     EXC_FMLATYPE_DATAVAL,       /// Data validation.
167     EXC_FMLATYPE_NAME,          /// Defined name.
168     EXC_FMLATYPE_CHART,         /// Chart source ranges.
169     EXC_FMLATYPE_CONTROL,       /// Spreadsheet links in form controls.
170     EXC_FMLATYPE_WQUERY,        /// Web query source range.
171     EXC_FMLATYPE_LISTVAL        /// List (cell range) validation.
172 };
173 
174 // Function parameter info ====================================================
175 
176 /** Enumerates validity modes for a function parameter. */
177 enum XclFuncParamValidity
178 {
179     EXC_PARAM_NONE = 0,         /// Default for an unspecified entry in a C-array.
180     EXC_PARAM_REGULAR,          /// Parameter supported by Calc and Excel.
181     EXC_PARAM_CALCONLY,         /// Parameter supported by Calc only.
182     EXC_PARAM_EXCELONLY         /// Parameter supported by Excel only.
183 };
184 
185 /** Enumerates different types of token class conversion in function parameters. */
186 enum XclFuncParamConv
187 {
188     EXC_PARAMCONV_ORG,          /// Use original class of current token.
189     EXC_PARAMCONV_VAL,          /// Convert tokens to VAL class.
190     EXC_PARAMCONV_ARR,          /// Convert tokens to ARR class.
191     EXC_PARAMCONV_RPT,          /// Repeat parent conversion in VALTYPE parameters.
192     EXC_PARAMCONV_RPX,          /// Repeat parent conversion in REFTYPE parameters.
193     EXC_PARAMCONV_RPO           /// Repeat parent conversion in operands of operators.
194 };
195 
196 /** Structure that contains all needed information for a parameter in a
197     function.
198 
199     The member meValid specifies which application supports the parameter. If
200     set to CALCONLY, import filters have to insert a default value for this
201     parameter, and export filters have to skip the parameter. If set to
202     EXCELONLY, import filters have to skip the parameter, and export filters
203     have to insert a default value for this parameter.
204 
205     The member mbValType specifies whether the parameter requires tokens to be
206     of value type (VAL or ARR class).
207 
208         If set to false, the parameter is called to be REFTYPE. Tokens with REF
209         default class can be inserted for the parameter (e.g. tAreaR tokens).
210 
211         If set to true, the parameter is called to be VALTYPE. Tokens with REF
212         class need to be converted to VAL tokens first (e.g. tAreaR will be
213         converted to tAreaV), and further conversion is done according to this
214         new token class.
215 
216     The member meConv specifies how to convert the current token class of the
217     token inserted for the parameter. If the token class is still REF this
218     means that the token has default REF class and the parameter is REFTYPE
219     (see member mbValType), the token will not be converted at all and remains
220     in REF class. Otherwise, token class conversion is depending on the actual
221     token class of the return value of the function containing this parameter.
222     The function may return REF class (tFuncR, tFuncVarR, tFuncCER), or it may
223     return VAL or ARR class (tFuncV, tFuncA, tFuncVarV, tFuncVarA, tFuncCEV,
224     tFuncCEA). Even if the function is able to return REF class, it may return
225     VAL or ARR class instead due to the VALTYPE data type of the parent
226     function parameter that calls the own function. Example: The INDIRECT
227     function returns REF class by default. But if called from a VALTYPE
228     function parameter, e.g. in the formula =ABS(INDIRECT("A1")), it returns
229     VAL or ARR class instead. Additionally, the repeating conversion types RPT
230     and RPX rely on the conversion executed for the function token class.
231 
232         1) ORG:
233         Use the original class of the token (VAL or ARR), regardless of any
234         conversion done for the function return class.
235 
236         2) VAL:
237         Convert ARR tokens to VAL class, regardless of any conversion done for
238         the function return class.
239 
240         3) ARR:
241         Convert VAL tokens to ARR class, regardless of any conversion done for
242         the function return class.
243 
244         4) RPT:
245         If the own function returns REF class (thus it is called from a REFTYPE
246         parameter, see above), and the parent conversion type (for the function
247         return class) was ORG, VAL, or ARR, ignore that conversion and always
248         use VAL conversion for the own token instead. If the parent conversion
249         type was RPT or RPX, repeat the conversion that would have been used if
250         the function would return value type.
251         If the own function returns value type (VAL or ARR class, see above),
252         and the parent conversion type (for the function return class) was ORG,
253         VAL, ARR, or RPT, repeat this conversion for the own token. If the
254         parent conversion type was RPX, always use ORG conversion type for the
255         own token instead.
256 
257         5) RPX:
258         This type of conversion only occurs in functions returning VAL class by
259         default. If the own token is value type, and the VAL return class of
260         the own function has been changed to ARR class (due to direct ARR
261         conversion, or due to ARR conversion repeated by RPT or RPX), set the
262         own token to ARR type. Otherwise use the original token type (VAL
263         conversion from parent parameter will not be repeated at all). If
264         nested functions have RPT or value-type RPX parameters, they will not
265         repeat this conversion type, but will use ORG conversion instead (see
266         description of RPT above).
267 
268         6) RPO:
269         This type of conversion is only used for the operands of all operators
270         (unary and binary arithmetic operators, comparison operators, and range
271         operators). It is not used for function parameters. On conversion, it
272         will be replaced by the last conversion type that was not the RPO
273         conversion. This leads to a slightly different behaviour than the RPT
274         conversion for operands in conjunction with a parent RPX conversion.
275  */
276 struct XclFuncParamInfo
277 {
278     XclFuncParamValidity  meValid;       /// Parameter validity.
279     XclFuncParamConv     meConv;         /// Token class conversion type.
280     bool                 mbValType;      /// Data type (false = REFTYPE, true = VALTYPE).
281 };
282 
283 // Function data ==============================================================
284 
285 const sal_uInt8 EXC_FUNC_MAXPARAM           = 30;       /// Maximum parameter count.
286 
287 const size_t EXC_FUNCINFO_PARAMINFO_COUNT   = 5;        /// Number of parameter info entries.
288 
289 const sal_uInt8 EXC_FUNCFLAG_VOLATILE       = 0x01;     /// Result is volatile (e.g. NOW() function).
290 const sal_uInt8 EXC_FUNCFLAG_IMPORTONLY     = 0x02;     /// Only used in import filter.
291 const sal_uInt8 EXC_FUNCFLAG_EXPORTONLY     = 0x04;     /// Only used in export filter.
292 const sal_uInt8 EXC_FUNCFLAG_PARAMPAIRS     = 0x08;     /// Optional parameters are expected to appear in pairs.
293 const sal_uInt8 EXC_FUNCFLAG_ADDINEQUIV     = 0x10;     /// Function is an add-in equivalent
294 
295 // selected function IDs
296 const sal_uInt16 EXC_FUNCID_IF              = 1;
297 const sal_uInt16 EXC_FUNCID_SUM             = 4;
298 const sal_uInt16 EXC_FUNCID_AND             = 36;
299 const sal_uInt16 EXC_FUNCID_OR              = 37;
300 const sal_uInt16 EXC_FUNCID_CHOOSE          = 100;
301 const sal_uInt16 EXC_FUNCID_EXTERNCALL      = 255;
302 
303 /** Represents information for a spreadsheet function for import and export.
304 
305     The member mpParamInfos points to an array of type information structures
306     for all parameters of the function. The last initialized structure
307     describing a regular parameter (member meValid == EXC_PARAMVALID_ALWAYS) in
308     this array is used repeatedly for all following parameters supported by a
309     function.
310  */
311 struct XclFunctionInfo
312 {
313     OpCode              meOpCode;           /// Calc function opcode.
314     sal_uInt16          mnXclFunc;          /// Excel function index.
315     sal_uInt8 const           mnMinParamCount;    /// Minimum number of parameters.
316     sal_uInt8 const           mnMaxParamCount;    /// Maximum number of parameters.
317     sal_uInt8 const           mnRetClass;         /// Token class of the return value.
318     XclFuncParamInfo const    mpParamInfos[ EXC_FUNCINFO_PARAMINFO_COUNT ]; /// Information for all parameters.
319     sal_uInt8 const           mnFlags;            /// Additional flags (EXC_FUNCFLAG_* constants).
320     const sal_Char*     mpcMacroName;       /** Function name, if simulated by
321                                                 a macro call (UTF-8) EXC_FUNCFLAG_ADDINEQUIV is 0;
322                                                 or programmatical add-in name
323                                                 if stored as such and
324                                                 EXC_FUNCFLAG_ADDINEQUIV is set. */
325 
326     /** Returns true, if the function is volatile. */
IsVolatileXclFunctionInfo327     bool         IsVolatile() const { return ::get_flag( mnFlags, EXC_FUNCFLAG_VOLATILE ); }
328     /** Returns true, if optional parameters are expected to appear in pairs. */
IsParamPairsXclFunctionInfo329     bool         IsParamPairs() const { return ::get_flag( mnFlags, EXC_FUNCFLAG_PARAMPAIRS ); }
330     /** Returns true, if the function parameter count is fixed. */
IsFixedParamCountXclFunctionInfo331     bool         IsFixedParamCount() const { return (mnXclFunc != EXC_FUNCID_EXTERNCALL) && (mnMinParamCount == mnMaxParamCount); }
332     /** Returns true, if the function is simulated by a macro call. */
IsMacroFuncXclFunctionInfo333     bool         IsMacroFunc() const { return mpcMacroName != nullptr && !(mnFlags & EXC_FUNCFLAG_ADDINEQUIV); }
334     /** Returns true, if the function is stored as an add-in call. */
IsAddInEquivalentXclFunctionInfo335     bool         IsAddInEquivalent() const { return mpcMacroName != nullptr && (mnFlags & EXC_FUNCFLAG_ADDINEQUIV); }
336     /** Returns the name of the external function as string. */
337     OUString            GetMacroFuncName() const;
338     /** Returns the programmatical name of the Add-In function as string. */
339     OUString            GetAddInEquivalentFuncName() const;
340 };
341 
342 class XclRoot;
343 
344 /** Provides access to function info structs for all available functions. */
345 class XclFunctionProvider
346 {
347 public:
348     explicit            XclFunctionProvider( const XclRoot& rRoot );
349 
350     /** Returns the function data for an Excel function index, or 0 on error. */
351     const XclFunctionInfo* GetFuncInfoFromXclFunc( sal_uInt16 nXclFunc ) const;
352     /** Returns the function data for an Excel function simulated by a macro call, or 0 on error. */
353     const XclFunctionInfo* GetFuncInfoFromXclMacroName( const OUString& rXclMacroName ) const;
354     /** Returns the function data for a Calc opcode, or 0 on error. */
355     const XclFunctionInfo* GetFuncInfoFromOpCode( OpCode eOpCode ) const;
356 
357 private:
358     void                FillXclFuncMap( const XclFunctionInfo* pBeg, const XclFunctionInfo* pEnd );
359     void                FillScFuncMap( const XclFunctionInfo* pBeg, const XclFunctionInfo* pEnd );
360 
361 private:
362     typedef ::std::map< sal_uInt16, const XclFunctionInfo* >    XclFuncMap;
363     typedef ::std::map< OUString, const XclFunctionInfo* >      XclMacroNameMap;
364     typedef ::std::map< OpCode, const XclFunctionInfo* >        ScFuncMap;
365 
366     XclFuncMap          maXclFuncMap;       /// Maps Excel function indexes to function data.
367     XclMacroNameMap     maXclMacroNameMap;  /// Maps macro function names to function data.
368     ScFuncMap           maScFuncMap;        /// Maps Calc opcodes to function data.
369 };
370 
371 // Token array ================================================================
372 
373 class XclImpStream;
374 class XclExpStream;
375 
376 /** Binary representation of an Excel token array. */
377 class XclTokenArray
378 {
379 public:
380     /** Creates an empty token array. */
381     explicit            XclTokenArray( bool bVolatile = false );
382     /** Creates a token array, swaps passed token vectors into own data. */
383     explicit            XclTokenArray( ScfUInt8Vec& rTokVec, ScfUInt8Vec& rExtDataVec, bool bVolatile = false );
384 
385     /** Returns true, if the token array is empty. */
Empty() const386     bool         Empty() const { return maTokVec.empty(); }
387     /** Returns the size of the token array in bytes. */
388     sal_uInt16          GetSize() const;
389     /** Returns read-only access to the byte vector storing token data. */
GetData() const390     const sal_uInt8* GetData() const { return maTokVec.empty() ? nullptr : maTokVec.data(); }
391     /** Returns true, if the formula contains a volatile function. */
IsVolatile() const392     bool         IsVolatile() const { return mbVolatile; }
393 
394     /** Reads the size field of the token array. */
395     void                ReadSize( XclImpStream& rStrm );
396     /** Reads the tokens of the token array (without size field). */
397     void                ReadArray( XclImpStream& rStrm );
398     /** Reads size field and the tokens. */
399     void                Read( XclImpStream& rStrm );
400 
401     /** Writes the size field of the token array. */
402     void                WriteSize( XclExpStream& rStrm ) const;
403     /** Writes the tokens of the token array (without size field). */
404     void                WriteArray( XclExpStream& rStrm ) const;
405     /** Writes size field and the tokens. */
406     void                Write( XclExpStream& rStrm ) const;
407 
408     /** Compares this token array with the passed. */
409     bool                operator==( const XclTokenArray& rTokArr ) const;
410 
411 private:
412     ScfUInt8Vec         maTokVec;       /// Byte vector containing token data.
413     ScfUInt8Vec         maExtDataVec;   /// Byte vector containing extended data (arrays, stacked NLRs).
414     bool const          mbVolatile;     /// True = Formula contains volatile function.
415 };
416 
417 typedef std::shared_ptr< XclTokenArray > XclTokenArrayRef;
418 
419 /** Calls the Read() function at the passed token array. */
420 XclImpStream& operator>>( XclImpStream& rStrm, XclTokenArray& rTokArr );
421 /** Calls the Write() function at the passed token array. */
422 XclExpStream& operator<<( XclExpStream& rStrm, const XclTokenArray& rTokArr );
423 /** Calls the Write() function at the passed token array. */
424 XclExpStream& operator<<( XclExpStream& rStrm, const XclTokenArrayRef& rxTokArr );
425 
426 namespace formula { class FormulaToken; }
427 class ScTokenArray;
428 
429 /** Special token array iterator for the Excel filters.
430 
431     Iterates over a Calc token array without modifying it (therefore the
432     iterator can be used with constant token arrays).
433 
434     Usage: Construct a new iterator object and pass a Calc token array, or use
435     the Init() function to assign another Calc token array. As long as the Is()
436     function returns true, the accessor functions can be used to get the
437     current Calc token.
438  */
439 class XclTokenArrayIterator
440 {
441 public:
442     explicit            XclTokenArrayIterator();
443     explicit            XclTokenArrayIterator( const ScTokenArray& rScTokArr, bool bSkipSpaces );
444     /** Copy constructor that allows to change the skip-spaces mode. */
445     explicit            XclTokenArrayIterator( const XclTokenArrayIterator& rTokArrIt, bool bSkipSpaces );
446 
447     void                Init( const ScTokenArray& rScTokArr, bool bSkipSpaces );
448 
Is() const449     bool         Is() const { return mppScToken != nullptr; }
operator !() const450     bool         operator!() const { return !Is(); }
Get() const451     const ::formula::FormulaToken* Get() const { return mppScToken ? *mppScToken : nullptr; }
operator ->() const452     const ::formula::FormulaToken* operator->() const { return Get(); }
operator *() const453     const ::formula::FormulaToken& operator*() const { return *Get(); }
454 
455     XclTokenArrayIterator& operator++();
456 
457 private:
458     void                NextRawToken();
459     void                SkipSpaces();
460 
461 private:
462     const ::formula::FormulaToken*const* mppScTokenBeg;     /// Pointer to first token pointer of token array.
463     const ::formula::FormulaToken*const* mppScTokenEnd;     /// Pointer behind last token pointer of token array.
464     const ::formula::FormulaToken*const* mppScToken;        /// Pointer to current token pointer of token array.
465     bool                mbSkipSpaces;       /// true = Skip whitespace tokens.
466 };
467 
468 /** Contains all cell references that can be extracted from a multiple operations formula. */
469 struct XclMultipleOpRefs
470 {
471     ScAddress           maFmlaScPos;        /// Position of the (first) formula cell.
472     ScAddress           maColFirstScPos;
473     ScAddress           maColRelScPos;
474     ScAddress           maRowFirstScPos;
475     ScAddress           maRowRelScPos;
476     bool                mbDblRefMode;       /// true = One formula with row and column values.
477 };
478 
479 /** A helper with Excel specific token array functions.
480 
481     The purpose to not add these functions to ScTokenArray is to prevent code
482     changes in low-level Calc headers and to keep the Excel specific source
483     code in the filter directory. Deriving from ScTokenArray is not viable
484     because that would need expensive copy-constructions of the token arrays.
485  */
486 class XclTokenArrayHelper
487 {
488 public:
489     // token identifiers ------------------------------------------------------
490 
491     /** Returns the classified token ID from a base ID and the token class. */
492     inline static sal_uInt8 GetTokenId( sal_uInt8 nBaseId, sal_uInt8 nTokenClass );
493 
494     /** Returns the token class of the passed token ID. */
GetTokenClass(sal_uInt8 nTokenId)495     static sal_uInt8 GetTokenClass( sal_uInt8 nTokenId ) { return nTokenId & EXC_TOKCLASS_MASK; }
496     /** Changes the token class in the passed classified token ID. */
497     inline static void  ChangeTokenClass( sal_uInt8& rnTokenId, sal_uInt8 nTokenClass );
498 
499     // strings and string lists -----------------------------------------------
500 
501     /** Tries to extract a string from the passed token.
502         @param rString  (out-parameter) The string contained in the token.
503         @return  true = Passed token is a string token, rString parameter is valid. */
504     static bool         GetTokenString( OUString& rString, const ::formula::FormulaToken& rScToken );
505 
506     /** Parses the passed formula and tries to find a single string token, i.e. "abc".
507         @param rString  (out-parameter) The string contained in the formula.
508         @return  true = String token found, rString parameter is valid. */
509     static bool         GetString( OUString& rString, const ScTokenArray& rScTokArr );
510 
511     /** Parses the passed formula and tries to find a string token list, i.e. "abc";"def";"ghi".
512         @descr  Returns the unquoted (!) strings in a single string, separated with the
513         passed character. If a comma is specified, the function will return abc,def,ghi from
514         the example above.
515         @param rStringList  (out-parameter) All strings contained in the formula as list.
516         @param cSep  List separator character.
517         @return  true = String token list found, rString parameter is valid. */
518     static bool         GetStringList( OUString& rStringList, const ScTokenArray& rScTokArr, sal_Unicode cSep );
519 
520     /** Tries to convert a formula that consists of a single string token to a list of strings.
521         Removes leading spaces from each token.
522         @descr  Example: The formula ="abc\ndef\nghi" will be converted to the formula
523         ="abc";"def";"ghi", if the LF character is specified as separator.
524         @param rScTokArr  (in/out-parameter) The token array to modify.
525         @param cStringSep  The separator in the source string. */
526     static void ConvertStringToList(
527         ScTokenArray& rScTokArr, svl::SharedStringPool& rSPool, sal_Unicode cStringSep );
528 
529     // multiple operations ----------------------------------------------------
530 
531     /** Parses the passed formula and tries to extract references of a multiple operation.
532         @descr  Requires that the formula contains a single MULTIPLE.OPERATION function call.
533         Spaces in the formula are silently ignored.
534         @return  true = Multiple operation found, and all references successfully extracted. */
535     static bool GetMultipleOpRefs( XclMultipleOpRefs& rRefs, const ScTokenArray& rScTokArr, const ScAddress& rScPos );
536 };
537 
GetTokenId(sal_uInt8 nBaseId,sal_uInt8 nTokenClass)538 inline sal_uInt8 XclTokenArrayHelper::GetTokenId( sal_uInt8 nBaseId, sal_uInt8 nTokenClass )
539 {
540     OSL_ENSURE( !::get_flag( nBaseId, static_cast< sal_uInt8 >( ~EXC_TOKID_MASK ) ), "XclTokenArrayHelper::GetTokenId - invalid token ID" );
541     OSL_ENSURE( !::get_flag( nTokenClass, static_cast< sal_uInt8 >( ~EXC_TOKCLASS_MASK ) ), "XclTokenArrayHelper::GetTokenId - invalid token class" );
542     return nBaseId | nTokenClass;
543 }
544 
ChangeTokenClass(sal_uInt8 & rnTokenId,sal_uInt8 nTokenClass)545 inline void XclTokenArrayHelper::ChangeTokenClass( sal_uInt8& rnTokenId, sal_uInt8 nTokenClass )
546 {
547     OSL_ENSURE( !::get_flag( nTokenClass, static_cast< sal_uInt8 >( ~EXC_TOKCLASS_MASK ) ), "XclTokenArrayHelper::ChangeTokenClass - invalid token class" );
548     ::set_flag( rnTokenId, EXC_TOKCLASS_MASK, false );
549     ::set_flag( rnTokenId, nTokenClass );
550 }
551 
552 #endif
553 
554 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
555