LCOV - code coverage report
Current view: top level - frmts/vrt - vrtexpression_muparser.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 53 63 84.1 %
Date: 2025-01-18 12:42:00 Functions: 12 12 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  Virtual GDAL Datasets
       4             :  * Purpose:  Implementation of GDALExpressionEvaluator.
       5             :  * Author:   Daniel Baston
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2024, ISciences LLC
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "vrtexpression.h"
      14             : #include "cpl_string.h"
      15             : 
      16             : #include <map>
      17             : #include <muParser.h>
      18             : 
      19             : namespace gdal
      20             : {
      21             : 
      22             : /*! @cond Doxygen_Suppress */
      23             : class MuParserExpression::Impl
      24             : {
      25             :   public:
      26          19 :     explicit Impl(std::string_view osExpression)
      27          38 :         : m_osExpression(std::string(osExpression)), m_oVectors{}, m_oParser{},
      28          57 :           m_adfResults{1}, m_bIsCompiled{false}
      29             :     {
      30          19 :     }
      31             : 
      32          89 :     void Register(std::string_view osVariable, double *pdfValue)
      33             :     {
      34          89 :         m_oParser.DefineVar(std::string(osVariable), pdfValue);
      35          89 :     }
      36             : 
      37          27 :     CPLErr Compile()
      38             :     {
      39             :         try
      40             :         {
      41          54 :             CPLString tmpExpression(m_osExpression);
      42             : 
      43          40 :             for (const auto &[osVec, osElems] : m_oVectors)
      44             :             {
      45          13 :                 tmpExpression.replaceAll(osVec, osElems);
      46             :             }
      47             : 
      48          27 :             m_oParser.SetExpr(tmpExpression);
      49             :         }
      50           0 :         catch (const mu::Parser::exception_type &e)
      51             :         {
      52           0 :             CPLError(CE_Failure, CPLE_AppDefined, "%s", e.GetMsg().c_str());
      53           0 :             return CE_Failure;
      54             :         }
      55           0 :         catch (const std::exception &e)
      56             :         {
      57           0 :             CPLError(CE_Failure, CPLE_AppDefined, "%s", e.what());
      58           0 :             return CE_Failure;
      59             :         }
      60             : 
      61          27 :         return CE_None;
      62             :     }
      63             : 
      64          57 :     CPLErr Evaluate()
      65             :     {
      66          57 :         if (!m_bIsCompiled)
      67             :         {
      68          19 :             if (auto eErr = Compile(); eErr != CE_None)
      69             :             {
      70           0 :                 return eErr;
      71             :             }
      72             : 
      73          19 :             m_bIsCompiled = true;
      74             :         }
      75             : 
      76             :         try
      77             :         {
      78             :             int nResults;
      79          57 :             const double *dfResults = m_oParser.Eval(nResults);
      80          56 :             m_adfResults.resize(nResults);
      81          56 :             std::copy(dfResults, dfResults + nResults, m_adfResults.begin());
      82             :         }
      83           1 :         catch (const mu::Parser::exception_type &e)
      84             :         {
      85           1 :             CPLError(CE_Failure, CPLE_AppDefined, "%s", e.GetMsg().c_str());
      86           1 :             return CE_Failure;
      87             :         }
      88           0 :         catch (const std::exception &e)
      89             :         {
      90           0 :             CPLError(CE_Failure, CPLE_AppDefined, "%s", e.what());
      91           0 :             return CE_Failure;
      92             :         }
      93             : 
      94          56 :         return CE_None;
      95             :     }
      96             : 
      97             :     CPLString m_osExpression;
      98             :     std::map<CPLString, CPLString> m_oVectors;
      99             :     mu::Parser m_oParser;
     100             :     std::vector<double> m_adfResults;
     101             :     bool m_bIsCompiled;
     102             : };
     103             : 
     104          19 : MuParserExpression::MuParserExpression(std::string_view osExpression)
     105          19 :     : m_pImpl{std::make_unique<Impl>(osExpression)}
     106             : 
     107             : {
     108          19 : }
     109             : 
     110          38 : MuParserExpression::~MuParserExpression()
     111             : {
     112          38 : }
     113             : 
     114           8 : CPLErr MuParserExpression::Compile()
     115             : {
     116           8 :     return m_pImpl->Compile();
     117             : }
     118             : 
     119          89 : void MuParserExpression::RegisterVariable(std::string_view osVariable,
     120             :                                           double *pdfValue)
     121             : {
     122          89 :     m_pImpl->Register(osVariable, pdfValue);
     123          89 : }
     124             : 
     125           7 : void MuParserExpression::RegisterVector(std::string_view osVariable,
     126             :                                         std::vector<double> *padfValues)
     127             : {
     128             :     // muparser does not support vector variables, so we simulate them
     129             :     // by creating a scalar variable for each element, and then replacing
     130             :     // the name of the vector by a list of its elements before compiling
     131             :     // the expression.
     132          14 :     CPLString osElementVarName;
     133          14 :     CPLString osElementsList;
     134           7 :     std::string osVectorVarName(osVariable);
     135             : 
     136             :     int nElementVarNameLength = static_cast<int>(
     137           7 :         4 + osVectorVarName.size() + std::log10(padfValues->size()));
     138           7 :     osElementsList.reserve(padfValues->size() *
     139           7 :                            (1 + nElementVarNameLength));  // +1 for commas
     140             : 
     141          36 :     for (std::size_t i = 0; i < padfValues->size(); i++)
     142             :     {
     143             :         osElementVarName.Printf("__%s_%d", osVectorVarName.c_str(),
     144          29 :                                 static_cast<int>(i));
     145          29 :         RegisterVariable(osElementVarName, padfValues->data() + i);
     146             : 
     147          29 :         if (i > 0)
     148             :         {
     149          22 :             osElementsList += ",";
     150             :         }
     151          29 :         osElementsList += osElementVarName;
     152             :     }
     153             : 
     154           7 :     m_pImpl->m_oVectors[std::string(osVariable)] = osElementsList;
     155           7 : }
     156             : 
     157          57 : CPLErr MuParserExpression::Evaluate()
     158             : {
     159          57 :     return m_pImpl->Evaluate();
     160             : }
     161             : 
     162          71 : const std::vector<double> &MuParserExpression::Results() const
     163             : {
     164          71 :     return m_pImpl->m_adfResults;
     165             : }
     166             : 
     167             : /*! @endcond Doxygen_Suppress */
     168             : 
     169             : }  // namespace gdal

Generated by: LCOV version 1.14