1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
24 #include <unordered_map>
25 #include <i18nlangtag/lang.h>
26 #include <basic/sbxvar.hxx>
27 #include <unotools/syslocale.hxx>
28 #include <rtl/ustrbuf.hxx>
29 #include <tools/solar.h>
30 #include <tools/long.hxx>
31 #include <o3tl/safeint.hxx>
35 class LocaleDataWrapper
;
38 class SwUserFieldType
;
40 const sal_Unicode cListDelim
= '|';
44 CALC_NAME
, CALC_NUMBER
, CALC_ENDCALC
,
45 CALC_PLUS
='+', CALC_MINUS
='-', CALC_MUL
='*',
46 CALC_DIV
='/', CALC_PRINT
=';', CALC_ASSIGN
='=',
47 CALC_LP
='(', CALC_RP
=')', CALC_PHD
='%',
49 CALC_NOT
=256, CALC_AND
=257, CALC_OR
=258,
50 CALC_XOR
=259, CALC_EQ
=260, CALC_NEQ
=261,
51 CALC_LEQ
=262, CALC_GEQ
=263, CALC_LES
=264,
52 CALC_GRE
=265, CALC_SUM
=266, CALC_MEAN
=267,
53 CALC_SQRT
=268, CALC_MIN
=269, CALC_MIN_IN
=270,
54 CALC_MAX
=271, CALC_MAX_IN
=272, CALC_SIN
=273,
55 CALC_COS
=274, CALC_TAN
=275, CALC_ASIN
=276,
56 CALC_ACOS
=278, CALC_ATAN
=279, CALC_TDIF
=280,
57 CALC_ROUND
=281, CALC_DATE
=282, CALC_MONTH
=283,
58 CALC_DAY
=284, CALC_PRODUCT
=285, CALC_AVERAGE
=286,
59 CALC_COUNT
=287, CALC_SIGN
=288, CALC_ABS
=289,
63 // Calculate Operations Strings
64 inline constexpr OUString sCalc_Add
= u
"add"_ustr
;
65 inline constexpr OUString sCalc_Sub
= u
"sub"_ustr
;
66 inline constexpr OUString sCalc_Mul
= u
"mul"_ustr
;
67 inline constexpr OUString sCalc_Div
= u
"div"_ustr
;
68 inline constexpr OUString sCalc_Phd
= u
"phd"_ustr
;
69 inline constexpr OUString sCalc_Sqrt
= u
"sqrt"_ustr
;
70 inline constexpr OUString sCalc_Pow
= u
"pow"_ustr
;
71 inline constexpr OUString sCalc_Or
= u
"or"_ustr
;
72 inline constexpr OUString sCalc_Xor
= u
"xor"_ustr
;
73 inline constexpr OUString sCalc_And
= u
"and"_ustr
;
74 inline constexpr OUString sCalc_Not
= u
"not"_ustr
;
75 inline constexpr OUString sCalc_Eq
= u
"eq"_ustr
;
76 inline constexpr OUString sCalc_Neq
= u
"neq"_ustr
;
77 inline constexpr OUString sCalc_Leq
= u
"leq"_ustr
;
78 inline constexpr OUString sCalc_Geq
= u
"geq"_ustr
;
79 inline constexpr OUString sCalc_L
= u
"l"_ustr
;
80 inline constexpr OUString sCalc_G
= u
"g"_ustr
;
81 inline constexpr OUString sCalc_Sum
= u
"sum"_ustr
;
82 inline constexpr OUString sCalc_Mean
= u
"mean"_ustr
;
83 inline constexpr OUString sCalc_Min
= u
"min"_ustr
;
84 inline constexpr OUString sCalc_Max
= u
"max"_ustr
;
85 inline constexpr OUString sCalc_Sin
= u
"sin"_ustr
;
86 inline constexpr OUString sCalc_Cos
= u
"cos"_ustr
;
87 inline constexpr OUString sCalc_Tan
= u
"tan"_ustr
;
88 inline constexpr OUString sCalc_Asin
= u
"asin"_ustr
;
89 inline constexpr OUString sCalc_Acos
= u
"acos"_ustr
;
90 inline constexpr OUString sCalc_Atan
= u
"atan"_ustr
;
91 inline constexpr OUString sCalc_Round
= u
"round"_ustr
;
92 inline constexpr OUString sCalc_Date
= u
"date"_ustr
;
93 inline constexpr OUString sCalc_Product
= u
"product"_ustr
;
94 inline constexpr OUString sCalc_Average
= u
"average"_ustr
;
95 inline constexpr OUString sCalc_Count
= u
"count"_ustr
;
96 inline constexpr OUString sCalc_Sign
= u
"sign"_ustr
;
97 inline constexpr OUString sCalc_Abs
= u
"abs"_ustr
;
98 inline constexpr OUString sCalc_Int
= u
"int"_ustr
;
100 // Calculate ErrorCodes
101 enum class SwCalcError
104 NaN
, // not a number (not an error, used for interoperability)
105 Syntax
, // syntax error
106 DivByZero
, // division by zero
107 FaultyBrackets
, // faulty brackets
108 OverflowInPower
, // overflow in power function
109 Overflow
, // overflow
112 class SwSbxValue final
: public SbxValue
117 // always default to a number. otherwise it will become a SbxEMPTY
118 SwSbxValue( tools::Long n
= 0 ) : m_bVoid(false), m_bDBvalue(false) { PutLong( n
); }
119 SwSbxValue( const double& rD
) : m_bVoid(false), m_bDBvalue(false) { PutDouble( rD
); }
121 bool GetBool() const;
122 double GetDouble() const;
123 SwSbxValue
& MakeDouble();
125 bool IsVoidValue() const {return m_bVoid
;}
126 void SetVoidValue(bool bSet
) {m_bVoid
= bSet
;}
128 bool IsDBvalue() const {return m_bDBvalue
;}
129 void SetDBvalue(bool bSet
) {m_bDBvalue
= bSet
;}
135 const SwFieldType
* pFieldType
;
137 SwCalcExp( SwSbxValue aVal
, const SwFieldType
* pFieldType
);
141 // if CalcOp != 0, this is a valid operator
143 CalcOp
* FindOperator( const OUString
& rSearch
);
145 extern "C" typedef double (*pfCalc
)(double);
149 std::unordered_map
<OUString
, SwCalcExp
> m_aVarTable
;
150 OUStringBuffer m_aVarName
;
153 std::vector
<const SwUserFieldType
*> m_aRekurStack
;
154 SwSbxValue m_nLastLeft
;
155 SwSbxValue m_nNumberValue
;
156 SwCalcExp m_aErrExpr
;
157 sal_Int32 m_nCommandPos
;
160 std::unique_ptr
<LocaleDataWrapper
> m_xLocaleDataWrapper
;
161 CharClass
* m_pCharClass
;
163 sal_uInt16 m_nListPor
;
164 bool m_bHasNumber
; // fix COUNT() and AVERAGE(), if all cells are NaN
165 SwCalcOper m_eCurrOper
;
166 SwCalcOper m_eCurrListOper
;
167 SwCalcError m_eError
;
169 SwCalcOper
GetToken();
172 SwSbxValue
PrimFunc(bool &rChkPow
);
174 SwSbxValue
StdFunc(pfCalc pFnc
, bool bChkTrig
);
176 static OUString
GetColumnName( const OUString
& rName
);
177 OUString
GetDBName( std::u16string_view rName
);
179 SwCalc( const SwCalc
& ) = delete;
180 SwCalc
& operator=( const SwCalc
& ) = delete;
188 SwSbxValue
Calculate( const OUString
&rStr
);
189 OUString
GetStrResult( const SwSbxValue
& rValue
);
190 OUString
GetStrResult( double );
192 SwCalcExp
* VarInsert( const OUString
& r
);
193 SwCalcExp
* VarLook( const OUString
&rStr
, bool bIns
= false );
194 void VarChange( const OUString
& rStr
, const SwSbxValue
& rValue
);
195 void VarChange( const OUString
& rStr
, double );
196 std::unordered_map
<OUString
, SwCalcExp
> & GetVarTable() { return m_aVarTable
; }
198 bool Push(const SwUserFieldType
* pUserFieldType
);
200 const CharClass
* GetCharClass() const;
201 void SetCharClass(const LanguageTag
& rLanguageTag
);
203 void SetCalcError( SwCalcError eErr
) { m_eError
= eErr
; }
204 bool IsCalcError() const { return SwCalcError::NONE
!= m_eError
&& SwCalcError::NaN
!= m_eError
; }
205 bool IsCalcNotANumber() const { return SwCalcError::NaN
== m_eError
; }
207 static bool Str2Double( const OUString
& rStr
, sal_Int32
& rPos
,
209 static bool Str2Double( const OUString
& rStr
, sal_Int32
& rPos
,
210 double& rVal
, SwDoc
const *const pDoc
);
212 static LanguageType
GetDocAppScriptLang( SwDoc
const & rDoc
);
214 SW_DLLPUBLIC
static bool IsValidVarName( const OUString
& rStr
,
215 OUString
* pValidName
= nullptr );
218 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */