Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/sc/source/core/tool/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 17 kB image not shown  

Quelle  interpretercontext.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <interpretercontext.hxx>
#include <svl/numformat.hxx>
#include <svl/zforlist.hxx>

#include <document.hxx>
#include <comphelper/random.hxx>
#include <formula/token.hxx>
#include <lookupcache.hxx>
#include <rangecache.hxx>
#include <algorithm>

ScInterpreterContextPool ScInterpreterContextPool::aThreadedInterpreterPool(true);
ScInterpreterContextPool ScInterpreterContextPool::aNonThreadedInterpreterPool(false);

ScInterpreterContext::ScInterpreterContext(const ScDocument& rDoc, SvNumberFormatter* pFormatter)
    : mpDoc(&rDoc)
    , mnTokenCachePos(0)
    , maTokens(TOKEN_CACHE_SIZE, nullptr)
    // create a per-interpreter Random Number Generator, seeded from the global rng, so we don't have
    // to lock a mutex to generate a random number
    , aRNG(comphelper::rng::uniform_uint_distribution(0, std::numeric_limits<sal_uInt32>::max()))
    , pInterpreter(nullptr)
    , mpFormatter(pFormatter)
{
    if (!pFormatter)
    {
        mpFormatData = nullptr;
        mpNatNum = nullptr;
    }
    else
        prepFormatterForRoMode(pFormatter);
}

ScInterpreterContext::~ScInterpreterContext() { ResetTokens(); }

void ScInterpreterContext::ResetTokens()
{
    for (auto p : maTokens)
        if (p)
            p->DecRef();

    mnTokenCachePos = 0;
    std::fill(maTokens.begin(), maTokens.end(), nullptr);
}

void ScInterpreterContext::SetDocAndFormatter(const ScDocument& rDoc, SvNumberFormatter* pFormatter)
{
    if (mpDoc != &rDoc)
    {
        mxScLookupCache.reset();
        mpDoc = &rDoc;
    }
    if (mpFormatter != pFormatter)
    {
        mpFormatter = pFormatter;

        // formatter has changed
        prepFormatterForRoMode(pFormatter);

        // drop cache
        std::fill(maNFBuiltInCache.begin(), maNFBuiltInCache.end(), NFBuiltIn());
        std::fill(maNFTypeCache.begin(), maNFTypeCache.end(), NFType());
    }
}

void ScInterpreterContext::prepFormatterForRoMode(SvNumberFormatter* pFormatter)
{
    pFormatter->PrepForRoMode();
    mpFormatData = &pFormatter->GetROFormatData();
    mpNatNum = &pFormatter->GetNatNum();
    mxLanguageData.reset(new SvNFLanguageData(pFormatter->GetROLanguageData()));
    mxAuxFormatKeyMap.reset(new SvNFFormatData::DefaultFormatKeysMap);
    maROPolicy = SvNFEngine::GetROPolicy(*mpFormatData, *mxAuxFormatKeyMap);
}

void ScInterpreterContext::initFormatTable()
{
    mpFormatter = mpDoc->GetFormatTable(); // will assert if not main thread
    prepFormatterForRoMode(mpFormatter);
}

void ScInterpreterContext::MergeDefaultFormatKeys(SvNumberFormatter& rFormatter) const
{
    rFormatter.MergeDefaultFormatKeys(*mxAuxFormatKeyMap);
}

void ScInterpreterContext::Cleanup()
{
    // Do not disturb mxScLookupCache.
    maConditions.clear();
    maDelayedSetNumberFormat.clear();
    ResetTokens();
}

void ScInterpreterContext::ClearLookupCache(const ScDocument* pDoc)
{
    if (pDoc == mpDoc)
    {
        mxScLookupCache.reset();
        mxLanguageData.reset();
        mxAuxFormatKeyMap.reset();
        mpFormatter = nullptr;
        mpFormatData = nullptr;
        mpNatNum = nullptr;
    }
}

SvNumFormatType ScInterpreterContext::NFGetType(sal_uInt32 nFIndex) const
{
    if (!mpDoc->IsThreadedGroupCalcInProgress())
        return GetFormatTable()->GetType(nFIndex);

    auto aFind = std::find_if(maNFTypeCache.begin(), maNFTypeCache.end(),
                              [nFIndex](const NFType& e) { return e.nKey == nFIndex; });
    if (aFind != maNFTypeCache.end())
        return aFind->eType;

    SvNumFormatType eType = mpFormatData->GetType(nFIndex);

    std::move_backward(maNFTypeCache.begin(),
                       std::next(maNFTypeCache.begin(), maNFTypeCache.size() - 1),
                       maNFTypeCache.end());
    maNFTypeCache[0].nKey = nFIndex;
    maNFTypeCache[0].eType = eType;

    return eType;
}

const SvNumberformat* ScInterpreterContext::NFGetFormatEntry(sal_uInt32 nKey) const
{
    if (!mpDoc->IsThreadedGroupCalcInProgress())
        return GetFormatTable()->GetEntry(nKey);
    return mpFormatData->GetFormatEntry(nKey);
}

bool ScInterpreterContext::NFIsTextFormat(sal_uInt32 nFIndex) const
{
    if (!mpDoc->IsThreadedGroupCalcInProgress())
        return GetFormatTable()->IsTextFormat(nFIndex);
    return mpFormatData->IsTextFormat(nFIndex);
}

const Date& ScInterpreterContext::NFGetNullDate() const
{
    if (!mpDoc->IsThreadedGroupCalcInProgress())
        return GetFormatTable()->GetNullDate();
    return mxLanguageData->GetNullDate();
}

sal_uInt32 ScInterpreterContext::NFGetTimeFormat(double fNumber, LanguageType eLnge,
                                                 bool bForceDuration) const
{
    if (!mpDoc->IsThreadedGroupCalcInProgress())
        return GetFormatTable()->GetTimeFormat(fNumber, eLnge, bForceDuration);
    return SvNFEngine::GetTimeFormat(*mxLanguageData, *mpFormatData, *mpNatNum, maROPolicy, fNumber,
                                     eLnge, bForceDuration);
}

sal_uInt32 ScInterpreterContext::NFGetFormatIndex(NfIndexTableOffset nTabOff,
                                                  LanguageType eLnge) const
{
    if (!mpDoc->IsThreadedGroupCalcInProgress())
        return GetFormatTable()->GetFormatIndex(nTabOff, eLnge);
    return SvNFEngine::GetFormatIndex(*mxLanguageData, maROPolicy, *mpNatNum, nTabOff, eLnge);
}
OUString ScInterpreterContext::NFGetFormatDecimalSep(sal_uInt32 nFormat) const
{
    if (!mpDoc->IsThreadedGroupCalcInProgress())
        return GetFormatTable()->GetFormatDecimalSep(nFormat);
    return SvNFEngine::GetFormatDecimalSep(*mxLanguageData, *mpFormatData, nFormat);
}

sal_uInt16 ScInterpreterContext::NFGetFormatPrecision(sal_uInt32 nFormat) const
{
    if (!mpDoc->IsThreadedGroupCalcInProgress())
        return GetFormatTable()->GetFormatPrecision(nFormat);
    return SvNFEngine::GetFormatPrecision(*mxLanguageData, *mpFormatData, nFormat);
}

sal_uInt32 ScInterpreterContext::NFGetFormatForLanguageIfBuiltIn(sal_uInt32 nFormat,
                                                                 LanguageType eLnge) const
{
    if (!mpDoc->IsThreadedGroupCalcInProgress())
        return GetFormatTable()->GetFormatForLanguageIfBuiltIn(nFormat, eLnge);

    sal_uInt64 nKey = (static_cast<sal_uInt64>(nFormat) << 32) | eLnge.get();

    auto aFind = std::find_if(maNFBuiltInCache.begin(), maNFBuiltInCache.end(),
                              [nKey](const NFBuiltIn& e) { return e.nKey == nKey; });
    if (aFind != maNFBuiltInCache.end())
        return aFind->nFormat;

    nFormat = SvNFEngine::GetFormatForLanguageIfBuiltIn(*mxLanguageData, *mpNatNum, maROPolicy,
                                                        nFormat, eLnge);

    std::move_backward(maNFBuiltInCache.begin(),
                       std::next(maNFBuiltInCache.begin(), maNFBuiltInCache.size() - 1),
                       maNFBuiltInCache.end());
    maNFBuiltInCache[0].nKey = nKey;
    maNFBuiltInCache[0].nFormat = nFormat;

    return nFormat;
}

sal_uInt32 ScInterpreterContext::NFGetStandardFormat(SvNumFormatType eType, LanguageType eLnge)
{
    if (!mpDoc->IsThreadedGroupCalcInProgress())
        return GetFormatTable()->GetStandardFormat(eType, eLnge);
    return SvNFEngine::GetStandardFormat(*mxLanguageData, *mpFormatData, *mpNatNum, maROPolicy,
                                         eType, eLnge);
}

sal_uInt32 ScInterpreterContext::NFGetStandardFormat(sal_uInt32 nFIndex, SvNumFormatType eType,
                                                     LanguageType eLnge)
{
    if (!mpDoc->IsThreadedGroupCalcInProgress())
        return GetFormatTable()->GetStandardFormat(nFIndex, eType, eLnge);
    return SvNFEngine::GetStandardFormat(*mxLanguageData, *mpFormatData, *mpNatNum, maROPolicy,
                                         nFIndex, eType, eLnge);
}

OUString ScInterpreterContext::NFGetInputLineString(const double& fOutNumber, sal_uInt32 nFIndex,
                                                    bool bFiltering, bool bForceSystemLocale) const
{
    if (!mpDoc->IsThreadedGroupCalcInProgress())
        return GetFormatTable()->GetInputLineString(fOutNumber, nFIndex, bFiltering,
                                                    bForceSystemLocale);
    return SvNFEngine::GetInputLineString(*mxLanguageData, *mpFormatData, *mpNatNum, maROPolicy,
                                          fOutNumber, nFIndex, bFiltering, bForceSystemLocale);
}
void ScInterpreterContext::NFGetOutputString(const double& fOutNumber, sal_uInt32 nFIndex,
                                             OUString& sOutString, const Color** ppColor,
                                             bool bUseStarFormat) const
{
    if (!mpDoc->IsThreadedGroupCalcInProgress())
        return GetFormatTable()->GetOutputString(fOutNumber, nFIndex, sOutString, ppColor,
                                                 bUseStarFormat);
    return SvNFEngine::GetOutputString(*mxLanguageData, *mpFormatData, *mpNatNum, maROPolicy,
                                       fOutNumber, nFIndex, sOutString, ppColor, bUseStarFormat);
}

void ScInterpreterContext::NFGetOutputString(const OUString& sString, sal_uInt32 nFIndex,
                                             OUString& sOutString, const Color** ppColor,
                                             bool bUseStarFormat) const
{
    if (!mpDoc->IsThreadedGroupCalcInProgress())
        return GetFormatTable()->GetOutputString(sString, nFIndex, sOutString, ppColor,
                                                 bUseStarFormat);
    return SvNFEngine::GetOutputString(*mxLanguageData, *mpFormatData, sString, nFIndex, sOutString,
                                       ppColor, bUseStarFormat);
}

sal_uInt32 ScInterpreterContext::NFGetStandardIndex(LanguageType eLnge) const
{
    if (!mpDoc->IsThreadedGroupCalcInProgress())
        return GetFormatTable()->GetStandardIndex(eLnge);
    return SvNFEngine::GetStandardIndex(*mxLanguageData, *mpFormatData, *mpNatNum, maROPolicy,
                                        eLnge);
}

bool ScInterpreterContext::NFGetPreviewString(const OUString& sFormatString, double fPreviewNumber,
                                              OUString& sOutString, const Color** ppColor,
                                              LanguageType eLnge)
{
    if (!mpDoc->IsThreadedGroupCalcInProgress())
        return GetFormatTable()->GetPreviewString(sFormatString, fPreviewNumber, sOutString,
                                                  ppColor, eLnge);
    return SvNFEngine::GetPreviewString(*mxLanguageData, *mpFormatData, *mpNatNum, maROPolicy,
                                        sFormatString, fPreviewNumber, sOutString, ppColor, eLnge,
                                        false);
}
bool ScInterpreterContext::NFGetPreviewString(const OUString& sFormatString,
                                              const OUString& sPreviewString, OUString& sOutString,
                                              const Color** ppColor, LanguageType eLnge)
{
    if (!mpDoc->IsThreadedGroupCalcInProgress())
        return GetFormatTable()->GetPreviewString(sFormatString, sPreviewString, sOutString,
                                                  ppColor, eLnge);
    return SvNFEngine::GetPreviewString(*mxLanguageData, *mpFormatData, *mpNatNum, maROPolicy,
                                        sFormatString, sPreviewString, sOutString, ppColor, eLnge);
}

bool ScInterpreterContext::NFGetPreviewStringGuess(const OUString& sFormatString,
                                                   double fPreviewNumber, OUString& sOutString,
                                                   const Color** ppColor, LanguageType eLnge)
{
    if (!mpDoc->IsThreadedGroupCalcInProgress())
        return GetFormatTable()->GetPreviewStringGuess(sFormatString, fPreviewNumber, sOutString,
                                                       ppColor, eLnge);
    return SvNFEngine::GetPreviewStringGuess(*mxLanguageData, *mpFormatData, *mpNatNum, maROPolicy,
                                             sFormatString, fPreviewNumber, sOutString, ppColor,
                                             eLnge);
}

OUString ScInterpreterContext::NFGenerateFormat(sal_uInt32 nIndex, LanguageType eLnge,
                                                bool bThousand, bool bIsRed, sal_uInt16 nPrecision,
                                                sal_uInt16 nLeadingCnt)
{
    if (!mpDoc->IsThreadedGroupCalcInProgress())
        return GetFormatTable()->GenerateFormat(nIndex, eLnge, bThousand, bIsRed, nPrecision,
                                                nLeadingCnt);
    return SvNFEngine::GenerateFormat(*mxLanguageData, *mpFormatData, *mpNatNum, maROPolicy, nIndex,
                                      eLnge, bThousand, bIsRed, nPrecision, nLeadingCnt);
}
OUString ScInterpreterContext::NFGetCalcCellReturn(sal_uInt32 nFormat) const
{
    if (!mpDoc->IsThreadedGroupCalcInProgress())
        return GetFormatTable()->GetCalcCellReturn(nFormat);
    return mpFormatData->GetCalcCellReturn(nFormat);
}

sal_uInt16 ScInterpreterContext::NFExpandTwoDigitYear(sal_uInt16 nYear) const
{
    if (!mpDoc->IsThreadedGroupCalcInProgress())
        return GetFormatTable()->ExpandTwoDigitYear(nYear);
    return mxLanguageData->ExpandTwoDigitYear(nYear);
}

bool ScInterpreterContext::NFIsNumberFormat(const OUString& sString, sal_uInt32&&nbsp;F_Index,
                                            double& fOutNumber, SvNumInputOptions eInputOptions)
{
    if (!mpDoc->IsThreadedGroupCalcInProgress())
        return GetFormatTable()->IsNumberFormat(sString, F_Index, fOutNumber, eInputOptions);
    return SvNFEngine::IsNumberFormat(*mxLanguageData, *mpFormatData, *mpNatNum, maROPolicy,
                                      sString, F_Index, fOutNumber, eInputOptions);
}

/* ScInterpreterContextPool */

// Threaded version
void ScInterpreterContextPool::Init(size_t nNumThreads, const ScDocument& rDoc,
                                    SvNumberFormatter* pFormatter)
{
    assert(mbThreaded);
    size_t nOldSize = maPool.size();
    maPool.resize(nNumThreads);
    for (size_t nIdx = 0; nIdx < nNumThreads; ++nIdx)
    {
        if (nIdx >= nOldSize)
            maPool[nIdx].reset(new ScInterpreterContext(rDoc, pFormatter));
        else
            maPool[nIdx]->SetDocAndFormatter(rDoc, pFormatter);
    }
}

ScInterpreterContext*
ScInterpreterContextPool::GetInterpreterContextForThreadIdx(size_t nThreadIdx) const
{
    assert(mbThreaded);
    assert(nThreadIdx < maPool.size());
    return maPool[nThreadIdx].get();
}

// Non-Threaded version
void ScInterpreterContextPool::Init(const ScDocument& rDoc, SvNumberFormatter* pFormatter)
{
    assert(!mbThreaded);
    assert(mnNextFree <= maPool.size());
    bool bCreateNew = (maPool.size() == mnNextFree);
    size_t nCurrIdx = mnNextFree;
    if (bCreateNew)
    {
        maPool.resize(maPool.size() + 1);
        maPool[nCurrIdx].reset(new ScInterpreterContext(rDoc, pFormatter));
    }
    else
        maPool[nCurrIdx]->SetDocAndFormatter(rDoc, pFormatter);

    ++mnNextFree;
}

ScInterpreterContext* ScInterpreterContextPool::GetInterpreterContext() const
{
    assert(!mbThreaded);
    assert(mnNextFree && (mnNextFree <= maPool.size()));
    return maPool[mnNextFree - 1].get();
}

void ScInterpreterContextPool::ReturnToPool()
{
    if (mbThreaded)
    {
        for (size_t nIdx = 0; nIdx < maPool.size(); ++nIdx)
            maPool[nIdx]->Cleanup();
    }
    else
    {
        assert(mnNextFree && (mnNextFree <= maPool.size()));
        --mnNextFree;
        maPool[mnNextFree]->Cleanup();
    }
}

// static
void ScInterpreterContextPool::ClearLookupCaches(const ScDocument* pDoc)
{
    for (auto& rPtr : aThreadedInterpreterPool.maPool)
        rPtr->ClearLookupCache(pDoc);
    for (auto& rPtr : aNonThreadedInterpreterPool.maPool)
        rPtr->ClearLookupCache(pDoc);
}

// static
void ScInterpreterContextPool::ModuleExiting()
{
    for (auto& rPtr : aThreadedInterpreterPool.maPool)
        rPtr->mxLanguageData.reset();
    for (auto& rPtr : aNonThreadedInterpreterPool.maPool)
        rPtr->mxLanguageData.reset();
}

/* ScThreadedInterpreterContextGetterGuard */

ScThreadedInterpreterContextGetterGuard::ScThreadedInterpreterContextGetterGuard(
    size_t nNumThreads, const ScDocument& rDoc, SvNumberFormatter* pFormatter)
    : rPool(ScInterpreterContextPool::aThreadedInterpreterPool)
{
    rPool.Init(nNumThreads, rDoc, pFormatter);
}

ScThreadedInterpreterContextGetterGuard::~ScThreadedInterpreterContextGetterGuard()
{
    rPool.ReturnToPool();
}

ScInterpreterContext*
ScThreadedInterpreterContextGetterGuard::GetInterpreterContextForThreadIdx(size_t nThreadIdx) const
{
    return rPool.GetInterpreterContextForThreadIdx(nThreadIdx);
}

/* ScInterpreterContextGetterGuard */

ScInterpreterContextGetterGuard::ScInterpreterContextGetterGuard(const ScDocument&&nbsp;rDoc,
                                                                 SvNumberFormatter* pFormatter)
    : rPool(ScInterpreterContextPool::aNonThreadedInterpreterPool)
#if !defined NDEBUG
    , nContextIdx(rPool.mnNextFree)
#endif
{
    rPool.Init(rDoc, pFormatter);
}

ScInterpreterContextGetterGuard::~ScInterpreterContextGetterGuard()
{
    assert(nContextIdx == (rPool.mnNextFree - 1));
    rPool.ReturnToPool();
}

ScInterpreterContext* ScInterpreterContextGetterGuard::GetInterpreterContext() const
{
    return rPool.GetInterpreterContext();
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=96 H=92 G=93

¤ Dauer der Verarbeitung: 0.6 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.