Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  global2.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 <sfx2/docfile.hxx>
#include <sfx2/objsh.hxx>
#include <comphelper/configuration.hxx>
#include <unotools/pathoptions.hxx>
#include <tools/urlobj.hxx>
#include <svl/numformat.hxx>
#include <svl/zforlist.hxx>
#include <formula/errorcodes.hxx>
#include <sal/log.hxx>
#include <rtl/character.hxx>
#include <rtl/math.hxx>
#include <o3tl/string_view.hxx>

#include <global.hxx>
#include <rangeutl.hxx>
#include <compiler.hxx>
#include <paramisc.hxx>
#include <calcconfig.hxx>
#include <interpretercontext.hxx>

// struct ScImportParam:

ScImportParam::ScImportParam() :
    nCol1(0),
    nRow1(0),
    nCol2(0),
    nRow2(0),
    bImport(false),
    bNative(false),
    bSql(true),
    nType(ScDbTable)
{
}

ScImportParam::ScImportParam( const ScImportParam& r ) :
    nCol1       (r.nCol1),
    nRow1       (r.nRow1),
    nCol2       (r.nCol2),
    nRow2       (r.nRow2),
    bImport     (r.bImport),
    aDBName     (r.aDBName),
    aStatement  (r.aStatement),
    bNative     (r.bNative),
    bSql        (r.bSql),
    nType       (r.nType)
{
}

ScImportParam::~ScImportParam()
{
}

ScImportParam& ScImportParam::operator=( const ScImportParam& r )
{
    nCol1           = r.nCol1;
    nRow1           = r.nRow1;
    nCol2           = r.nCol2;
    nRow2           = r.nRow2;
    bImport         = r.bImport;
    aDBName         = r.aDBName;
    aStatement      = r.aStatement;
    bNative         = r.bNative;
    bSql            = r.bSql;
    nType           = r.nType;

    return *this;
}

bool ScImportParam::operator==( const ScImportParam& rOther ) const
{
    return( nCol1       == rOther.nCol1 &&
            nRow1       == rOther.nRow1 &&
            nCol2       == rOther.nCol2 &&
            nRow2       == rOther.nRow2 &&
            bImport     == rOther.bImport &&
            aDBName     == rOther.aDBName &&
            aStatement  == rOther.aStatement &&
            bNative     == rOther.bNative &&
            bSql        == rOther.bSql &&
            nType       == rOther.nType );

    //TODO: are nQuerySh and pConnection equal ?
}

// struct ScConsolidateParam:

ScConsolidateParam::ScConsolidateParam()
{
    Clear();
}

ScConsolidateParam::ScConsolidateParam( const ScConsolidateParam& r )
{
    operator=(r);
}

ScConsolidateParam::~ScConsolidateParam()
{
}

void ScConsolidateParam::ClearDataAreas()
{
    pDataAreas.reset();
    nDataAreaCount = 0;
}

void ScConsolidateParam::Clear()
{
    ClearDataAreas();

    nCol = 0;
    nRow = 0;
    nTab = 0;
    bByCol = bByRow = bReferenceData    = false;
    eFunction                           = SUBTOTAL_FUNC_SUM;
}

ScConsolidateParam& ScConsolidateParam::operator=( const ScConsolidateParam& ;r )
{
    if (this != &r)
    {
        nCol            = r.nCol;
        nRow            = r.nRow;
        nTab            = r.nTab;
        bByCol          = r.bByCol;
        bByRow          = r.bByRow;
        bReferenceData  = r.bReferenceData;
        eFunction       = r.eFunction;
        nDataAreaCount  = r.nDataAreaCount;
        if ( r.nDataAreaCount > 0 )
        {
            nDataAreaCount = r.nDataAreaCount;
            pDataAreas.reset( new ScArea[nDataAreaCount] );
            for ( sal_uInt16 i=0; i<nDataAreaCount; i++ )
                pDataAreas[i] = r.pDataAreas[i];
        }
        else
            pDataAreas.reset();
    }
    return *this;
}

bool ScConsolidateParam::operator==( const ScConsolidateParam& r ) const
{
    bool bEqual =   (nCol           == r.nCol)
                 && (nRow           == r.nRow)
                 && (nTab           == r.nTab)
                 && (bByCol         == r.bByCol)
                 && (bByRow         == r.bByRow)
                 && (bReferenceData == r.bReferenceData)
                 && (nDataAreaCount == r.nDataAreaCount)
                 && (eFunction      == r.eFunction);

    if ( nDataAreaCount == 0 )
        bEqual = bEqual && (pDataAreas == nullptr) && (r.pDataAreas == nullptr);
    else
        bEqual = bEqual && (pDataAreas != nullptr) && (r.pDataAreas != nullptr);

    if ( bEqual && (nDataAreaCount > 0) )
        for ( sal_uInt16 i=0; i<nDataAreaCount && bEqual; i++ )
            bEqual = pDataAreas[i] == r.pDataAreas[i];

    return bEqual;
}

void ScConsolidateParam::SetAreas( std::unique_ptr<ScArea[]> pAreas, sal_uInt16 nCount )
{
    pDataAreas = std::move(pAreas);
    nDataAreaCount = nCount;
}

// struct ScSolveParam

ScSolveParam::ScSolveParam()
{
}

ScSolveParam::ScSolveParam( const ScSolveParam& r )
    :   aRefFormulaCell ( r.aRefFormulaCell ),
        aRefVariableCell( r.aRefVariableCell ),
        pStrTargetVal   ( r.pStrTargetVal )
{
}

ScSolveParam::ScSolveParam( const ScAddress& rFormulaCell,
                            const ScAddress& rVariableCell,
                            const OUString&   rTargetValStr )
    :   aRefFormulaCell ( rFormulaCell ),
        aRefVariableCell( rVariableCell ),
        pStrTargetVal   ( rTargetValStr )
{
}

ScSolveParam::~ScSolveParam()
{
}

ScSolveParam& ScSolveParam::operator=( const ScSolveParam& r )
{
    aRefFormulaCell  = r.aRefFormulaCell;
    aRefVariableCell = r.aRefVariableCell;
    pStrTargetVal = r.pStrTargetVal;
    return *this;
}

bool ScSolveParam::operator==( const ScSolveParam& r ) const
{
    bool bEqual =   (aRefFormulaCell  == r.aRefFormulaCell)
                 && (aRefVariableCell == r.aRefVariableCell);

    if ( bEqual )
    {
        if ( !pStrTargetVal && !r.pStrTargetVal )
            bEqual = true;
        else if ( !pStrTargetVal || !r.pStrTargetVal )
            bEqual = false;
        else
            bEqual = ( *pStrTargetVal == *(r.pStrTargetVal) );
    }

    return bEqual;
}

// struct ScTabOpParam

ScTabOpParam::ScTabOpParam() : meMode(Column) {}

ScTabOpParam::ScTabOpParam( const ScTabOpParam& r )
    :   aRefFormulaCell ( r.aRefFormulaCell ),
        aRefFormulaEnd  ( r.aRefFormulaEnd ),
        aRefRowCell     ( r.aRefRowCell ),
        aRefColCell     ( r.aRefColCell ),
    meMode(r.meMode)
{
}

ScTabOpParam::ScTabOpParam( const ScRefAddress& rFormulaCell,
                            const ScRefAddress& rFormulaEnd,
                            const ScRefAddress& rRowCell,
                            const ScRefAddress& rColCell,
                            Mode eMode )
    :   aRefFormulaCell ( rFormulaCell ),
        aRefFormulaEnd  ( rFormulaEnd ),
        aRefRowCell     ( rRowCell ),
        aRefColCell     ( rColCell ),
    meMode(eMode)
{
}

ScTabOpParam& ScTabOpParam::operator=( const ScTabOpParam& r )
{
    aRefFormulaCell  = r.aRefFormulaCell;
    aRefFormulaEnd   = r.aRefFormulaEnd;
    aRefRowCell      = r.aRefRowCell;
    aRefColCell      = r.aRefColCell;
    meMode = r.meMode;
    return *this;
}

bool ScTabOpParam::operator==( const ScTabOpParam& r ) const
{
    return (        (aRefFormulaCell == r.aRefFormulaCell)
                 && (aRefFormulaEnd  == r.aRefFormulaEnd)
                 && (aRefRowCell     == r.aRefRowCell)
                 && (aRefColCell     == r.aRefColCell)
                 && (meMode == r.meMode) );
}

OUString ScGlobal::GetAbsDocName( const OUString& rFileName,
                                  const SfxObjectShell* pShell )
{
    OUString aAbsName;
    if (!pShell || !pShell->HasName())
    {   // maybe relative to document path working directory
        INetURLObject aObj;
        if (!comphelper::IsFuzzing())
        {
            aObj.SetSmartURL(SvtPathOptions().GetWorkPath());
            aObj.setFinalSlash();       // it IS a path
        }
        else
            aObj.SetSmartURL(u"file:///tmp/document");
        bool bWasAbs = true;
        aAbsName = aObj.smartRel2Abs( rFileName, bWasAbs ).GetMainURL(INetURLObject::DecodeMechanism::NONE);
        //  returned string must be encoded because it's used directly to create SfxMedium
    }
    else
    {
        const SfxMedium* pMedium = pShell->GetMedium();
        if ( pMedium )
        {
            bool bWasAbs = true;
            aAbsName = pMedium->GetURLObject().smartRel2Abs( rFileName, bWasAbs ).GetMainURL(INetURLObject::DecodeMechanism::NONE);
        }
        else
        {   // This can't happen, but ...
            // just to be sure to have the same encoding
            INetURLObject aObj;
            aObj.SetSmartURL( aAbsName );
            aAbsName = aObj.GetMainURL(INetURLObject::DecodeMechanism::NONE);
        }
    }
    return aAbsName;
}

OUString ScGlobal::GetDocTabName( std::u16string_view rFileName,
                                std::u16string_view rTabName )
{
    OUString aDocTab(rFileName);
    // "'Doc'#Tab"
    aDocTab = "'" + aDocTab.replaceAll(u"'", u"\\'") + "'" + OUStringChar(SC_COMPILER_FILE_TAB_SEP) + rTabName;
    return aDocTab;
}

namespace
{
bool isEmptyString( const OUString& rStr )
{
    if (rStr.isEmpty())
        return true;
    else if (rStr[0] == ' ')
    {
        const sal_Unicode* p = rStr.getStr() + 1;
        const sal_Unicode* const pStop = p - 1 + rStr.getLength();
        while (p < pStop && *p == ' ')
            ++p;
        if (p == pStop)
            return true;
    }
    return false;
}
}

double ScGlobal::ConvertStringToValue( const OUString& rStr, const ScCalcConfig&&nbsp;rConfig,
        FormulaError & rError, FormulaError nStringNoValueError,
        ScInterpreterContext& rContext, SvNumFormatType & rCurFmtType )
{
    // We keep ScCalcConfig::StringConversion::LOCALE default until
    // we provide a friendly way to convert string numbers into numbers in the UI.

    double fValue = 0.0;
    if (nStringNoValueError == FormulaError::CellNoValue)
    {
        // Requested that all strings result in 0, error handled by caller.
        rError = nStringNoValueError;
        return fValue;
    }

    switch (rConfig.meStringConversion)
    {
        case ScCalcConfig::StringConversion::ILLEGAL:
            rError = nStringNoValueError;
            return fValue;
        case ScCalcConfig::StringConversion::ZERO:
            return fValue;
        case ScCalcConfig::StringConversion::LOCALE:
            {
                if (rConfig.mbEmptyStringAsZero)
                {
                    // The number scanner does not accept empty strings or strings
                    // containing only spaces, be on par in these cases with what was
                    // accepted in OOo and is in AOO (see also the
                    // StringConversion::UNAMBIGUOUS branch) and convert to 0 to prevent
                    // interoperability nightmares.

                    if (isEmptyString( rStr))
                        return fValue;
                }

                sal_uInt32 nFIndex = 0;
                if (!rContext.NFIsNumberFormat(rStr, nFIndex, fValue))
                {
                    rError = nStringNoValueError;
                    fValue = 0.0;
                }
                return fValue;
            }
            break;
        case ScCalcConfig::StringConversion::UNAMBIGUOUS:
            {
                if (!rConfig.mbEmptyStringAsZero)
                {
                    if (isEmptyString( rStr))
                    {
                        rError = nStringNoValueError;
                        return fValue;
                    }
                }
            }
            // continue below, pulled from switch case for better readability
            break;
    }

    rtl_math_ConversionStatus eStatus;
    sal_Int32 nParseEnd;
    // Decimal and group separator 0 => only integer and possibly exponent,
    // stops at first non-digit non-sign.
    fValue = ::rtl::math::stringToDouble( rStr, 0, 0, &eStatus, &nParseEnd);
    sal_Int32 nLen = rStr.getLength();
    if (eStatus == rtl_math_ConversionStatus_Ok && nParseEnd < nLen)
    {
        // Not at string end, check for trailing blanks or switch to date or
        // time parsing or bail out.
        const sal_Unicode* const pStart = rStr.getStr();
        const sal_Unicode* p = pStart + nParseEnd;
        const sal_Unicode* const pStop = pStart + nLen;
        switch (*p++)
        {
            case ' ':
                while (p < pStop && *p == ' ')
                    ++p;
                if (p < pStop)
                    rError = nStringNoValueError;
                break;
            case '-':
            case ':':
                {
                    bool bDate = (*(p-1) == '-');
                    enum State { year = 0, month, day, hour, minute, second, fraction, done, blank, stop };
                    sal_Int32 nUnit[done] = {0,0,0,0,0,0,0};
                    const sal_Int32 nLimit[done] = {0,12,31,0,59,59,0};
                    State eState = (bDate ? month : minute);
                    rCurFmtType = (bDate ? SvNumFormatType::DATE : SvNumFormatType::TIME);
                    nUnit[eState-1] = o3tl::toInt32(rStr.subView( 0, nParseEnd));
                    const sal_Unicode* pLastStart = p;
                    // Ensure there's no preceding sign. Negative dates
                    // currently aren't handled correctly. Also discard
                    // +CCYY-MM-DD
                    p = pStart;
                    while (p < pStop && *p == ' ')
                        ++p;
                    if (p < pStop && !rtl::isAsciiDigit(*p))
                        rError = nStringNoValueError;
                    p = pLastStart;
                    while (p < pStop && rError == FormulaError::NONE && eState < blank)
                    {
                        if (eState == minute)
                            rCurFmtType |= SvNumFormatType::TIME;
                        if (rtl::isAsciiDigit(*p))
                        {
                            // Maximum 2 digits per unit, except fractions.
                            if (p - pLastStart >= 2 && eState != fraction)
                                rError = nStringNoValueError;
                        }
                        else if (p > pLastStart)
                        {
                            // We had at least one digit.
                            if (eState < done)
                            {
                                nUnit[eState] = o3tl::toInt32(rStr.subView( pLastStart - pStart, p - pLastStart));
                                if (nLimit[eState] && nLimit[eState] < nUnit[eState])
                                    rError = nStringNoValueError;
                            }
                            pLastStart = p + 1;     // hypothetical next start
                            // Delimiters must match, a trailing delimiter
                            // yields an invalid date/time.
                            switch (eState)
                            {
                                case month:
                                    // Month must be followed by separator and
                                    // day, no trailing blanks.
                                    if (*p != '-' || (p+1 == pStop))
                                        rError = nStringNoValueError;
                                    break;
                                case day:
                                    if ((*p != 'T' || (p+1 == pStop)) && *p != ' ')
                                        rError = nStringNoValueError;
                                    // Take one blank as a valid delimiter
                                    // between date and time.
                                    break;
                                case hour:
                                    // Hour must be followed by separator and
                                    // minute, no trailing blanks.
                                    if (*p != ':' || (p+1 == pStop))
                                        rError = nStringNoValueError;
                                    break;
                                case minute:
                                    if ((*p != ':' || (p+1 == pStop)) && *p != ' ')
                                        rError = nStringNoValueError;
                                    if (*p == ' ')
                                        eState = done;
                                    break;
                                case second:
                                    if (((*p != ',' && *p != '.') || (p+1 == pStop)) && *p != ' ')
                                        rError = nStringNoValueError;
                                    if (*p == ' ')
                                        eState = done;
                                    break;
                                case fraction:
                                    eState = done;
                                    break;
                                default:
                                    rError = nStringNoValueError;
                                    break;
                            }
                            eState = static_cast<State>(eState + 1);
                        }
                        else
                            rError = nStringNoValueError;
                        ++p;
                    }
                    if (eState == blank)
                    {
                        while (p < pStop && *p == ' ')
                            ++p;
                        if (p < pStop)
                            rError = nStringNoValueError;
                        eState = stop;
                    }

                    // Month without day, or hour without minute.
                    if (eState == month || (eState == day && p <= pLastStart) ||
                            eState == hour || (eState == minute && p <= pLastStart))
                        rError = nStringNoValueError;

                    if (rError == FormulaError::NONE)
                    {
                        // Catch the very last unit at end of string.
                        if (p > pLastStart && eState < done)
                        {
                            nUnit[eState] = o3tl::toInt32(rStr.subView( pLastStart - pStart, p - pLastStart));
                            if (nLimit[eState] && nLimit[eState] < nUnit[eState])
                                rError = nStringNoValueError;
                        }
                        if (bDate && nUnit[hour] > 23)
                            rError = nStringNoValueError;
                        if (rError == FormulaError::NONE)
                        {
                            if (bDate && nUnit[day] == 0)
                                nUnit[day] = 1;
                            double fFraction = (nUnit[fraction] <= 0 ? 0.0 :
                                    ::rtl::math::pow10Exp( nUnit[fraction],
                                        static_cast<int>( -ceil( log10( static_cast<double>( nUnit[fraction]))))));
                            if (!bDate)
                                fValue = 0.0;
                            else
                            {
                                Date aDate(
                                        sal::static_int_cast<sal_Int16>(nUnit[day]),
                                        sal::static_int_cast<sal_Int16>(nUnit[month]),
                                        sal::static_int_cast<sal_Int16>(nUnit[year]));
                                if (!aDate.IsValidDate())
                                    rError = nStringNoValueError;
                                else
                                {
                                    fValue = aDate - rContext.NFGetNullDate();
                                }
                            }
                            fValue += ((nUnit[hour] * 3600) + (nUnit[minute] * 60) + nUnit[second] + fFraction) / 86400.0;
                        }
                    }
                }
                break;
            default:
                rError = nStringNoValueError;
        }
        if (rError != FormulaError::NONE)
            fValue = 0.0;
    }
    return fValue;
}

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

Messung V0.5
C=94 H=95 G=94

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet)  ¤

*© 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.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge