Resolves: tdf#162093 TableRef item specifier may occur standalone
[LibreOffice.git] / sc / source / core / tool / interpretercontext.cxx
blob26aaeaf3e8e6658a2f13ca3ffba57c45db2d9430
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <interpretercontext.hxx>
21 #include <svl/numformat.hxx>
22 #include <svl/zforlist.hxx>
24 #include <document.hxx>
25 #include <comphelper/random.hxx>
26 #include <formula/token.hxx>
27 #include <lookupcache.hxx>
28 #include <rangecache.hxx>
29 #include <algorithm>
31 ScInterpreterContextPool ScInterpreterContextPool::aThreadedInterpreterPool(true);
32 ScInterpreterContextPool ScInterpreterContextPool::aNonThreadedInterpreterPool(false);
34 ScInterpreterContext::ScInterpreterContext(const ScDocument& rDoc, SvNumberFormatter* pFormatter)
35 : mpDoc(&rDoc)
36 , mnTokenCachePos(0)
37 , maTokens(TOKEN_CACHE_SIZE, nullptr)
38 // create a per-interpreter Random Number Generator, seeded from the global rng, so we don't have
39 // to lock a mutex to generate a random number
40 , aRNG(comphelper::rng::uniform_uint_distribution(0, std::numeric_limits<sal_uInt32>::max()))
41 , pInterpreter(nullptr)
42 , mpFormatter(pFormatter)
44 if (!pFormatter)
46 mpFormatData = nullptr;
47 mpNatNum = nullptr;
49 else
50 prepFormatterForRoMode(pFormatter);
53 ScInterpreterContext::~ScInterpreterContext() { ResetTokens(); }
55 void ScInterpreterContext::ResetTokens()
57 for (auto p : maTokens)
58 if (p)
59 p->DecRef();
61 mnTokenCachePos = 0;
62 std::fill(maTokens.begin(), maTokens.end(), nullptr);
65 void ScInterpreterContext::SetDocAndFormatter(const ScDocument& rDoc, SvNumberFormatter* pFormatter)
67 if (mpDoc != &rDoc)
69 mxScLookupCache.reset();
70 mpDoc = &rDoc;
72 if (mpFormatter != pFormatter)
74 mpFormatter = pFormatter;
76 // formatter has changed
77 prepFormatterForRoMode(pFormatter);
79 // drop cache
80 std::fill(maNFBuiltInCache.begin(), maNFBuiltInCache.end(), NFBuiltIn());
81 std::fill(maNFTypeCache.begin(), maNFTypeCache.end(), NFType());
85 void ScInterpreterContext::prepFormatterForRoMode(SvNumberFormatter* pFormatter)
87 pFormatter->PrepForRoMode();
88 mpFormatData = &pFormatter->GetROFormatData();
89 mpNatNum = &pFormatter->GetNatNum();
90 mxLanguageData.reset(new SvNFLanguageData(pFormatter->GetROLanguageData()));
91 mxAuxFormatKeyMap.reset(new SvNFFormatData::DefaultFormatKeysMap);
92 maROPolicy = SvNFEngine::GetROPolicy(*mpFormatData, *mxAuxFormatKeyMap);
95 void ScInterpreterContext::initFormatTable()
97 mpFormatter = mpDoc->GetFormatTable(); // will assert if not main thread
98 prepFormatterForRoMode(mpFormatter);
101 void ScInterpreterContext::MergeDefaultFormatKeys(SvNumberFormatter& rFormatter) const
103 rFormatter.MergeDefaultFormatKeys(*mxAuxFormatKeyMap);
106 void ScInterpreterContext::Cleanup()
108 // Do not disturb mxScLookupCache.
109 maConditions.clear();
110 maDelayedSetNumberFormat.clear();
111 ResetTokens();
114 void ScInterpreterContext::ClearLookupCache(const ScDocument* pDoc)
116 if (pDoc == mpDoc)
118 mxScLookupCache.reset();
119 mxLanguageData.reset();
120 mxAuxFormatKeyMap.reset();
121 mpFormatter = nullptr;
122 mpFormatData = nullptr;
123 mpNatNum = nullptr;
127 SvNumFormatType ScInterpreterContext::NFGetType(sal_uInt32 nFIndex) const
129 if (!mpDoc->IsThreadedGroupCalcInProgress())
130 return GetFormatTable()->GetType(nFIndex);
132 auto aFind = std::find_if(maNFTypeCache.begin(), maNFTypeCache.end(),
133 [nFIndex](const NFType& e) { return e.nKey == nFIndex; });
134 if (aFind != maNFTypeCache.end())
135 return aFind->eType;
137 SvNumFormatType eType = mpFormatData->GetType(nFIndex);
139 std::move_backward(maNFTypeCache.begin(),
140 std::next(maNFTypeCache.begin(), maNFTypeCache.size() - 1),
141 maNFTypeCache.end());
142 maNFTypeCache[0].nKey = nFIndex;
143 maNFTypeCache[0].eType = eType;
145 return eType;
148 const SvNumberformat* ScInterpreterContext::NFGetFormatEntry(sal_uInt32 nKey) const
150 if (!mpDoc->IsThreadedGroupCalcInProgress())
151 return GetFormatTable()->GetEntry(nKey);
152 return mpFormatData->GetFormatEntry(nKey);
155 bool ScInterpreterContext::NFIsTextFormat(sal_uInt32 nFIndex) const
157 if (!mpDoc->IsThreadedGroupCalcInProgress())
158 return GetFormatTable()->IsTextFormat(nFIndex);
159 return mpFormatData->IsTextFormat(nFIndex);
162 const Date& ScInterpreterContext::NFGetNullDate() const
164 if (!mpDoc->IsThreadedGroupCalcInProgress())
165 return GetFormatTable()->GetNullDate();
166 return mxLanguageData->GetNullDate();
169 sal_uInt32 ScInterpreterContext::NFGetTimeFormat(double fNumber, LanguageType eLnge,
170 bool bForceDuration) const
172 if (!mpDoc->IsThreadedGroupCalcInProgress())
173 return GetFormatTable()->GetTimeFormat(fNumber, eLnge, bForceDuration);
174 return SvNFEngine::GetTimeFormat(*mxLanguageData, *mpFormatData, *mpNatNum, maROPolicy, fNumber,
175 eLnge, bForceDuration);
178 sal_uInt32 ScInterpreterContext::NFGetFormatIndex(NfIndexTableOffset nTabOff,
179 LanguageType eLnge) const
181 if (!mpDoc->IsThreadedGroupCalcInProgress())
182 return GetFormatTable()->GetFormatIndex(nTabOff, eLnge);
183 return SvNFEngine::GetFormatIndex(*mxLanguageData, maROPolicy, *mpNatNum, nTabOff, eLnge);
185 OUString ScInterpreterContext::NFGetFormatDecimalSep(sal_uInt32 nFormat) const
187 if (!mpDoc->IsThreadedGroupCalcInProgress())
188 return GetFormatTable()->GetFormatDecimalSep(nFormat);
189 return SvNFEngine::GetFormatDecimalSep(*mxLanguageData, *mpFormatData, nFormat);
192 sal_uInt16 ScInterpreterContext::NFGetFormatPrecision(sal_uInt32 nFormat) const
194 if (!mpDoc->IsThreadedGroupCalcInProgress())
195 return GetFormatTable()->GetFormatPrecision(nFormat);
196 return SvNFEngine::GetFormatPrecision(*mxLanguageData, *mpFormatData, nFormat);
199 sal_uInt32 ScInterpreterContext::NFGetFormatForLanguageIfBuiltIn(sal_uInt32 nFormat,
200 LanguageType eLnge) const
202 if (!mpDoc->IsThreadedGroupCalcInProgress())
203 return GetFormatTable()->GetFormatForLanguageIfBuiltIn(nFormat, eLnge);
205 sal_uInt64 nKey = (static_cast<sal_uInt64>(nFormat) << 32) | eLnge.get();
207 auto aFind = std::find_if(maNFBuiltInCache.begin(), maNFBuiltInCache.end(),
208 [nKey](const NFBuiltIn& e) { return e.nKey == nKey; });
209 if (aFind != maNFBuiltInCache.end())
210 return aFind->nFormat;
212 nFormat = SvNFEngine::GetFormatForLanguageIfBuiltIn(*mxLanguageData, *mpNatNum, maROPolicy,
213 nFormat, eLnge);
215 std::move_backward(maNFBuiltInCache.begin(),
216 std::next(maNFBuiltInCache.begin(), maNFBuiltInCache.size() - 1),
217 maNFBuiltInCache.end());
218 maNFBuiltInCache[0].nKey = nKey;
219 maNFBuiltInCache[0].nFormat = nFormat;
221 return nFormat;
224 sal_uInt32 ScInterpreterContext::NFGetStandardFormat(SvNumFormatType eType, LanguageType eLnge)
226 if (!mpDoc->IsThreadedGroupCalcInProgress())
227 return GetFormatTable()->GetStandardFormat(eType, eLnge);
228 return SvNFEngine::GetStandardFormat(*mxLanguageData, *mpFormatData, *mpNatNum, maROPolicy,
229 eType, eLnge);
232 sal_uInt32 ScInterpreterContext::NFGetStandardFormat(sal_uInt32 nFIndex, SvNumFormatType eType,
233 LanguageType eLnge)
235 if (!mpDoc->IsThreadedGroupCalcInProgress())
236 return GetFormatTable()->GetStandardFormat(nFIndex, eType, eLnge);
237 return SvNFEngine::GetStandardFormat(*mxLanguageData, *mpFormatData, *mpNatNum, maROPolicy,
238 nFIndex, eType, eLnge);
241 void ScInterpreterContext::NFGetInputLineString(const double& fOutNumber, sal_uInt32 nFIndex,
242 OUString& rOutString, bool bFiltering,
243 bool bForceSystemLocale) const
245 if (!mpDoc->IsThreadedGroupCalcInProgress())
246 return GetFormatTable()->GetInputLineString(fOutNumber, nFIndex, rOutString, bFiltering,
247 bForceSystemLocale);
248 return SvNFEngine::GetInputLineString(*mxLanguageData, *mpFormatData, *mpNatNum, maROPolicy,
249 fOutNumber, nFIndex, rOutString, bFiltering,
250 bForceSystemLocale);
252 void ScInterpreterContext::NFGetOutputString(const double& fOutNumber, sal_uInt32 nFIndex,
253 OUString& sOutString, const Color** ppColor,
254 bool bUseStarFormat) const
256 if (!mpDoc->IsThreadedGroupCalcInProgress())
257 return GetFormatTable()->GetOutputString(fOutNumber, nFIndex, sOutString, ppColor,
258 bUseStarFormat);
259 return SvNFEngine::GetOutputString(*mxLanguageData, *mpFormatData, *mpNatNum, maROPolicy,
260 fOutNumber, nFIndex, sOutString, ppColor, bUseStarFormat);
263 void ScInterpreterContext::NFGetOutputString(const OUString& sString, sal_uInt32 nFIndex,
264 OUString& sOutString, const Color** ppColor,
265 bool bUseStarFormat) const
267 if (!mpDoc->IsThreadedGroupCalcInProgress())
268 return GetFormatTable()->GetOutputString(sString, nFIndex, sOutString, ppColor,
269 bUseStarFormat);
270 return SvNFEngine::GetOutputString(*mxLanguageData, *mpFormatData, sString, nFIndex, sOutString,
271 ppColor, bUseStarFormat);
274 sal_uInt32 ScInterpreterContext::NFGetStandardIndex(LanguageType eLnge) const
276 if (!mpDoc->IsThreadedGroupCalcInProgress())
277 return GetFormatTable()->GetStandardIndex(eLnge);
278 return SvNFEngine::GetStandardIndex(*mxLanguageData, *mpFormatData, *mpNatNum, maROPolicy,
279 eLnge);
282 bool ScInterpreterContext::NFGetPreviewString(const OUString& sFormatString, double fPreviewNumber,
283 OUString& sOutString, const Color** ppColor,
284 LanguageType eLnge)
286 if (!mpDoc->IsThreadedGroupCalcInProgress())
287 return GetFormatTable()->GetPreviewString(sFormatString, fPreviewNumber, sOutString,
288 ppColor, eLnge);
289 return SvNFEngine::GetPreviewString(*mxLanguageData, *mpFormatData, *mpNatNum, maROPolicy,
290 sFormatString, fPreviewNumber, sOutString, ppColor, eLnge,
291 false);
293 bool ScInterpreterContext::NFGetPreviewString(const OUString& sFormatString,
294 const OUString& sPreviewString, OUString& sOutString,
295 const Color** ppColor, LanguageType eLnge)
297 if (!mpDoc->IsThreadedGroupCalcInProgress())
298 return GetFormatTable()->GetPreviewString(sFormatString, sPreviewString, sOutString,
299 ppColor, eLnge);
300 return SvNFEngine::GetPreviewString(*mxLanguageData, *mpFormatData, *mpNatNum, maROPolicy,
301 sFormatString, sPreviewString, sOutString, ppColor, eLnge);
304 bool ScInterpreterContext::NFGetPreviewStringGuess(const OUString& sFormatString,
305 double fPreviewNumber, OUString& sOutString,
306 const Color** ppColor, LanguageType eLnge)
308 if (!mpDoc->IsThreadedGroupCalcInProgress())
309 return GetFormatTable()->GetPreviewStringGuess(sFormatString, fPreviewNumber, sOutString,
310 ppColor, eLnge);
311 return SvNFEngine::GetPreviewStringGuess(*mxLanguageData, *mpFormatData, *mpNatNum, maROPolicy,
312 sFormatString, fPreviewNumber, sOutString, ppColor,
313 eLnge);
316 OUString ScInterpreterContext::NFGenerateFormat(sal_uInt32 nIndex, LanguageType eLnge,
317 bool bThousand, bool bIsRed, sal_uInt16 nPrecision,
318 sal_uInt16 nLeadingCnt)
320 if (!mpDoc->IsThreadedGroupCalcInProgress())
321 return GetFormatTable()->GenerateFormat(nIndex, eLnge, bThousand, bIsRed, nPrecision,
322 nLeadingCnt);
323 return SvNFEngine::GenerateFormat(*mxLanguageData, *mpFormatData, *mpNatNum, maROPolicy, nIndex,
324 eLnge, bThousand, bIsRed, nPrecision, nLeadingCnt);
326 OUString ScInterpreterContext::NFGetCalcCellReturn(sal_uInt32 nFormat) const
328 if (!mpDoc->IsThreadedGroupCalcInProgress())
329 return GetFormatTable()->GetCalcCellReturn(nFormat);
330 return mpFormatData->GetCalcCellReturn(nFormat);
333 sal_uInt16 ScInterpreterContext::NFExpandTwoDigitYear(sal_uInt16 nYear) const
335 if (!mpDoc->IsThreadedGroupCalcInProgress())
336 return GetFormatTable()->ExpandTwoDigitYear(nYear);
337 return mxLanguageData->ExpandTwoDigitYear(nYear);
340 bool ScInterpreterContext::NFIsNumberFormat(const OUString& sString, sal_uInt32& F_Index,
341 double& fOutNumber, SvNumInputOptions eInputOptions)
343 if (!mpDoc->IsThreadedGroupCalcInProgress())
344 return GetFormatTable()->IsNumberFormat(sString, F_Index, fOutNumber, eInputOptions);
345 return SvNFEngine::IsNumberFormat(*mxLanguageData, *mpFormatData, *mpNatNum, maROPolicy,
346 sString, F_Index, fOutNumber, eInputOptions);
349 /* ScInterpreterContextPool */
351 // Threaded version
352 void ScInterpreterContextPool::Init(size_t nNumThreads, const ScDocument& rDoc,
353 SvNumberFormatter* pFormatter)
355 assert(mbThreaded);
356 size_t nOldSize = maPool.size();
357 maPool.resize(nNumThreads);
358 for (size_t nIdx = 0; nIdx < nNumThreads; ++nIdx)
360 if (nIdx >= nOldSize)
361 maPool[nIdx].reset(new ScInterpreterContext(rDoc, pFormatter));
362 else
363 maPool[nIdx]->SetDocAndFormatter(rDoc, pFormatter);
367 ScInterpreterContext*
368 ScInterpreterContextPool::GetInterpreterContextForThreadIdx(size_t nThreadIdx) const
370 assert(mbThreaded);
371 assert(nThreadIdx < maPool.size());
372 return maPool[nThreadIdx].get();
375 // Non-Threaded version
376 void ScInterpreterContextPool::Init(const ScDocument& rDoc, SvNumberFormatter* pFormatter)
378 assert(!mbThreaded);
379 assert(mnNextFree <= maPool.size());
380 bool bCreateNew = (maPool.size() == mnNextFree);
381 size_t nCurrIdx = mnNextFree;
382 if (bCreateNew)
384 maPool.resize(maPool.size() + 1);
385 maPool[nCurrIdx].reset(new ScInterpreterContext(rDoc, pFormatter));
387 else
388 maPool[nCurrIdx]->SetDocAndFormatter(rDoc, pFormatter);
390 ++mnNextFree;
393 ScInterpreterContext* ScInterpreterContextPool::GetInterpreterContext() const
395 assert(!mbThreaded);
396 assert(mnNextFree && (mnNextFree <= maPool.size()));
397 return maPool[mnNextFree - 1].get();
400 void ScInterpreterContextPool::ReturnToPool()
402 if (mbThreaded)
404 for (size_t nIdx = 0; nIdx < maPool.size(); ++nIdx)
405 maPool[nIdx]->Cleanup();
407 else
409 assert(mnNextFree && (mnNextFree <= maPool.size()));
410 --mnNextFree;
411 maPool[mnNextFree]->Cleanup();
415 // static
416 void ScInterpreterContextPool::ClearLookupCaches(const ScDocument* pDoc)
418 for (auto& rPtr : aThreadedInterpreterPool.maPool)
419 rPtr->ClearLookupCache(pDoc);
420 for (auto& rPtr : aNonThreadedInterpreterPool.maPool)
421 rPtr->ClearLookupCache(pDoc);
424 // static
425 void ScInterpreterContextPool::ModuleExiting()
427 for (auto& rPtr : aThreadedInterpreterPool.maPool)
428 rPtr->mxLanguageData.reset();
429 for (auto& rPtr : aNonThreadedInterpreterPool.maPool)
430 rPtr->mxLanguageData.reset();
433 /* ScThreadedInterpreterContextGetterGuard */
435 ScThreadedInterpreterContextGetterGuard::ScThreadedInterpreterContextGetterGuard(
436 size_t nNumThreads, const ScDocument& rDoc, SvNumberFormatter* pFormatter)
437 : rPool(ScInterpreterContextPool::aThreadedInterpreterPool)
439 rPool.Init(nNumThreads, rDoc, pFormatter);
442 ScThreadedInterpreterContextGetterGuard::~ScThreadedInterpreterContextGetterGuard()
444 rPool.ReturnToPool();
447 ScInterpreterContext*
448 ScThreadedInterpreterContextGetterGuard::GetInterpreterContextForThreadIdx(size_t nThreadIdx) const
450 return rPool.GetInterpreterContextForThreadIdx(nThreadIdx);
453 /* ScInterpreterContextGetterGuard */
455 ScInterpreterContextGetterGuard::ScInterpreterContextGetterGuard(const ScDocument& rDoc,
456 SvNumberFormatter* pFormatter)
457 : rPool(ScInterpreterContextPool::aNonThreadedInterpreterPool)
458 #if !defined NDEBUG
459 , nContextIdx(rPool.mnNextFree)
460 #endif
462 rPool.Init(rDoc, pFormatter);
465 ScInterpreterContextGetterGuard::~ScInterpreterContextGetterGuard()
467 assert(nContextIdx == (rPool.mnNextFree - 1));
468 rPool.ReturnToPool();
471 ScInterpreterContext* ScInterpreterContextGetterGuard::GetInterpreterContext() const
473 return rPool.GetInterpreterContext();
476 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */