/* -*- 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 .
*/
#pragma once
#include <memory>
#include <vector>
#include <unordered_map>
#include <i18nlangtag/lang.h>
#include <basic/sbxvar.hxx>
#include <unotools/syslocale.hxx>
#include <rtl/ustrbuf.hxx>
#include <tools/solar.h>
#include <tools/
long.hxx>
#include <o3tl/safeint.hxx>
#include "swdllapi.h"
class CharClass;
class LocaleDataWrapper;
class SwFieldType;
class SwDoc;
class SwUserFieldType;
const sal_Unicode cListDelim =
'|';
enum SwCalcOper
{
CALC_NAME, CALC_NUMBER, CALC_ENDCALC,
CALC_PLUS=
'+', CALC_MINUS=
'-', CALC_MUL=
'*',
CALC_DIV=
'/', CALC_PRINT=
';', CALC_ASSIGN=
'=',
CALC_LP=
'(', CALC_RP=
')', CALC_PHD=
'%',
CALC_POW=
'^',
CALC_NOT=256, CALC_AND=257, CALC_OR=258,
CALC_XOR=259, CALC_EQ=260, CALC_NEQ=261,
CALC_LEQ=262, CALC_GEQ=263, CALC_LES=264,
CALC_GRE=265, CALC_SUM=266, CALC_MEAN=267,
CALC_SQRT=268, CALC_MIN=269, CALC_MIN_IN=270,
CALC_MAX=271, CALC_MAX_IN=272, CALC_SIN=273,
CALC_COS=274, CALC_TAN=275, CALC_ASIN=276,
CALC_ACOS=278, CALC_ATAN=279, CALC_TDIF=280,
CALC_ROUND=281, CALC_DATE=282, CALC_MONTH=283,
CALC_DAY=284, CALC_PRODUCT=285, CALC_AVERAGE=286,
CALC_COUNT=287, CALC_SIGN=288, CALC_ABS=289,
CALC_INT=290, CALC_MOD=291, CALC_MOD_IN=292
};
// Calculate Operations Strings
inline constexpr OUString sCalc_Add = u
"add"_ustr;
inline constexpr OUString sCalc_Sub = u
"sub"_ustr;
inline constexpr OUString sCalc_Mul = u
"mul"_ustr;
inline constexpr OUString sCalc_Div = u
"div"_ustr;
inline constexpr OUString sCalc_Phd = u
"phd"_ustr;
inline constexpr OUString sCalc_Sqrt = u
"sqrt"_ustr;
inline constexpr OUString sCalc_Pow = u
"pow"_ustr;
inline constexpr OUString sCalc_Or = u
"or"_ustr;
inline constexpr OUString sCalc_Xor = u
"xor"_ustr;
inline constexpr OUString sCalc_And = u
"and"_ustr;
inline constexpr OUString sCalc_Not = u
"not"_ustr;
inline constexpr OUString sCalc_Eq = u
"eq"_ustr;
inline constexpr OUString sCalc_Neq = u
"neq"_ustr;
inline constexpr OUString sCalc_Leq = u
"leq"_ustr;
inline constexpr OUString sCalc_Geq = u
"geq"_ustr;
inline constexpr OUString sCalc_L = u
"l"_ustr;
inline constexpr OUString sCalc_G = u
"g"_ustr;
inline constexpr OUString sCalc_Sum = u
"sum"_ustr;
inline constexpr OUString sCalc_Mean = u
"mean"_ustr;
inline constexpr OUString sCalc_Min = u
"min"_ustr;
inline constexpr OUString sCalc_Max = u
"max"_ustr;
inline constexpr OUString sCalc_Mod = u
"mod"_ustr;
inline constexpr OUString sCalc_Sin = u
"sin"_ustr;
inline constexpr OUString sCalc_Cos = u
"cos"_ustr;
inline constexpr OUString sCalc_Tan = u
"tan"_ustr;
inline constexpr OUString sCalc_Asin = u
"asin"_ustr;
inline constexpr OUString sCalc_Acos = u
"acos"_ustr;
inline constexpr OUString sCalc_Atan = u
"atan"_ustr;
inline constexpr OUString sCalc_Round= u
"round"_ustr;
inline constexpr OUString sCalc_Date = u
"date"_ustr;
inline constexpr OUString sCalc_Product = u
"product"_ustr;
inline constexpr OUString sCalc_Average = u
"average"_ustr;
inline constexpr OUString sCalc_Count= u
"count"_ustr;
inline constexpr OUString sCalc_Sign = u
"sign"_ustr;
inline constexpr OUString sCalc_Abs = u
"abs"_ustr;
inline constexpr OUString sCalc_Int = u
"int"_ustr;
// Calculate ErrorCodes
enum class SwCalcError
{
NONE=0,
NaN,
// not a number (not an error, used for interoperability)
Syntax,
// syntax error
DivByZero,
// division by zero
FaultyBrackets,
// faulty brackets
OverflowInPower,
// overflow in power function
Overflow,
// overflow
};
class SwSbxValue final :
public SbxValue
{
bool m_bVoid;
bool m_bDBvalue;
public:
// always default to a number. otherwise it will become a SbxEMPTY
SwSbxValue( tools::
Long n = 0 ) : m_bVoid(
false), m_bDBvalue(
false) { PutLong( n ); }
SwSbxValue(
const double& rD ) : m_bVoid(
false), m_bDBvalue(
false) { PutDouble( rD ); }
bool GetBool()
const;
double GetDouble()
const;
SwSbxValue& MakeDouble();
bool IsVoidValue()
const {
return m_bVoid;}
void SetVoidValue(
bool bSet) {m_bVoid = bSet;}
bool IsDBvalue()
const {
return m_bDBvalue;}
void SetDBvalue(
bool bSet) {m_bDBvalue = bSet;}
};
struct SwCalcExp
{
SwSbxValue nValue;
const SwFieldType* pFieldType;
SwCalcExp( SwSbxValue aVal,
const SwFieldType* pFieldType );
};
// if CalcOp != 0, this is a valid operator
struct CalcOp;
CalcOp* FindOperator(
const OUString& rSearch );
extern "C" typedef double (*pfCalc)(
double);
class SwCalc
{
std::unordered_map<OUString, SwCalcExp> m_aVarTable;
OUStringBuffer m_aVarName;
OUString m_sCurrSym;
OUString m_sCommand;
std::vector<
const SwUserFieldType*> m_aRekurStack;
SwSbxValue m_nLastLeft;
SwSbxValue m_nNumberValue;
SwCalcExp m_aErrExpr;
sal_Int32 m_nCommandPos;
SwDoc& m_rDoc;
std::unique_ptr<LocaleDataWrapper> m_xLocaleDataWrapper;
CharClass* m_pCharClass;
sal_uInt16 m_nListPor;
bool m_bHasNumber;
// fix COUNT() and AVERAGE(), if all cells are NaN
SwCalcOper m_eCurrOper;
SwCalcOper m_eCurrListOper;
SwCalcError m_eError;
SwCalcOper GetToken();
SwSbxValue Expr();
SwSbxValue Term();
SwSbxValue PrimFunc(
bool &rChkPow);
SwSbxValue Prim();
SwSbxValue StdFunc(pfCalc pFnc,
bool bChkTrig);
static OUString GetColumnName(
const OUString& rName );
OUString GetDBName( std::u16string_view rName );
SwCalc(
const SwCalc& ) =
delete;
SwCalc&
operator=(
const SwCalc& ) =
delete;
void ImplDestroy();
public:
SwCalc(SwDoc& rD);
~SwCalc();
SwSbxValue Calculate(
const OUString &rStr );
OUString GetStrResult(
const SwSbxValue& rValue );
OUString GetStrResult(
double );
SwCalcExp* VarInsert(
const OUString& r );
SwCalcExp* VarLook(
const OUString &rStr,
bool bIns =
false );
void VarChange(
const OUString& rStr,
const SwSbxValue& rValue );
void VarChange(
const OUString& rStr,
double );
std::unordered_map<OUString, SwCalcExp> & GetVarTable() {
return m_aVarTable; }
bool Push(
const SwUserFieldType* pUserFieldType);
void Pop();
const CharClass* GetCharClass()
const;
void SetCharClass(
const LanguageTag& rLanguageTag);
void SetCalcError( SwCalcError eErr ) { m_eError = eErr; }
bool IsCalcError()
const {
return SwCalcError::NONE != m_eError && SwCalcError::NaN != m_eErr
or; }
bool IsCalcNotANumber() const { return SwCalcError::NaN == m_eError; }
static bool Str2Double( const OUString& rStr, sal_Int32& rPos,
double& rVal );
static bool Str2Double( const OUString& rStr, sal_Int32& rPos,
double& rVal, SwDoc const *const pDoc );
static LanguageType GetDocAppScriptLang( SwDoc const & rDoc );
SW_DLLPUBLIC static bool IsValidVarName( const OUString& rStr,
OUString* pValidName = nullptr );
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */