Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / inc / calc.hxx
blob87583f752ff4e18a46818fd50c328ed2a92e1b2a
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 #ifndef INCLUDED_SW_INC_CALC_HXX
21 #define INCLUDED_SW_INC_CALC_HXX
23 #include <memory>
24 #include <vector>
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>
32 #include "swdllapi.h"
34 class CharClass;
35 class LocaleDataWrapper;
36 class SwFieldType;
37 class SwDoc;
38 class SwUserFieldType;
40 #define TBLSZ 47 // should be a prime, because of hash table
42 const sal_Unicode cListDelim = '|';
44 enum SwCalcOper
46 CALC_NAME, CALC_NUMBER, CALC_ENDCALC,
47 CALC_PLUS='+', CALC_MINUS='-', CALC_MUL='*',
48 CALC_DIV='/', CALC_PRINT=';', CALC_ASSIGN='=',
49 CALC_LP='(', CALC_RP=')', CALC_PHD='%',
50 CALC_POW='^',
51 CALC_NOT=256, CALC_AND=257, CALC_OR=258,
52 CALC_XOR=259, CALC_EQ=260, CALC_NEQ=261,
53 CALC_LEQ=262, CALC_GEQ=263, CALC_LES=264,
54 CALC_GRE=265, CALC_SUM=266, CALC_MEAN=267,
55 CALC_SQRT=268, CALC_MIN=269, CALC_MIN_IN=270,
56 CALC_MAX=271, CALC_MAX_IN=272, CALC_SIN=273,
57 CALC_COS=274, CALC_TAN=275, CALC_ASIN=276,
58 CALC_ACOS=278, CALC_ATAN=279, CALC_TDIF=280,
59 CALC_ROUND=281, CALC_DATE=282, CALC_MONTH=283,
60 CALC_DAY=284, CALC_PRODUCT=285, CALC_AVERAGE=286,
61 CALC_COUNT=287, CALC_SIGN=288, CALC_ABS=289,
62 CALC_INT=290
65 // Calculate Operations Strings
66 extern const char sCalc_Add[];
67 extern const char sCalc_Sub[];
68 extern const char sCalc_Mul[];
69 extern const char sCalc_Div[];
70 extern const char sCalc_Phd[];
71 extern const char sCalc_Sqrt[];
72 extern const char sCalc_Pow[];
73 extern const char sCalc_Or[];
74 extern const char sCalc_Xor[];
75 extern const char sCalc_And[];
76 extern const char sCalc_Not[];
77 extern const char sCalc_Eq[];
78 extern const char sCalc_Neq[];
79 extern const char sCalc_Leq[];
80 extern const char sCalc_Geq[];
81 extern const char sCalc_L[];
82 extern const char sCalc_G[];
83 extern const char sCalc_Sum[];
84 extern const char sCalc_Mean[];
85 extern const char sCalc_Average[];
86 extern const char sCalc_Product[];
87 extern const char sCalc_Count[];
88 extern const char sCalc_Min[];
89 extern const char sCalc_Max[];
90 extern const char sCalc_Sin[];
91 extern const char sCalc_Cos[];
92 extern const char sCalc_Tan[];
93 extern const char sCalc_Asin[];
94 extern const char sCalc_Acos[];
95 extern const char sCalc_Atan[];
96 extern const char sCalc_Round[];
97 extern const char sCalc_Date[];
98 extern const char sCalc_Sign[];
99 extern const char sCalc_Abs[];
100 extern const char sCalc_Int[];
102 // Calculate ErrorCodes
103 enum class SwCalcError
105 NONE=0,
106 NaN, // not a number (not an error, used for interoperability)
107 Syntax, // syntax error
108 DivByZero, // division by zero
109 FaultyBrackets, // faulty brackets
110 OverflowInPower, // overflow in power function
111 Overflow, // overflow
114 class SwSbxValue final : public SbxValue
116 bool m_bVoid;
117 bool m_bDBvalue;
118 public:
119 // always default to a number. otherwise it will become a SbxEMPTY
120 SwSbxValue( tools::Long n = 0 ) : m_bVoid(false), m_bDBvalue(false) { PutLong( n ); }
121 SwSbxValue( const double& rD ) : m_bVoid(false), m_bDBvalue(false) { PutDouble( rD ); }
123 bool GetBool() const;
124 double GetDouble() const;
125 SwSbxValue& MakeDouble();
127 bool IsVoidValue() const {return m_bVoid;}
128 void SetVoidValue(bool bSet) {m_bVoid = bSet;}
130 bool IsDBvalue() const {return m_bDBvalue;}
131 void SetDBvalue(bool bSet) {m_bDBvalue = bSet;}
134 // Calculate HashTables for VarTable and Operations
135 struct SwHash
137 SwHash( OUString aStr );
138 virtual ~SwHash();
139 OUString aStr;
140 std::unique_ptr<SwHash> pNext;
143 struct SwCalcExp final : public SwHash
145 SwSbxValue nValue;
146 const SwFieldType* pFieldType;
148 SwCalcExp( const OUString& rStr, SwSbxValue aVal,
149 const SwFieldType* pFieldType );
152 /// T should be a subclass of SwHash
153 template<class T>
154 class SwHashTable
156 std::vector<std::unique_ptr<T>> m_aData;
157 public:
158 SwHashTable(size_t nSize) : m_aData(nSize)
160 assert(nSize < SAL_MAX_UINT32);
162 std::unique_ptr<T> & operator[](size_t idx) { return m_aData[idx]; }
163 std::unique_ptr<T> const & operator[](size_t idx) const { return m_aData[idx]; }
164 void resize(size_t nSize) { m_aData.resize(nSize); }
166 T* Find( std::u16string_view aStr, sal_uInt32* pPos = nullptr ) const
168 size_t nTableSize = m_aData.size();
169 assert(nTableSize < SAL_MAX_UINT32);
170 sal_uInt32 ii = 0;
171 for( size_t n = 0; n < aStr.size(); ++n )
173 ii = ii << 1 ^ aStr[n];
175 ii %= nTableSize;
177 if( pPos )
178 *pPos = ii;
180 for( T* pEntry = m_aData[ii].get(); pEntry; pEntry = static_cast<T*>(pEntry->pNext.get()) )
182 if( aStr == pEntry->aStr )
184 return pEntry;
187 return nullptr;
193 // if CalcOp != 0, this is a valid operator
194 struct CalcOp;
195 CalcOp* FindOperator( const OUString& rSearch );
197 extern "C" typedef double (*pfCalc)(double);
199 class SwCalc
201 SwHashTable<SwCalcExp> m_aVarTable;
202 OUStringBuffer m_aVarName;
203 OUString m_sCurrSym;
204 OUString m_sCommand;
205 std::vector<const SwUserFieldType*> m_aRekurStack;
206 SwSbxValue m_nLastLeft;
207 SwSbxValue m_nNumberValue;
208 SwCalcExp m_aErrExpr;
209 sal_Int32 m_nCommandPos;
211 SwDoc& m_rDoc;
212 std::unique_ptr<LocaleDataWrapper> m_xLocaleDataWrapper;
213 CharClass* m_pCharClass;
215 sal_uInt16 m_nListPor;
216 bool m_bHasNumber; // fix COUNT() and AVERAGE(), if all cells are NaN
217 SwCalcOper m_eCurrOper;
218 SwCalcOper m_eCurrListOper;
219 SwCalcError m_eError;
221 SwCalcOper GetToken();
222 SwSbxValue Expr();
223 SwSbxValue Term();
224 SwSbxValue PrimFunc(bool &rChkPow);
225 SwSbxValue Prim();
226 SwSbxValue StdFunc(pfCalc pFnc, bool bChkTrig);
228 static OUString GetColumnName( const OUString& rName );
229 OUString GetDBName( std::u16string_view rName );
231 SwCalc( const SwCalc& ) = delete;
232 SwCalc& operator=( const SwCalc& ) = delete;
234 void ImplDestroy();
236 public:
237 SwCalc(SwDoc& rD);
238 ~SwCalc();
240 SwSbxValue Calculate( const OUString &rStr );
241 OUString GetStrResult( const SwSbxValue& rValue );
242 OUString GetStrResult( double );
244 SwCalcExp* VarInsert( const OUString& r );
245 SwCalcExp* VarLook( const OUString &rStr, bool bIns = false );
246 void VarChange( const OUString& rStr, const SwSbxValue& rValue );
247 void VarChange( const OUString& rStr, double );
248 SwHashTable<SwCalcExp> & GetVarTable() { return m_aVarTable; }
250 bool Push(const SwUserFieldType* pUserFieldType);
251 void Pop();
252 const CharClass* GetCharClass() const;
253 void SetCharClass(const LanguageTag& rLanguageTag);
255 void SetCalcError( SwCalcError eErr ) { m_eError = eErr; }
256 bool IsCalcError() const { return SwCalcError::NONE != m_eError && SwCalcError::NaN != m_eError; }
257 bool IsCalcNotANumber() const { return SwCalcError::NaN == m_eError; }
259 static bool Str2Double( const OUString& rStr, sal_Int32& rPos,
260 double& rVal );
261 static bool Str2Double( const OUString& rStr, sal_Int32& rPos,
262 double& rVal, SwDoc const *const pDoc );
264 static LanguageType GetDocAppScriptLang( SwDoc const & rDoc );
266 SW_DLLPUBLIC static bool IsValidVarName( const OUString& rStr,
267 OUString* pValidName = nullptr );
270 #endif
272 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */