Coverage Report

Created: 2025-06-09 07:42

/src/gdal/muparser/include/muParserBase.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
3
   _____  __ _____________ _______  ______ ___________
4
  /     \|  |  \____ \__  \\_  __ \/  ___// __ \_  __ \
5
   |  Y Y  \  |  /  |_> > __ \|  | \/\___ \\  ___/|  | \/
6
   |__|_|  /____/|   __(____  /__|  /____  >\___  >__|
7
     \/      |__|       \/           \/     \/
8
   Copyright (C) 2004 - 2022 Ingo Berg
9
10
  Redistribution and use in source and binary forms, with or without modification, are permitted
11
  provided that the following conditions are met:
12
13
    * Redistributions of source code must retain the above copyright notice, this list of
14
    conditions and the following disclaimer.
15
    * Redistributions in binary form must reproduce the above copyright notice, this list of
16
    conditions and the following disclaimer in the documentation and/or other materials provided
17
    with the distribution.
18
19
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
20
  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21
  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22
  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25
  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26
  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
*/
28
29
#ifndef MU_PARSER_BASE_H
30
#define MU_PARSER_BASE_H
31
32
//--- Standard includes ------------------------------------------------------------------------
33
#include <cmath>
34
#include <string>
35
#include <iostream>
36
#include <map>
37
#include <memory>
38
#include <locale>
39
#include <limits.h>
40
41
//--- Parser includes --------------------------------------------------------------------------
42
#include "muParserDef.h"
43
#include "muParserTokenReader.h"
44
#include "muParserBytecode.h"
45
#include "muParserError.h"
46
47
#if defined(_MSC_VER)
48
  #pragma warning(push)
49
  #pragma warning(disable : 4251)  // ...needs to have dll-interface to be used by clients of class ...
50
#endif
51
52
53
namespace mu
54
{
55
  /** \file
56
    \brief This file contains the class definition of the muparser engine.
57
  */
58
59
  /** \brief Mathematical expressions parser (base parser engine).
60
61
    This is the implementation of a bytecode based mathematical expressions parser.
62
    The formula will be parsed from string and converted into a bytecode.
63
    Future calculations will be done with the bytecode instead the formula string
64
    resulting in a significant performance increase.
65
    Complementary to a set of internally implemented functions the parser is able to handle
66
    user defined functions and variables.
67
  */
68
  class API_EXPORT_CXX ParserBase
69
  {
70
    friend class ParserTokenReader;
71
72
  private:
73
74
    /** \brief Typedef for the parse functions.
75
76
      The parse function do the actual work. The parser exchanges
77
      the function pointer to the parser function depending on
78
      which state it is in. (i.e. bytecode parser vs. string parser)
79
    */
80
    typedef value_type(ParserBase::* ParseFunction)() const;
81
82
    /** \brief Type used for storing an array of values. */
83
    typedef std::vector<value_type> valbuf_type;
84
85
    /** \brief Type for a vector of strings. */
86
    typedef std::vector<string_type> stringbuf_type;
87
88
    /** \brief Typedef for the token reader. */
89
    typedef ParserTokenReader token_reader_type;
90
91
    /** \brief Type used for parser tokens. */
92
    typedef ParserToken<value_type, string_type> token_type;
93
94
    /** \brief Maximum number of threads spawned by OpenMP when using the bulk mode. */
95
    static const int s_MaxNumOpenMPThreads;
96
97
  public:
98
99
    /** \brief Type of the error class.
100
101
      Included for backwards compatibility.
102
    */
103
    typedef ParserError exception_type;
104
105
    static void EnableDebugDump(bool bDumpCmd, bool bDumpStack);
106
107
    ParserBase();
108
    ParserBase(const ParserBase& a_Parser);
109
    ParserBase& operator=(const ParserBase& a_Parser);
110
111
    virtual ~ParserBase();
112
113
    value_type Eval() const;
114
    value_type* Eval(int& nStackSize) const;
115
    void Eval(value_type* results, int nBulkSize);
116
117
    int GetNumResults() const;
118
119
    void SetExpr(const string_type& a_sExpr);
120
    void SetVarFactory(facfun_type a_pFactory, void* pUserData = nullptr);
121
122
    void SetDecSep(char_type cDecSep);
123
    void SetThousandsSep(char_type cThousandsSep = 0);
124
    void ResetLocale();
125
126
    void EnableOptimizer(bool a_bIsOn = true);
127
    void EnableBuiltInOprt(bool a_bIsOn = true);
128
129
    bool HasBuiltInOprt() const;
130
    void AddValIdent(identfun_type a_pCallback);
131
132
    /** \fn void mu::ParserBase::DefineFun(const string_type &a_strName, fun_type0 a_pFun, bool a_bAllowOpt = true)
133
      \brief Define a parser function without arguments.
134
      \param a_strName Name of the function
135
      \param a_pFun Pointer to the callback function
136
      \param a_bAllowOpt A flag indicating this function may be optimized
137
    */
138
    template<typename T>
139
    void DefineFun(const string_type& a_strName, T a_pFun, bool a_bAllowOpt = true)
140
0
    {
141
0
      AddCallback(a_strName, ParserCallback(a_pFun, a_bAllowOpt), m_FunDef, ValidNameChars());
142
0
    }
Unexecuted instantiation: void mu::ParserBase::DefineFun<double (*)(double)>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, double (*)(double), bool)
Unexecuted instantiation: void mu::ParserBase::DefineFun<double (*)(double, double)>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, double (*)(double, double), bool)
Unexecuted instantiation: void mu::ParserBase::DefineFun<double (*)(double const*, int)>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, double (*)(double const*, int), bool)
Unexecuted instantiation: void mu::ParserBase::DefineFun<double (*)()>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, double (*)(), bool)
143
144
    /** \fn void mu::ParserBase::DefineFunUserData
145
      \brief Define a parser function with user data (not null).
146
      \param a_strName Name of the function
147
      \param a_pFun Pointer to the callback function
148
      \param a_pUserData Pointer that will be passed back to callback (shall not be nullptr)
149
      \param a_bAllowOpt A flag indicating this function may be optimized
150
    */
151
    template<typename T>
152
    void DefineFunUserData(const string_type& a_strName, T a_pFun, void* a_pUserData, bool a_bAllowOpt = true)
153
    {
154
      AddCallback(a_strName, ParserCallback(a_pFun, a_pUserData, a_bAllowOpt), m_FunDef, ValidNameChars());
155
    }
156
157
    void DefineOprt(const string_type& a_strName, fun_type2 a_pFun, unsigned a_iPri = 0, EOprtAssociativity a_eAssociativity = oaLEFT, bool a_bAllowOpt = false);
158
    void DefineConst(const string_type& a_sName, value_type a_fVal);
159
    void DefineStrConst(const string_type& a_sName, const string_type& a_strVal);
160
    void DefineVar(const string_type& a_sName, value_type* a_fVar);
161
    void DefinePostfixOprt(const string_type& a_strFun, fun_type1 a_pOprt, bool a_bAllowOpt = true);
162
    void DefineInfixOprt(const string_type& a_strName, fun_type1 a_pOprt, int a_iPrec = prINFIX, bool a_bAllowOpt = true);
163
164
    // Clear user defined variables, constants or functions
165
    void ClearVar();
166
    void ClearFun();
167
    void ClearConst();
168
    void ClearInfixOprt();
169
    void ClearPostfixOprt();
170
    void ClearOprt();
171
172
    void RemoveVar(const string_type& a_strVarName);
173
    const varmap_type& GetUsedVar() const;
174
    const varmap_type& GetVar() const;
175
    const valmap_type& GetConst() const;
176
    const string_type& GetExpr() const;
177
    const funmap_type& GetFunDef() const;
178
    string_type GetVersion(EParserVersionInfo eInfo = pviFULL) const;
179
    const ParserByteCode& GetByteCode() const;
180
181
    const char_type** GetOprtDef() const;
182
    void DefineNameChars(const char_type* a_szCharset);
183
    void DefineOprtChars(const char_type* a_szCharset);
184
    void DefineInfixOprtChars(const char_type* a_szCharset);
185
186
    const char_type* ValidNameChars() const;
187
    const char_type* ValidOprtChars() const;
188
    const char_type* ValidInfixOprtChars() const;
189
190
    void SetArgSep(char_type cArgSep);
191
    void SetByteCode(const ParserByteCode& a_ByteCode);
192
193
    char_type GetArgSep() const;
194
195
  protected:
196
197
    void Init();
198
    void Error(EErrorCodes a_iErrc, int a_iPos = static_cast<int>(mu::string_type::npos), const string_type& a_strTok = string_type()) const;
199
200
    virtual void InitCharSets() = 0;
201
    virtual void InitFun() = 0;
202
    virtual void InitConst() = 0;
203
    virtual void InitOprt() = 0;
204
205
    virtual void OnDetectVar(string_type* pExpr, int& nStart, int& nEnd);
206
207
    static const char_type* c_DefaultOprt[];
208
    static std::locale s_locale;  ///< The locale used by the parser
209
    static bool g_DbgDumpCmdCode;
210
    static bool g_DbgDumpStack;
211
212
    /** \brief A facet class used to change decimal and thousands separator. */
213
    template<class TChar>
214
    class change_dec_sep : public std::numpunct<TChar>
215
    {
216
    public:
217
218
      explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3)
219
2
        :std::numpunct<TChar>()
220
2
        ,m_nGroup(nGroup)
221
2
        ,m_cDecPoint(cDecSep)
222
2
        ,m_cThousandsSep(cThousandsSep)
223
2
      {}
224
225
    protected:
226
227
      char_type do_decimal_point() const override
228
0
      {
229
0
        return m_cDecPoint;
230
0
      }
231
232
      char_type do_thousands_sep() const override
233
0
      {
234
0
        return m_cThousandsSep;
235
0
      }
236
237
      std::string do_grouping() const override
238
0
      {
239
        // fix for issue 4: https://code.google.com/p/muparser/issues/detail?id=4
240
        // courtesy of Jens Bartsch
241
        // original code:
242
        //        return std::string(1, (char)m_nGroup); 
243
        // new code:
244
0
        return std::string(1, (char)(m_cThousandsSep > 0 ? m_nGroup : CHAR_MAX));
245
0
      }
246
247
    private:
248
249
      int m_nGroup;
250
      char_type m_cDecPoint;
251
      char_type m_cThousandsSep;
252
    };
253
254
  private:
255
256
    void Assign(const ParserBase& a_Parser);
257
    void InitTokenReader();
258
    void ReInit() const;
259
260
    void AddCallback(const string_type& a_strName, const ParserCallback& a_Callback, funmap_type& a_Storage, const char_type* a_szCharSet);
261
    void ApplyRemainingOprt(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal) const;
262
    void ApplyBinOprt(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal) const;
263
    void ApplyIfElse(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal) const;
264
    void ApplyFunc(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal, int iArgCount) const;
265
266
    token_type ApplyStrFunc(const token_type& a_FunTok, const std::vector<token_type>& a_vArg) const;
267
268
    int GetOprtPrecedence(const token_type& a_Tok) const;
269
    EOprtAssociativity GetOprtAssociativity(const token_type& a_Tok) const;
270
271
    void CreateRPN() const;
272
273
    value_type ParseString() const;
274
    value_type ParseCmdCode() const;
275
    value_type ParseCmdCodeShort() const;
276
    value_type ParseCmdCodeBulk(int nOffset, int nThreadID) const;
277
278
    void  CheckName(const string_type& a_strName, const string_type& a_CharSet) const;
279
    void  CheckOprt(const string_type& a_sName, const ParserCallback& a_Callback, const string_type& a_szCharSet) const;
280
281
    void StackDump(const std::stack<token_type >& a_stVal, const std::stack<token_type >& a_stOprt) const;
282
283
    /** \brief Pointer to the parser function.
284
285
      Eval() calls the function whose address is stored there.
286
    */
287
    mutable ParseFunction  m_pParseFormula;
288
    mutable ParserByteCode m_vRPN;        ///< The Bytecode class.
289
    mutable stringbuf_type  m_vStringBuf; ///< String buffer, used for storing string function arguments
290
    stringbuf_type  m_vStringVarBuf;
291
292
    std::unique_ptr<token_reader_type> m_pTokenReader; ///< Managed pointer to the token reader object.
293
294
    funmap_type  m_FunDef;         ///< Map of function names and pointers.
295
    funmap_type  m_PostOprtDef;    ///< Postfix operator callbacks
296
    funmap_type  m_InfixOprtDef;   ///< unary infix operator.
297
    funmap_type  m_OprtDef;        ///< Binary operator callbacks
298
    valmap_type  m_ConstDef;       ///< user constants.
299
    strmap_type  m_StrVarDef;      ///< user defined string constants
300
    varmap_type  m_VarDef;         ///< user defind variables.
301
302
    bool m_bBuiltInOp;             ///< Flag that can be used for switching built in operators on and off
303
304
    string_type m_sNameChars;      ///< Charset for names
305
    string_type m_sOprtChars;      ///< Charset for postfix/ binary operator tokens
306
    string_type m_sInfixOprtChars; ///< Charset for infix operator tokens
307
308
    // items merely used for caching state information
309
    mutable valbuf_type m_vStackBuffer; ///< This is merely a buffer used for the stack in the cmd parsing routine
310
    mutable int m_nFinalResultIdx;
311
  };
312
313
} // namespace mu
314
315
#if defined(_MSC_VER)
316
  #pragma warning(pop)
317
#endif
318
319
#endif