/src/libreoffice/sc/source/ui/unoobj/tokenuno.cxx
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 | | #include <memory> |
21 | | #include <tokenuno.hxx> |
22 | | |
23 | | #include <sal/macros.h> |
24 | | #include <sal/log.hxx> |
25 | | |
26 | | #include <com/sun/star/sheet/ComplexReference.hpp> |
27 | | #include <com/sun/star/sheet/ExternalReference.hpp> |
28 | | #include <com/sun/star/sheet/ReferenceFlags.hpp> |
29 | | #include <com/sun/star/sheet/AddressConvention.hpp> |
30 | | #include <com/sun/star/sheet/NameToken.hpp> |
31 | | #include <com/sun/star/sheet/TableRefToken.hpp> |
32 | | #include <com/sun/star/table/CellAddress.hpp> |
33 | | |
34 | | #include <svl/itemprop.hxx> |
35 | | #include <vcl/svapp.hxx> |
36 | | #include <comphelper/string.hxx> |
37 | | |
38 | | #include <miscuno.hxx> |
39 | | #include <convuno.hxx> |
40 | | #include <unonames.hxx> |
41 | | #include <compiler.hxx> |
42 | | #include <tokenarray.hxx> |
43 | | #include <docsh.hxx> |
44 | | #include <rangeseq.hxx> |
45 | | #include <externalrefmgr.hxx> |
46 | | |
47 | | using namespace ::formula; |
48 | | using namespace ::com::sun::star; |
49 | | |
50 | | static std::span<const SfxItemPropertyMapEntry> lcl_GetFormulaParserMap() |
51 | 1 | { |
52 | 1 | static const SfxItemPropertyMapEntry aFormulaParserMap_Impl[] = |
53 | 1 | { |
54 | 1 | { SC_UNO_COMPILEFAP, 0, cppu::UnoType<bool>::get(), 0, 0 }, |
55 | 1 | { SC_UNO_COMPILEENGLISH, 0, cppu::UnoType<bool>::get(), 0, 0 }, |
56 | 1 | { SC_UNO_IGNORELEADING, 0, cppu::UnoType<bool>::get(), 0, 0 }, |
57 | 1 | { SC_UNO_FORMULACONVENTION, 0, cppu::UnoType<decltype(sheet::AddressConvention::UNSPECIFIED)>::get(), 0, 0 }, |
58 | 1 | { SC_UNO_OPCODEMAP, 0, cppu::UnoType<uno::Sequence< sheet::FormulaOpCodeMapEntry >>::get(), 0, 0 }, |
59 | 1 | }; |
60 | 1 | return aFormulaParserMap_Impl; |
61 | 1 | } |
62 | | |
63 | | const formula::FormulaGrammar::AddressConvention aConvMap[] = { |
64 | | formula::FormulaGrammar::CONV_OOO, // <- AddressConvention::OOO |
65 | | formula::FormulaGrammar::CONV_XL_A1, // <- AddressConvention::XL_A1 |
66 | | formula::FormulaGrammar::CONV_XL_R1C1, // <- AddressConvention::XL_R1C1 |
67 | | formula::FormulaGrammar::CONV_XL_OOX, // <- AddressConvention::XL_OOX |
68 | | formula::FormulaGrammar::CONV_LOTUS_A1 // <- AddressConvention::LOTUS_A1 |
69 | | }; |
70 | | // sal_Int16 because of comparison of integer expressions below. |
71 | | constexpr sal_Int16 nConvMapCount = SAL_N_ELEMENTS(aConvMap); |
72 | | |
73 | | |
74 | | SC_SIMPLE_SERVICE_INFO( ScFormulaParserObj, u"ScFormulaParserObj"_ustr, SC_SERVICENAME_FORMULAPARS ) |
75 | | |
76 | | ScFormulaParserObj::ScFormulaParserObj(ScDocShell* pDocSh) : |
77 | 10.4k | mpDocShell( pDocSh ), |
78 | 10.4k | mnConv( sheet::AddressConvention::UNSPECIFIED ), |
79 | 10.4k | mbEnglish( false ), |
80 | 10.4k | mbIgnoreSpaces( true ), |
81 | 10.4k | mbCompileFAP( false ), |
82 | 10.4k | mbRefConventionChartOOXML( false ) |
83 | 10.4k | { |
84 | 10.4k | mpDocShell->GetDocument().AddUnoObject(*this); |
85 | 10.4k | } |
86 | | |
87 | | ScFormulaParserObj::~ScFormulaParserObj() |
88 | 10.4k | { |
89 | 10.4k | SolarMutexGuard g; |
90 | | |
91 | 10.4k | if (mpDocShell) |
92 | 10.4k | mpDocShell->GetDocument().RemoveUnoObject(*this); |
93 | 10.4k | } |
94 | | |
95 | | void ScFormulaParserObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) |
96 | 278k | { |
97 | 278k | if ( rHint.GetId() == SfxHintId::Dying ) |
98 | 0 | mpDocShell = nullptr; |
99 | 278k | } |
100 | | |
101 | | // XFormulaParser |
102 | | |
103 | | void ScFormulaParserObj::SetCompilerFlags( ScCompiler& rCompiler ) const |
104 | 5.00k | { |
105 | 5.00k | formula::FormulaGrammar::AddressConvention eConv = formula::FormulaGrammar::CONV_UNSPECIFIED; |
106 | 5.00k | if (mnConv >= 0 && mnConv < nConvMapCount) |
107 | 5.00k | eConv = aConvMap[mnConv]; |
108 | | |
109 | | // If mxOpCodeMap is not empty it overrides mbEnglish, and vice versa. We |
110 | | // don't need to initialize things twice. |
111 | 5.00k | if (mxOpCodeMap) |
112 | 5.00k | rCompiler.SetFormulaLanguage( mxOpCodeMap ); |
113 | 0 | else |
114 | 0 | { |
115 | 0 | const sal_Int32 nFormulaLanguage = (eConv == formula::FormulaGrammar::CONV_XL_OOX ? |
116 | 0 | sheet::FormulaLanguage::OOXML : |
117 | 0 | (mbEnglish ? sheet::FormulaLanguage::ENGLISH : sheet::FormulaLanguage::NATIVE)); |
118 | 0 | ScCompiler::OpCodeMapPtr xMap = rCompiler.GetOpCodeMap( nFormulaLanguage); |
119 | 0 | rCompiler.SetFormulaLanguage( xMap); |
120 | 0 | } |
121 | | |
122 | 5.00k | rCompiler.SetRefConvention( eConv ); |
123 | 5.00k | rCompiler.EnableJumpCommandReorder(!mbCompileFAP); |
124 | 5.00k | rCompiler.EnableStopOnError(!mbCompileFAP); |
125 | | |
126 | 5.00k | rCompiler.SetExternalLinks(maExternalLinks); |
127 | 5.00k | rCompiler.SetRefConventionChartOOXML(mbRefConventionChartOOXML); |
128 | 5.00k | } |
129 | | |
130 | | uno::Sequence<sheet::FormulaToken> SAL_CALL ScFormulaParserObj::parseFormula( |
131 | | const OUString& aFormula, const table::CellAddress& rReferencePos ) |
132 | 5.00k | { |
133 | 5.00k | SolarMutexGuard aGuard; |
134 | 5.00k | uno::Sequence<sheet::FormulaToken> aRet; |
135 | | |
136 | 5.00k | if (mpDocShell) |
137 | 5.00k | { |
138 | 5.00k | ScDocument& rDoc = mpDocShell->GetDocument(); |
139 | 5.00k | ScExternalRefManager::ApiGuard aExtRefGuard(rDoc); |
140 | | |
141 | 5.00k | ScAddress aRefPos( ScAddress::UNINITIALIZED ); |
142 | 5.00k | ScUnoConversion::FillScAddress( aRefPos, rReferencePos ); |
143 | 5.00k | ScCompiler aCompiler( rDoc, aRefPos, rDoc.GetGrammar()); |
144 | 5.00k | SetCompilerFlags( aCompiler ); |
145 | | |
146 | 5.00k | std::unique_ptr<ScTokenArray> pCode = aCompiler.CompileString( aFormula ); |
147 | 5.00k | if (pCode->HasOpCode(ocTableRef)) |
148 | 0 | { |
149 | 0 | FormulaError nErr = pCode->GetCodeError(); |
150 | 0 | aCompiler.EnableJumpCommandReorder(true); |
151 | 0 | aCompiler.CompileTokenArray(); // needed for corresponding inner reference |
152 | 0 | pCode->DelRPN(); // can be discarded |
153 | 0 | pCode->SetCodeError(nErr); // reset to parsing error, if any |
154 | 0 | } |
155 | 5.00k | ScTokenConversion::ConvertToTokenSequence( rDoc, aRet, *pCode ); |
156 | 5.00k | } |
157 | | |
158 | 5.00k | return aRet; |
159 | 5.00k | } |
160 | | |
161 | | OUString SAL_CALL ScFormulaParserObj::printFormula( |
162 | | const uno::Sequence<sheet::FormulaToken>& aTokens, const table::CellAddress& rReferencePos ) |
163 | 0 | { |
164 | 0 | SolarMutexGuard aGuard; |
165 | 0 | OUString aRet; |
166 | |
|
167 | 0 | if (mpDocShell) |
168 | 0 | { |
169 | 0 | ScDocument& rDoc = mpDocShell->GetDocument(); |
170 | 0 | ScTokenArray aCode(rDoc); |
171 | 0 | (void)ScTokenConversion::ConvertToTokenArray( rDoc, aCode, aTokens ); |
172 | 0 | ScAddress aRefPos( ScAddress::UNINITIALIZED ); |
173 | 0 | ScUnoConversion::FillScAddress( aRefPos, rReferencePos ); |
174 | 0 | ScCompiler aCompiler(rDoc, aRefPos, aCode, rDoc.GetGrammar()); |
175 | 0 | SetCompilerFlags( aCompiler ); |
176 | |
|
177 | 0 | OUStringBuffer aBuffer; |
178 | 0 | aCompiler.CreateStringFromTokenArray( aBuffer ); |
179 | 0 | aRet = aBuffer.makeStringAndClear(); |
180 | 0 | } |
181 | |
|
182 | 0 | return aRet; |
183 | 0 | } |
184 | | |
185 | | // XPropertySet |
186 | | |
187 | | uno::Reference<beans::XPropertySetInfo> SAL_CALL ScFormulaParserObj::getPropertySetInfo() |
188 | 10.4k | { |
189 | 10.4k | static uno::Reference< beans::XPropertySetInfo > aRef(new SfxItemPropertySetInfo( lcl_GetFormulaParserMap() )); |
190 | 10.4k | return aRef; |
191 | 10.4k | } |
192 | | |
193 | | void SAL_CALL ScFormulaParserObj::setPropertyValue( |
194 | | const OUString& aPropertyName, const uno::Any& aValue ) |
195 | 42.0k | { |
196 | 42.0k | SolarMutexGuard aGuard; |
197 | 42.0k | if ( aPropertyName == SC_UNO_COMPILEFAP ) |
198 | 0 | { |
199 | 0 | aValue >>= mbCompileFAP; |
200 | 0 | } |
201 | 42.0k | else if ( aPropertyName == SC_UNO_COMPILEENGLISH ) |
202 | 10.4k | { |
203 | 10.4k | bool bOldEnglish = mbEnglish; |
204 | 10.4k | if (!(aValue >>= mbEnglish)) |
205 | 0 | throw lang::IllegalArgumentException(); |
206 | | |
207 | | // Need to recreate the symbol map to change English property |
208 | | // because the map is const. So for performance reasons set |
209 | | // CompileEnglish _before_ OpCodeMap! |
210 | 10.4k | if (mxOpCodeMap && mbEnglish != bOldEnglish) |
211 | 0 | { |
212 | 0 | mxOpCodeMap = formula::FormulaCompiler::CreateOpCodeMap( maOpCodeMapping, mbEnglish); |
213 | 0 | } |
214 | | |
215 | 10.4k | } |
216 | 31.6k | else if ( aPropertyName == SC_UNO_FORMULACONVENTION ) |
217 | 10.4k | { |
218 | 10.4k | aValue >>= mnConv; |
219 | | |
220 | 10.4k | bool bOldEnglish = mbEnglish; |
221 | 10.4k | if (mnConv >= 0 && mnConv < nConvMapCount |
222 | 10.4k | && aConvMap[mnConv] == formula::FormulaGrammar::CONV_XL_OOX) |
223 | 10.4k | mbEnglish = true; |
224 | | |
225 | | // Same as for SC_UNO_COMPILEENGLISH, though an OpCodeMap should not |
226 | | // had been set for CONV_XL_OOX. |
227 | 10.4k | if (mxOpCodeMap && mbEnglish != bOldEnglish) |
228 | 0 | { |
229 | 0 | mxOpCodeMap = formula::FormulaCompiler::CreateOpCodeMap( maOpCodeMapping, mbEnglish); |
230 | 0 | } |
231 | 10.4k | } |
232 | 21.1k | else if ( aPropertyName == SC_UNO_IGNORELEADING ) |
233 | 10.4k | { |
234 | 10.4k | aValue >>= mbIgnoreSpaces; |
235 | 10.4k | } |
236 | 10.7k | else if ( aPropertyName == SC_UNO_OPCODEMAP ) |
237 | 10.4k | { |
238 | 10.4k | if (!(aValue >>= maOpCodeMapping)) |
239 | 0 | throw lang::IllegalArgumentException(); |
240 | | |
241 | 10.4k | mxOpCodeMap = formula::FormulaCompiler::CreateOpCodeMap( maOpCodeMapping, mbEnglish); |
242 | | |
243 | 10.4k | } |
244 | 315 | else if ( aPropertyName == SC_UNO_EXTERNALLINKS ) |
245 | 320 | { |
246 | 320 | if (!(aValue >>= maExternalLinks)) |
247 | 0 | throw lang::IllegalArgumentException(); |
248 | 320 | } |
249 | 18.4E | else if ( aPropertyName == SC_UNO_REF_CONV_CHARTOOXML ) |
250 | 0 | { |
251 | 0 | if (!(aValue >>= mbRefConventionChartOOXML)) |
252 | 0 | throw lang::IllegalArgumentException(); |
253 | 0 | } |
254 | 18.4E | else |
255 | 18.4E | throw beans::UnknownPropertyException(aPropertyName); |
256 | 42.0k | } |
257 | | |
258 | | uno::Any SAL_CALL ScFormulaParserObj::getPropertyValue( const OUString& aPropertyName ) |
259 | 0 | { |
260 | 0 | SolarMutexGuard aGuard; |
261 | 0 | uno::Any aRet; |
262 | 0 | if ( aPropertyName == SC_UNO_COMPILEFAP ) |
263 | 0 | { |
264 | 0 | aRet <<= mbCompileFAP; |
265 | 0 | } |
266 | 0 | else if ( aPropertyName == SC_UNO_COMPILEENGLISH ) |
267 | 0 | { |
268 | 0 | aRet <<= mbEnglish; |
269 | 0 | } |
270 | 0 | else if ( aPropertyName == SC_UNO_FORMULACONVENTION ) |
271 | 0 | { |
272 | 0 | aRet <<= mnConv; |
273 | 0 | } |
274 | 0 | else if ( aPropertyName == SC_UNO_IGNORELEADING ) |
275 | 0 | { |
276 | 0 | aRet <<= mbIgnoreSpaces; |
277 | 0 | } |
278 | 0 | else if ( aPropertyName == SC_UNO_OPCODEMAP ) |
279 | 0 | { |
280 | 0 | aRet <<= maOpCodeMapping; |
281 | 0 | } |
282 | 0 | else if ( aPropertyName == SC_UNO_EXTERNALLINKS ) |
283 | 0 | { |
284 | 0 | aRet <<= maExternalLinks; |
285 | 0 | } |
286 | 0 | else if ( aPropertyName == SC_UNO_REF_CONV_CHARTOOXML ) |
287 | 0 | { |
288 | 0 | aRet <<= mbRefConventionChartOOXML; |
289 | 0 | } |
290 | 0 | else |
291 | 0 | throw beans::UnknownPropertyException(aPropertyName); |
292 | 0 | return aRet; |
293 | 0 | } |
294 | | |
295 | | SC_IMPL_DUMMY_PROPERTY_LISTENER( ScFormulaParserObj ) |
296 | | |
297 | | static void lcl_ExternalRefToApi( sheet::SingleReference& rAPI, const ScSingleRefData& rRef ) |
298 | 115 | { |
299 | 115 | rAPI.Column = 0; |
300 | 115 | rAPI.Row = 0; |
301 | 115 | rAPI.Sheet = 0; |
302 | 115 | rAPI.RelativeColumn = 0; |
303 | 115 | rAPI.RelativeRow = 0; |
304 | 115 | rAPI.RelativeSheet = 0; |
305 | | |
306 | 115 | sal_Int32 nFlags = 0; |
307 | 115 | if ( rRef.IsColRel() ) |
308 | 0 | { |
309 | 0 | nFlags |= sheet::ReferenceFlags::COLUMN_RELATIVE; |
310 | 0 | rAPI.RelativeColumn = rRef.Col(); |
311 | 0 | } |
312 | 115 | else |
313 | 115 | rAPI.Column = rRef.Col(); |
314 | | |
315 | 115 | if ( rRef.IsRowRel() ) |
316 | 0 | { |
317 | 0 | nFlags |= sheet::ReferenceFlags::ROW_RELATIVE; |
318 | 0 | rAPI.RelativeRow = rRef.Row(); |
319 | 0 | } |
320 | 115 | else |
321 | 115 | rAPI.Row = rRef.Row(); |
322 | | |
323 | 115 | if ( rRef.IsColDeleted() ) nFlags |= sheet::ReferenceFlags::COLUMN_DELETED; |
324 | 115 | if ( rRef.IsRowDeleted() ) nFlags |= sheet::ReferenceFlags::ROW_DELETED; |
325 | 115 | if ( rRef.IsFlag3D() ) nFlags |= sheet::ReferenceFlags::SHEET_3D; |
326 | 115 | if ( rRef.IsRelName() ) nFlags |= sheet::ReferenceFlags::RELATIVE_NAME; |
327 | 115 | rAPI.Flags = nFlags; |
328 | 115 | } |
329 | | |
330 | | static void lcl_SingleRefToApi( sheet::SingleReference& rAPI, const ScSingleRefData& rRef ) |
331 | 13.4k | { |
332 | 13.4k | sal_Int32 nFlags = 0; |
333 | 13.4k | if ( rRef.IsColRel() ) |
334 | 1.18k | { |
335 | 1.18k | nFlags |= sheet::ReferenceFlags::COLUMN_RELATIVE; |
336 | 1.18k | rAPI.RelativeColumn = rRef.Col(); |
337 | 1.18k | rAPI.Column = 0; |
338 | 1.18k | } |
339 | 12.2k | else |
340 | 12.2k | { |
341 | 12.2k | rAPI.RelativeColumn = 0; |
342 | 12.2k | rAPI.Column = rRef.Col(); |
343 | 12.2k | } |
344 | | |
345 | 13.4k | if ( rRef.IsRowRel() ) |
346 | 1.34k | { |
347 | 1.34k | nFlags |= sheet::ReferenceFlags::ROW_RELATIVE; |
348 | 1.34k | rAPI.RelativeRow = rRef.Row(); |
349 | 1.34k | rAPI.Row = 0; |
350 | 1.34k | } |
351 | 12.0k | else |
352 | 12.0k | { |
353 | 12.0k | rAPI.RelativeRow = 0; |
354 | 12.0k | rAPI.Row = rRef.Row(); |
355 | 12.0k | } |
356 | | |
357 | 13.4k | if ( rRef.IsTabRel() ) |
358 | 2.73k | { |
359 | 2.73k | nFlags |= sheet::ReferenceFlags::SHEET_RELATIVE; |
360 | 2.73k | rAPI.RelativeSheet = rRef.Tab(); |
361 | 2.73k | rAPI.Sheet = 0; |
362 | 2.73k | } |
363 | 10.6k | else |
364 | 10.6k | { |
365 | 10.6k | rAPI.RelativeSheet = 0; |
366 | 10.6k | rAPI.Sheet = rRef.Tab(); |
367 | 10.6k | } |
368 | | |
369 | 13.4k | if ( rRef.IsColDeleted() ) nFlags |= sheet::ReferenceFlags::COLUMN_DELETED; |
370 | 13.4k | if ( rRef.IsRowDeleted() ) nFlags |= sheet::ReferenceFlags::ROW_DELETED; |
371 | 13.4k | if ( rRef.IsTabDeleted() ) nFlags |= sheet::ReferenceFlags::SHEET_DELETED; |
372 | 13.4k | if ( rRef.IsFlag3D() ) nFlags |= sheet::ReferenceFlags::SHEET_3D; |
373 | 13.4k | if ( rRef.IsRelName() ) nFlags |= sheet::ReferenceFlags::RELATIVE_NAME; |
374 | 13.4k | rAPI.Flags = nFlags; |
375 | 13.4k | } |
376 | | |
377 | | bool ScTokenConversion::ConvertToTokenArray( ScDocument& rDoc, |
378 | | ScTokenArray& rTokenArray, const uno::Sequence<sheet::FormulaToken>& rSequence ) |
379 | 3.12k | { |
380 | 3.12k | return !rTokenArray.Fill(rSequence, rDoc.GetSharedStringPool(), rDoc.GetExternalRefManager()); |
381 | 3.12k | } |
382 | | |
383 | | void ScTokenConversion::ConvertToTokenSequence( const ScDocument& rDoc, |
384 | | uno::Sequence<sheet::FormulaToken>& rSequence, const ScTokenArray& rTokenArray, |
385 | | bool bIgnoreTableRefNoInnerReference ) |
386 | 12.4k | { |
387 | 12.4k | sal_Int32 nLen = static_cast<sal_Int32>(rTokenArray.GetLen()); |
388 | 12.4k | formula::FormulaToken** pTokens = rTokenArray.GetArray(); |
389 | 12.4k | if ( pTokens ) |
390 | 12.1k | { |
391 | 12.1k | rSequence.realloc(nLen); |
392 | 12.1k | auto pSequence = rSequence.getArray(); |
393 | 45.4k | for (sal_Int32 nPos=0; nPos<nLen; nPos++) |
394 | 33.2k | { |
395 | 33.2k | const formula::FormulaToken& rToken = *pTokens[nPos]; |
396 | 33.2k | sheet::FormulaToken& rAPI = pSequence[nPos]; |
397 | | |
398 | 33.2k | OpCode eOpCode = rToken.GetOpCode(); |
399 | | // eOpCode may be changed in the following switch/case |
400 | 33.2k | switch ( rToken.GetType() ) |
401 | 33.2k | { |
402 | 4.87k | case svByte: |
403 | | // Only the count of spaces is stored as "long". Parameter count is ignored. |
404 | 4.87k | if ( eOpCode == ocSpaces ) |
405 | 54 | rAPI.Data <<= static_cast<sal_Int32>(static_cast<const FormulaByteToken&>(rToken).GetByte()); |
406 | 4.81k | else if (eOpCode == ocWhitespace) |
407 | 0 | { |
408 | 0 | auto const & rSToken = static_cast<const FormulaSpaceToken&>(rToken); |
409 | | // Convention is one character repeated. |
410 | 0 | if (rSToken.GetByte() == 1) |
411 | 0 | rAPI.Data <<= OUString( rSToken.GetChar()); |
412 | 0 | else |
413 | 0 | { |
414 | 0 | OUStringBuffer aBuf(rSToken.GetByte()); |
415 | 0 | comphelper::string::padToLength( aBuf, rSToken.GetByte(), rSToken.GetChar()); |
416 | 0 | rAPI.Data <<= aBuf.makeStringAndClear(); |
417 | 0 | } |
418 | 0 | } |
419 | 4.81k | else |
420 | 4.81k | rAPI.Data.clear(); // no data |
421 | 4.87k | break; |
422 | 2.48k | case formula::svDouble: |
423 | 2.48k | rAPI.Data <<= static_cast<const FormulaDoubleToken&>(rToken).GetDouble(); |
424 | 2.48k | break; |
425 | 2.38k | case formula::svString: |
426 | 2.38k | rAPI.Data <<= static_cast<const FormulaStringToken&>(rToken).GetString().getString(); |
427 | 2.38k | break; |
428 | 0 | case svExternal: |
429 | | // Function name is stored as string. |
430 | | // Byte (parameter count) is ignored. |
431 | 0 | rAPI.Data <<= static_cast<const FormulaExternalToken&>(rToken).GetExternal(); |
432 | 0 | break; |
433 | 3.82k | case svSingleRef: |
434 | 3.82k | { |
435 | 3.82k | sheet::SingleReference aSingleRef; |
436 | 3.82k | lcl_SingleRefToApi( aSingleRef, static_cast<const ScSingleRefToken&>(rToken).GetSingleRef() ); |
437 | 3.82k | rAPI.Data <<= aSingleRef; |
438 | 3.82k | } |
439 | 3.82k | break; |
440 | 4.78k | case formula::svDoubleRef: |
441 | 4.78k | { |
442 | 4.78k | sheet::ComplexReference aCompRef; |
443 | 4.78k | lcl_SingleRefToApi( aCompRef.Reference1, static_cast<const ScDoubleRefToken&>(rToken).GetSingleRef() ); |
444 | 4.78k | lcl_SingleRefToApi( aCompRef.Reference2, static_cast<const ScDoubleRefToken&>(rToken).GetSingleRef2() ); |
445 | 4.78k | rAPI.Data <<= aCompRef; |
446 | 4.78k | } |
447 | 4.78k | break; |
448 | 331 | case svIndex: |
449 | 331 | { |
450 | 331 | if (rToken.GetOpCode() == ocTableRef) |
451 | 15 | { |
452 | 15 | const ScTableRefToken* pTR = static_cast<const ScTableRefToken*>(&rToken); |
453 | 15 | sheet::TableRefToken aTableRefToken; |
454 | 15 | aTableRefToken.Index = static_cast<sal_Int32>( pTR->GetIndex()); |
455 | 15 | aTableRefToken.Item = static_cast<sal_Int16>( pTR->GetItem()); |
456 | 15 | const FormulaToken* pRef = pTR->GetAreaRefRPN(); |
457 | 15 | assert((pRef || bIgnoreTableRefNoInnerReference) |
458 | 15 | && "something forgot to create RPN for ocTableRef inner reference"); |
459 | 15 | (void)bIgnoreTableRefNoInnerReference; |
460 | 15 | if (pRef) |
461 | 15 | { |
462 | 15 | switch (pRef->GetType()) |
463 | 15 | { |
464 | 0 | case svSingleRef: |
465 | 0 | lcl_SingleRefToApi( aTableRefToken.Reference.Reference1, static_cast<const ScSingleRefToken*>(pRef)->GetSingleRef()); |
466 | 0 | aTableRefToken.Reference.Reference2 = aTableRefToken.Reference.Reference1; |
467 | 0 | break; |
468 | 15 | case svDoubleRef: |
469 | 15 | lcl_SingleRefToApi( aTableRefToken.Reference.Reference1, static_cast<const ScDoubleRefToken*>(pRef)->GetSingleRef()); |
470 | 15 | lcl_SingleRefToApi( aTableRefToken.Reference.Reference2, static_cast<const ScDoubleRefToken*>(pRef)->GetSingleRef2()); |
471 | 15 | break; |
472 | 0 | default: |
473 | 0 | ; // nothing |
474 | 15 | } |
475 | 15 | } |
476 | 15 | rAPI.Data <<= aTableRefToken; |
477 | 15 | } |
478 | 316 | else |
479 | 316 | { |
480 | 316 | auto const & rIndexToken = static_cast<const FormulaIndexToken&>(rToken); |
481 | 316 | sheet::NameToken aNameToken; |
482 | 316 | aNameToken.Index = static_cast<sal_Int32>( rIndexToken.GetIndex() ); |
483 | 316 | aNameToken.Sheet = rIndexToken.GetSheet(); |
484 | 316 | rAPI.Data <<= aNameToken; |
485 | 316 | } |
486 | 331 | } |
487 | 331 | break; |
488 | 331 | case svMatrix: |
489 | 6 | if (!ScRangeToSequence::FillMixedArray( rAPI.Data, static_cast<const ScMatrixToken&>(rToken).GetMatrix(), true)) |
490 | 0 | rAPI.Data.clear(); |
491 | 6 | break; |
492 | 27 | case svExternalSingleRef: |
493 | 27 | { |
494 | 27 | const auto & rESRToken = static_cast<const ScExternalSingleRefToken&>(rToken); |
495 | 27 | sheet::SingleReference aSingleRef; |
496 | 27 | lcl_ExternalRefToApi( aSingleRef, rESRToken.GetSingleRef() ); |
497 | 27 | size_t nCacheId; |
498 | 27 | rDoc.GetExternalRefManager()->getCacheTable( |
499 | 27 | rESRToken.GetFileId(), rESRToken.GetTableName().getString(), false, &nCacheId); |
500 | 27 | aSingleRef.Sheet = static_cast< sal_Int32 >( nCacheId ); |
501 | 27 | sheet::ExternalReference aExtRef; |
502 | 27 | aExtRef.Index = rESRToken.GetFileId(); |
503 | 27 | aExtRef.Reference <<= aSingleRef; |
504 | 27 | rAPI.Data <<= aExtRef; |
505 | 27 | eOpCode = ocPush; |
506 | 27 | } |
507 | 27 | break; |
508 | 44 | case svExternalDoubleRef: |
509 | 44 | { |
510 | 44 | const auto & rEDRToken = static_cast<const ScExternalDoubleRefToken&>(rToken); |
511 | 44 | sheet::ComplexReference aComplRef; |
512 | 44 | lcl_ExternalRefToApi( aComplRef.Reference1, rEDRToken.GetSingleRef() ); |
513 | 44 | lcl_ExternalRefToApi( aComplRef.Reference2, rEDRToken.GetSingleRef2() ); |
514 | 44 | size_t nCacheId; |
515 | 44 | rDoc.GetExternalRefManager()->getCacheTable( |
516 | 44 | rEDRToken.GetFileId(), rEDRToken.GetTableName().getString(), false, &nCacheId); |
517 | 44 | aComplRef.Reference1.Sheet = static_cast< sal_Int32 >( nCacheId ); |
518 | | // NOTE: This assumes that cached sheets are in consecutive order! |
519 | 44 | aComplRef.Reference2.Sheet = |
520 | 44 | aComplRef.Reference1.Sheet + |
521 | 44 | (rEDRToken.GetSingleRef2().Tab() - rEDRToken.GetSingleRef().Tab()); |
522 | 44 | sheet::ExternalReference aExtRef; |
523 | 44 | aExtRef.Index = rEDRToken.GetFileId(); |
524 | 44 | aExtRef.Reference <<= aComplRef; |
525 | 44 | rAPI.Data <<= aExtRef; |
526 | 44 | eOpCode = ocPush; |
527 | 44 | } |
528 | 44 | break; |
529 | 0 | case svExternalName: |
530 | 0 | { |
531 | 0 | auto const & rExtNameToken = static_cast<const ScExternalNameToken&>(rToken); |
532 | 0 | sheet::ExternalReference aExtRef; |
533 | 0 | aExtRef.Index = rExtNameToken.GetFileId(); |
534 | 0 | aExtRef.Reference <<= rExtNameToken.GetName().getString(); |
535 | 0 | rAPI.Data <<= aExtRef; |
536 | 0 | eOpCode = ocPush; |
537 | 0 | } |
538 | 0 | break; |
539 | 0 | default: |
540 | 0 | SAL_WARN("sc", "ScTokenConversion::ConvertToTokenSequence: unhandled token type " << StackVarEnumToString(rToken.GetType())); |
541 | 0 | [[fallthrough]]; |
542 | 1.12k | case svError: |
543 | 1.12k | switch (static_cast<const FormulaErrorToken&>(rToken).GetError()) |
544 | 1.12k | { |
545 | 0 | case FormulaError::NoCode: |
546 | 0 | eOpCode = ocErrNull; |
547 | 0 | break; |
548 | 0 | case FormulaError::DivisionByZero: |
549 | 0 | eOpCode = ocErrDivZero; |
550 | 0 | break; |
551 | 0 | case FormulaError::NoValue: |
552 | 0 | eOpCode = ocErrValue; |
553 | 0 | break; |
554 | 1.11k | case FormulaError::NoRef: |
555 | 1.11k | eOpCode = ocErrRef; |
556 | 1.11k | break; |
557 | 0 | case FormulaError::NoName: |
558 | 0 | eOpCode = ocErrName; |
559 | 0 | break; |
560 | 0 | case FormulaError::IllegalFPOperation: |
561 | 0 | eOpCode = ocErrNum; |
562 | 0 | break; |
563 | 8 | case FormulaError::NotAvailable: |
564 | 8 | eOpCode = ocErrNA; |
565 | 8 | break; |
566 | 0 | default: |
567 | 0 | break; |
568 | 1.12k | } |
569 | 1.12k | [[fallthrough]]; |
570 | 1.12k | case svJump: // occurs with ocIf, ocChoose |
571 | 1.12k | case svMissing: // occurs with ocMissing |
572 | 14.5k | case svSep: // occurs with ocSep, ocOpen, ocClose, ocArray* |
573 | 14.5k | rAPI.Data.clear(); // no data |
574 | 33.2k | } |
575 | 33.2k | rAPI.OpCode = static_cast<sal_Int32>(eOpCode); //! assuming equal values for the moment |
576 | 33.2k | } |
577 | 12.1k | } |
578 | 343 | else |
579 | 343 | rSequence.realloc(0); |
580 | 12.4k | } |
581 | | |
582 | | ScFormulaOpCodeMapperObj::ScFormulaOpCodeMapperObj(::std::unique_ptr<formula::FormulaCompiler> && _pCompiler) |
583 | 0 | : formula::FormulaOpCodeMapperObj(std::move(_pCompiler)) |
584 | 0 | { |
585 | 0 | } |
586 | | |
587 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |