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