Coverage Report

Created: 2026-06-30 11:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sw/inc/calc.hxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
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/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
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 .
18
 */
19
20
#pragma once
21
22
#include <memory>
23
#include <vector>
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>
32
#include "swdllapi.h"
33
34
class CharClass;
35
class LocaleDataWrapper;
36
class SwFieldType;
37
class SwDoc;
38
class SwUserFieldType;
39
40
const sal_Unicode cListDelim    = '|';
41
42
enum SwCalcOper
43
{
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='%',
48
    CALC_POW='^',
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,
60
    CALC_INT=290,           CALC_MOD=291,           CALC_MOD_IN=292
61
};
62
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_Mod  = u"mod"_ustr;
86
inline constexpr OUString sCalc_Sin  = u"sin"_ustr;
87
inline constexpr OUString sCalc_Cos  = u"cos"_ustr;
88
inline constexpr OUString sCalc_Tan  = u"tan"_ustr;
89
inline constexpr OUString sCalc_Asin = u"asin"_ustr;
90
inline constexpr OUString sCalc_Acos = u"acos"_ustr;
91
inline constexpr OUString sCalc_Atan = u"atan"_ustr;
92
inline constexpr OUString sCalc_Round= u"round"_ustr;
93
inline constexpr OUString sCalc_Date = u"date"_ustr;
94
inline constexpr OUString sCalc_Product = u"product"_ustr;
95
inline constexpr OUString sCalc_Average = u"average"_ustr;
96
inline constexpr OUString sCalc_Count= u"count"_ustr;
97
inline constexpr OUString sCalc_Sign = u"sign"_ustr;
98
inline constexpr OUString sCalc_Abs  = u"abs"_ustr;
99
inline constexpr OUString sCalc_Int  = u"int"_ustr;
100
101
//  Calculate ErrorCodes
102
enum class SwCalcError
103
{
104
    NONE=0,
105
    NaN,              //  not a number (not an error, used for interoperability)
106
    Syntax,           //  syntax error
107
    DivByZero,        //  division by zero
108
    FaultyBrackets,   //  faulty brackets
109
    OverflowInPower,  //  overflow in power function
110
    Overflow,         //  overflow
111
};
112
113
class SwSbxValue final : public SbxValue
114
{
115
    bool m_bVoid;
116
    bool m_bDBvalue;
117
public:
118
    // always default to a number. otherwise it will become a SbxEMPTY
119
5.08k
    SwSbxValue( tools::Long n = 0 ) : m_bVoid(false), m_bDBvalue(false)  { PutLong( n ); }
120
0
    SwSbxValue( const double& rD ) : m_bVoid(false), m_bDBvalue(false) { PutDouble( rD ); }
121
122
    bool GetBool() const;
123
    double GetDouble() const;
124
    SwSbxValue& MakeDouble();
125
126
1.66k
    bool IsVoidValue() const {return m_bVoid;}
127
2.32k
    void SetVoidValue(bool bSet) {m_bVoid = bSet;}
128
129
721
    bool IsDBvalue() const {return m_bDBvalue;}
130
0
    void SetDBvalue(bool bSet) {m_bDBvalue = bSet;}
131
};
132
133
struct SwCalcExp
134
{
135
    SwSbxValue  nValue;
136
    const SwFieldType* pFieldType;
137
138
    SwCalcExp( SwSbxValue aVal, const SwFieldType* pFieldType );
139
};
140
141
142
// if CalcOp != 0, this is a valid operator
143
struct CalcOp;
144
CalcOp* FindOperator( const OUString& rSearch );
145
146
extern "C" typedef double (*pfCalc)(double);
147
148
class SwCalc
149
{
150
    std::unordered_map<OUString, SwCalcExp> m_aVarTable;
151
    OUStringBuffer m_aVarName;
152
    OUString    m_sCurrSym;
153
    OUString    m_sCommand;
154
    std::vector<const SwUserFieldType*> m_aRekurStack;
155
    SwSbxValue  m_nLastLeft;
156
    SwSbxValue  m_nNumberValue;
157
    SwCalcExp   m_aErrExpr;
158
    sal_Int32   m_nCommandPos;
159
160
    SwDoc&      m_rDoc;
161
    std::unique_ptr<LocaleDataWrapper> m_xLocaleDataWrapper;
162
    CharClass*  m_pCharClass;
163
164
    sal_uInt16      m_nListPor;
165
    bool        m_bHasNumber; // fix COUNT() and AVERAGE(), if all cells are NaN
166
    SwCalcOper  m_eCurrOper;
167
    SwCalcOper  m_eCurrListOper;
168
    SwCalcError m_eError;
169
170
    SwCalcOper  GetToken();
171
    SwSbxValue  Expr();
172
    SwSbxValue  Term();
173
    SwSbxValue  PrimFunc(bool &rChkPow);
174
    SwSbxValue  Prim();
175
    SwSbxValue  StdFunc(pfCalc pFnc, bool bChkTrig);
176
177
    static OUString  GetColumnName( const OUString& rName );
178
    OUString  GetDBName( std::u16string_view rName );
179
180
    SwCalc( const SwCalc& ) = delete;
181
    SwCalc& operator=( const SwCalc& ) = delete;
182
183
    void ImplDestroy();
184
185
public:
186
    SwCalc(SwDoc& rD);
187
    ~SwCalc();
188
189
    SwSbxValue  Calculate( const OUString &rStr );
190
    OUString    GetStrResult( const SwSbxValue& rValue );
191
    OUString    GetStrResult( double );
192
193
    SwCalcExp*  VarInsert( const OUString& r );
194
    SwCalcExp*  VarLook( const OUString &rStr, bool bIns = false );
195
    void        VarChange( const OUString& rStr, const SwSbxValue& rValue );
196
    void        VarChange( const OUString& rStr, double );
197
0
    std::unordered_map<OUString, SwCalcExp> & GetVarTable() { return m_aVarTable; }
198
199
    bool        Push(const SwUserFieldType* pUserFieldType);
200
    void        Pop();
201
    const CharClass*  GetCharClass() const;
202
    void        SetCharClass(const LanguageTag& rLanguageTag);
203
204
4
    void        SetCalcError( SwCalcError eErr )    { m_eError = eErr; }
205
648
    bool        IsCalcError() const                 { return SwCalcError::NONE != m_eError && SwCalcError::NaN != m_eError; }
206
0
    bool        IsCalcNotANumber() const            { return SwCalcError::NaN == m_eError; }
207
208
    static bool Str2Double( const OUString& rStr, sal_Int32& rPos,
209
                                double& rVal );
210
    static bool Str2Double( const OUString& rStr, sal_Int32& rPos,
211
                                double& rVal, SwDoc const *const pDoc );
212
213
    static LanguageType GetDocAppScriptLang( SwDoc const & rDoc );
214
215
    SW_DLLPUBLIC static bool IsValidVarName( const OUString& rStr,
216
                                    OUString* pValidName = nullptr );
217
};
218
219
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */