diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 765f32d6..00000000 Binary files a/.DS_Store and /dev/null differ diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 2e4ae6e1..1851ac46 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -1,37 +1,76 @@ name: Test Build -on: [push, pull_request] +on: + push: + branches: [ main, master, release-* ] + pull_request: + branches: [ main, master ] jobs: - test: + build: + name: Build (${{ matrix.os }}) runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: - os: [windows-latest, macOS-latest, ubuntu-latest] + os: [windows-latest, macos-latest, ubuntu-latest] steps: - - name: Install Qt - uses: jurplel/install-qt-action@v2 + - name: Checkout Code + uses: actions/checkout@v4 with: - modules: 'qtcore qtgui qtwidgets qtopengl qtnetwork qtsvg qtscript qtscripttools qtprintsupport qtdatavis3d' - - - name: clone repository - uses: actions/checkout@v2 + submodules: recursive + - name: Install Qt + uses: jurplel/install-qt-action@v3 + with: + version: '6.8.3' + modules: 'qtdatavis3d qt5compat qtshadertools' + arch: ${{ runner.os == 'Windows' && 'win64_msvc2022_64' || '' }} - - name: Install Dependantcies And Make Linux - if: startsWith(matrix.os, 'ubuntu') + # --- LINUX --- + - name: Dependencies (Linux) + if: runner.os == 'Linux' run: | - sudo apt-get update -qq + sudo apt-get update sudo apt-get install -y libgsl-dev libglu1-mesa-dev freeglut3-dev mesa-common-dev - qmake CONFIG+=linux_all_dynamic - make - - - - name: Install Dependantcies And Make Mac - if: startsWith(matrix.os, 'mac') + + - name: Build (Linux) + if: runner.os == 'Linux' + run: | + qmake PRESET=linux_all_dynamic INCLUDEPATH+=/usr/include QMAKE_LIBDIR+=/usr/lib/x86_64-linux-gnu + make -j$(nproc) + + # --- MACOS --- + - name: Dependencies (macOS) + if: runner.os == 'macOS' + run: brew install gsl + + - name: Build (macOS) + if: runner.os == 'macOS' + run: | + qmake PRESET=osx_dist INCLUDEPATH+=/opt/homebrew/include QMAKE_LIBDIR+=/opt/homebrew/lib + make -j$(sysctl -n hw.ncpu) + + # --- WINDOWS --- + - name: Dependencies (Windows) + if: runner.os == 'Windows' + shell: cmd + run: | + vcpkg install gsl:x64-windows + echo GSL_ROOT=%VCPKG_INSTALLATION_ROOT%/installed/x64-windows>> %GITHUB_ENV% + + - name: Set up MSVC (Windows) + if: runner.os == 'Windows' + uses: ilammy/msvc-dev-cmd@v1 + + - name: Build (Windows) + if: runner.os == 'Windows' + shell: cmd run: | - brew install gsl - qmake CONFIG+=osx_dist - make - + cl + qmake -v + qmake -query + set + qmake PRESET=win32 + nmake \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..ba370786 --- /dev/null +++ b/.gitignore @@ -0,0 +1,70 @@ +# C++ objects and libs +*.slo +*.lo +*.o +*.a +*.la +*.lai +*.so +*.so.* +*.dll +*.dylib + +# Qt-es +object_script.*.Release +object_script.*.Debug +*_plugin_import.cpp +/.qmake.cache +/.qmake.stash +/build/.qmake.cache +/build/.qmake.stash +*.pro.user +*.pro.user.* +*.qbs.user +*.qbs.user.* +*.moc +moc_*.cpp +moc_*.h +qrc_*.cpp +ui_*.h +*.qmlc +*.jsc +Makefile* +*build-* +*.qm +*.prl + +# Qt unit tests +target_wrapper.* + +# QtCreator +*.autosave + +# QtCreator Qml +*.qmlproject.user +*.qmlproject.user.* + +# QtCreator CMake +CMakeLists.txt.user* + +# QtCreator 4.8< compilation database +compile_commands.json + +# QtCreator local machine specific files for imported projects +*creator.user* + +*_qmlcache.qrc + +# Temporary files +*.tmp +*.log +*.bak +*.swp + +# test output & cache +Run-make.sh +Testing/ +.cache/ +temp/ +build_retry/ +/alphaplot/alphaplot diff --git a/.qmake.conf b/.qmake.conf new file mode 100644 index 00000000..e3e6543e --- /dev/null +++ b/.qmake.conf @@ -0,0 +1,4 @@ +# Fail-safe MSVC version detection for GitHub Actions +win32 { + isEmpty(QMAKE_MSC_VER): QMAKE_MSC_VER = 1944 +} diff --git a/3rdparty/epsengine/EpsPaintDevice.cpp b/3rdparty/epsengine/EpsPaintDevice.cpp index 97a9d58d..31fd9283 100755 --- a/3rdparty/epsengine/EpsPaintDevice.cpp +++ b/3rdparty/epsengine/EpsPaintDevice.cpp @@ -9,7 +9,8 @@ Description : Enables the export of QPainter grafics to .eps files #include "EpsEngine.h" #include -#include +#include +#include EpsPaintDevice::EpsPaintDevice(const QString& fileName, const QSize& s) : QPaintDevice() @@ -49,7 +50,7 @@ void EpsPaintDevice::setCreator(const QString& s) int EpsPaintDevice::metric(PaintDeviceMetric metric) const { - QDesktopWidget *desktop = QApplication::desktop(); + QScreen *desktop = QGuiApplication::primaryScreen(); int dpi_x = desktop->logicalDpiX(); int dpi_y = desktop->logicalDpiY(); switch (metric){ diff --git a/3rdparty/muparser/muParser.cpp b/3rdparty/muparser/muParser.cpp index 39ea8610..53e692be 100644 --- a/3rdparty/muparser/muParser.cpp +++ b/3rdparty/muparser/muParser.cpp @@ -1,397 +1,264 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - - Copyright (C) 2013 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -#include "muParser.h" -#include "muParserTemplateMagic.h" - -//--- Standard includes ------------------------------------------------------------------------ -#include -#include -#include - -/** \brief Pi (what else?). */ -#define PARSER_CONST_PI 3.141592653589793238462643 - -/** \brief The Eulerian number. */ -#define PARSER_CONST_E 2.718281828459045235360287 - -using namespace std; - -/** \file - \brief Implementation of the standard floating point parser. -*/ - - - -/** \brief Namespace for mathematical applications. */ -namespace mu -{ - - - //--------------------------------------------------------------------------- - // Trigonometric function - value_type Parser::Sin(value_type v) { return MathImpl::Sin(v); } - value_type Parser::Cos(value_type v) { return MathImpl::Cos(v); } - value_type Parser::Tan(value_type v) { return MathImpl::Tan(v); } - value_type Parser::ASin(value_type v) { return MathImpl::ASin(v); } - value_type Parser::ACos(value_type v) { return MathImpl::ACos(v); } - value_type Parser::ATan(value_type v) { return MathImpl::ATan(v); } - value_type Parser::ATan2(value_type v1, value_type v2) { return MathImpl::ATan2(v1, v2); } - value_type Parser::Sinh(value_type v) { return MathImpl::Sinh(v); } - value_type Parser::Cosh(value_type v) { return MathImpl::Cosh(v); } - value_type Parser::Tanh(value_type v) { return MathImpl::Tanh(v); } - value_type Parser::ASinh(value_type v) { return MathImpl::ASinh(v); } - value_type Parser::ACosh(value_type v) { return MathImpl::ACosh(v); } - value_type Parser::ATanh(value_type v) { return MathImpl::ATanh(v); } - - //--------------------------------------------------------------------------- - // Logarithm functions - - // Logarithm base 2 - value_type Parser::Log2(value_type v) - { - #ifdef MUP_MATH_EXCEPTIONS - if (v<=0) - throw ParserError(ecDOMAIN_ERROR, _T("Log2")); - #endif - - return MathImpl::Log2(v); - } - - // Logarithm base 10 - value_type Parser::Log10(value_type v) - { - #ifdef MUP_MATH_EXCEPTIONS - if (v<=0) - throw ParserError(ecDOMAIN_ERROR, _T("Log10")); - #endif - - return MathImpl::Log10(v); - } - -// Logarithm base e (natural logarithm) - value_type Parser::Ln(value_type v) - { - #ifdef MUP_MATH_EXCEPTIONS - if (v<=0) - throw ParserError(ecDOMAIN_ERROR, _T("Ln")); - #endif - - return MathImpl::Log(v); - } - - //--------------------------------------------------------------------------- - // misc - value_type Parser::Exp(value_type v) { return MathImpl::Exp(v); } - value_type Parser::Abs(value_type v) { return MathImpl::Abs(v); } - value_type Parser::Sqrt(value_type v) - { - #ifdef MUP_MATH_EXCEPTIONS - if (v<0) - throw ParserError(ecDOMAIN_ERROR, _T("sqrt")); - #endif - - return MathImpl::Sqrt(v); - } - value_type Parser::Rint(value_type v) { return MathImpl::Rint(v); } - value_type Parser::Sign(value_type v) { return MathImpl::Sign(v); } - - //--------------------------------------------------------------------------- - /** \brief Callback for the unary minus operator. - \param v The value to negate - \return -v - */ - value_type Parser::UnaryMinus(value_type v) - { - return -v; - } - - //--------------------------------------------------------------------------- - /** \brief Callback for the unary minus operator. - \param v The value to negate - \return -v - */ - value_type Parser::UnaryPlus(value_type v) - { - return v; - } - - //--------------------------------------------------------------------------- - /** \brief Callback for adding multiple values. - \param [in] a_afArg Vector with the function arguments - \param [in] a_iArgc The size of a_afArg - */ - value_type Parser::Sum(const value_type *a_afArg, int a_iArgc) - { - if (!a_iArgc) - throw exception_type(_T("too few arguments for function sum.")); - - value_type fRes=0; - for (int i=0; i> fVal; - stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading - - if (iEnd==(stringstream_type::pos_type)-1) - return 0; - - *a_iPos += (int)iEnd; - *a_fVal = fVal; - return 1; - } - - - //--------------------------------------------------------------------------- - /** \brief Constructor. - - Call ParserBase class constructor and trigger Function, Operator and Constant initialization. - */ - Parser::Parser() - :ParserBase() - { - AddValIdent(IsVal); - - InitCharSets(); - InitFun(); - InitConst(); - InitOprt(); - } - - //--------------------------------------------------------------------------- - /** \brief Define the character sets. - \sa DefineNameChars, DefineOprtChars, DefineInfixOprtChars - - This function is used for initializing the default character sets that define - the characters to be useable in function and variable names and operators. - */ - void Parser::InitCharSets() - { - DefineNameChars( _T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") ); - DefineOprtChars( _T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-*^/?<>=#!$%&|~'_{}") ); - DefineInfixOprtChars( _T("/+-*^?<>=#!$%&|~'_") ); - } - - //--------------------------------------------------------------------------- - /** \brief Initialize the default functions. */ - void Parser::InitFun() - { - if (mu::TypeInfo::IsInteger()) - { - // When setting MUP_BASETYPE to an integer type - // Place functions for dealing with integer values here - // ... - // ... - // ... - } - else - { - // trigonometric functions - DefineFun(_T("sin"), Sin); - DefineFun(_T("cos"), Cos); - DefineFun(_T("tan"), Tan); - // arcus functions - DefineFun(_T("asin"), ASin); - DefineFun(_T("acos"), ACos); - DefineFun(_T("atan"), ATan); - DefineFun(_T("atan2"), ATan2); - // hyperbolic functions - DefineFun(_T("sinh"), Sinh); - DefineFun(_T("cosh"), Cosh); - DefineFun(_T("tanh"), Tanh); - // arcus hyperbolic functions - DefineFun(_T("asinh"), ASinh); - DefineFun(_T("acosh"), ACosh); - DefineFun(_T("atanh"), ATanh); - // Logarithm functions - DefineFun(_T("log2"), Log2); - DefineFun(_T("log10"), Log10); - DefineFun(_T("log"), Ln); - DefineFun(_T("ln"), Ln); - // misc - DefineFun(_T("exp"), Exp); - DefineFun(_T("sqrt"), Sqrt); - DefineFun(_T("sign"), Sign); - DefineFun(_T("rint"), Rint); - DefineFun(_T("abs"), Abs); - // Functions with variable number of arguments - DefineFun(_T("sum"), Sum); - DefineFun(_T("avg"), Avg); - DefineFun(_T("min"), Min); - DefineFun(_T("max"), Max); - } - } - - //--------------------------------------------------------------------------- - /** \brief Initialize constants. - - By default the parser recognizes two constants. Pi ("pi") and the Eulerian - number ("_e"). - */ - void Parser::InitConst() - { - DefineConst(_T("_pi"), (value_type)PARSER_CONST_PI); - DefineConst(_T("_e"), (value_type)PARSER_CONST_E); - } - - //--------------------------------------------------------------------------- - /** \brief Initialize operators. - - By default only the unary minus operator is added. - */ - void Parser::InitOprt() - { - DefineInfixOprt(_T("-"), UnaryMinus); - DefineInfixOprt(_T("+"), UnaryPlus); - } - - //--------------------------------------------------------------------------- - void Parser::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/) - { - // this is just sample code to illustrate modifying variable names on the fly. - // I'm not sure anyone really needs such a feature... - /* - - - string sVar(pExpr->begin()+nStart, pExpr->begin()+nEnd); - string sRepl = std::string("_") + sVar + "_"; - - int nOrigVarEnd = nEnd; - cout << "variable detected!\n"; - cout << " Expr: " << *pExpr << "\n"; - cout << " Start: " << nStart << "\n"; - cout << " End: " << nEnd << "\n"; - cout << " Var: \"" << sVar << "\"\n"; - cout << " Repl: \"" << sRepl << "\"\n"; - nEnd = nStart + sRepl.length(); - cout << " End: " << nEnd << "\n"; - pExpr->replace(pExpr->begin()+nStart, pExpr->begin()+nOrigVarEnd, sRepl); - cout << " New expr: " << *pExpr << "\n"; - */ - } - - //--------------------------------------------------------------------------- - /** \brief Numerically differentiate with regard to a variable. - \param [in] a_Var Pointer to the differentiation variable. - \param [in] a_fPos Position at which the differentiation should take place. - \param [in] a_fEpsilon Epsilon used for the numerical differentiation. - - Numerical differentiation uses a 5 point operator yielding a 4th order - formula. The default value for epsilon is 0.00074 which is - numeric_limits::epsilon() ^ (1/5) as suggested in the muparser - forum: - - http://sourceforge.net/forum/forum.php?thread_id=1994611&forum_id=462843 - */ - value_type Parser::Diff(value_type *a_Var, - value_type a_fPos, - value_type a_fEpsilon) const - { - value_type fRes(0), - fBuf(*a_Var), - f[4] = {0,0,0,0}, - fEpsilon(a_fEpsilon); - - // Backwards compatible calculation of epsilon inc case the user doesn't provide - // his own epsilon - if (fEpsilon==0) - fEpsilon = (a_fPos==0) ? (value_type)1e-10 : (value_type)1e-7 * a_fPos; - - *a_Var = a_fPos+2 * fEpsilon; f[0] = Eval(); - *a_Var = a_fPos+1 * fEpsilon; f[1] = Eval(); - *a_Var = a_fPos-1 * fEpsilon; f[2] = Eval(); - *a_Var = a_fPos-2 * fEpsilon; f[3] = Eval(); - *a_Var = fBuf; // restore variable - - fRes = (-f[0] + 8*f[1] - 8*f[2] + f[3]) / (12*fEpsilon); - return fRes; - } -} // namespace mu +/* + + _____ __ _____________ _______ ______ ___________ + / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ + | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ + |__|_| /____/| __(____ /__| /____ >\___ >__| + \/ |__| \/ \/ \/ + Copyright (C) 2004 - 2022 Ingo Berg + + Redistribution and use in source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "muParser.h" +#include "muParserTemplateMagic.h" + +//--- Standard includes ------------------------------------------------------------------------ +#include +#include +#include +#include + + +using namespace std; + +/** \file + \brief Implementation of the standard floating point parser. +*/ + + + +/** \brief Namespace for mathematical applications. */ +namespace mu +{ + //--------------------------------------------------------------------------- + /** \brief Default value recognition callback. + \param [in] a_szExpr Pointer to the expression + \param [in, out] a_iPos Pointer to an index storing the current position within the expression + \param [out] a_fVal Pointer where the value should be stored in case one is found. + \return 1 if a value was found 0 otherwise. + */ + int Parser::IsVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal) + { + // There is an issue with libc++ where it creates an error if a double value is followed by a character which + // is the case when using postfix operators. + // + // http://cplusplus.github.io/LWG/lwg-defects.html#2381 + // + // This happens only with libc++, not with libstdc++ (Gnu C++ standard library) + // It seems that Macs are using libc++. This is causing #123. The fix below will fix #123 + // but is will break localization support and cause #136. + + // I'm disabling this fix. For systems using libc++ you must put a space between floating point numbers and postfix operators. +#if defined(__APPLE__) && defined(NEVERTRUE) + try + { + std::size_t charsProcessed; + value_type fVal = static_cast(std::stod(string_type(a_szExpr), &charsProcessed)); + if (charsProcessed == 0) + return 0; + + *a_iPos += (int)charsProcessed; + *a_fVal = fVal; + return 1; + } + catch (...) + { + return 0; + } +#else + value_type fVal(0); + + stringstream_type stream(a_szExpr); + stream.imbue(Parser::s_locale); + stream >> fVal; + stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading + + if (iEnd == (stringstream_type::pos_type) - 1) + return 0; + + *a_iPos += (int)iEnd; + *a_fVal = fVal; + return 1; +#endif + } + + + //--------------------------------------------------------------------------- + /** \brief Constructor. + + Call ParserBase class constructor and trigger Function, Operator and Constant initialization. + */ + Parser::Parser() + :ParserBase() + { + AddValIdent(IsVal); + + InitCharSets(); + InitFun(); + InitConst(); + InitOprt(); + } + + //--------------------------------------------------------------------------- + /** \brief Define the character sets. + \sa DefineNameChars, DefineOprtChars, DefineInfixOprtChars + + This function is used for initializing the default character sets that define + the characters to be useable in function and variable names and operators. + */ + void Parser::InitCharSets() + { + DefineNameChars(_T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")); + DefineOprtChars(_T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-*^/?<>=#!$%&|~'_{}")); + DefineInfixOprtChars(_T("/+-*^?<>=#!$%&|~'_")); + } + + //--------------------------------------------------------------------------- + /** \brief Initialize the default functions. */ + void Parser::InitFun() + { + if (mu::TypeInfo::IsInteger()) + { + // When setting MUP_BASETYPE to an integer type + // Place functions for dealing with integer values here + // ... + // ... + // ... + } + else + { + // trigonometric functions + DefineFun(_T("sin"), MathImpl::Sin); + DefineFun(_T("cos"), MathImpl::Cos); + DefineFun(_T("tan"), MathImpl::Tan); + // arcus functions + DefineFun(_T("asin"), MathImpl::ASin); + DefineFun(_T("acos"), MathImpl::ACos); + DefineFun(_T("atan"), MathImpl::ATan); + DefineFun(_T("atan2"), MathImpl::ATan2); + // hyperbolic functions + DefineFun(_T("sinh"), MathImpl::Sinh); + DefineFun(_T("cosh"), MathImpl::Cosh); + DefineFun(_T("tanh"), MathImpl::Tanh); + // arcus hyperbolic functions + DefineFun(_T("asinh"), MathImpl::ASinh); + DefineFun(_T("acosh"), MathImpl::ACosh); + DefineFun(_T("atanh"), MathImpl::ATanh); + // Logarithm functions + DefineFun(_T("log2"), MathImpl::Log2); + DefineFun(_T("log10"), MathImpl::Log10); + DefineFun(_T("log"), MathImpl::Log); + DefineFun(_T("ln"), MathImpl::Log); + // misc + DefineFun(_T("exp"), MathImpl::Exp); + DefineFun(_T("sqrt"), MathImpl::Sqrt); + DefineFun(_T("sign"), MathImpl::Sign); + DefineFun(_T("rint"), MathImpl::Rint); + DefineFun(_T("abs"), MathImpl::Abs); + // Functions with variable number of arguments + DefineFun(_T("sum"), MathImpl::Sum); + DefineFun(_T("avg"), MathImpl::Avg); + DefineFun(_T("min"), MathImpl::Min); + DefineFun(_T("max"), MathImpl::Max); + // Random number + DefineFun(_T("rnd"), MathImpl::Rnd, false); + } + } + + //--------------------------------------------------------------------------- + /** \brief Initialize constants. + + By default the parser recognizes two constants. Pi ("pi") and the Eulerian + number ("_e"). + */ + void Parser::InitConst() + { + DefineConst(_T("_pi"), MathImpl::CONST_PI); + DefineConst(_T("_e"), MathImpl::CONST_E); + } + + //--------------------------------------------------------------------------- + /** \brief Initialize operators. + + By default only the unary minus operator is added. + */ + void Parser::InitOprt() + { + DefineInfixOprt(_T("-"), MathImpl::UnaryMinus); + DefineInfixOprt(_T("+"), MathImpl::UnaryPlus); + } + + //--------------------------------------------------------------------------- + void Parser::OnDetectVar(string_type* /*pExpr*/, int& /*nStart*/, int& /*nEnd*/) + { + // this is just sample code to illustrate modifying variable names on the fly. + // I'm not sure anyone really needs such a feature... + /* + + + string sVar(pExpr->begin()+nStart, pExpr->begin()+nEnd); + string sRepl = std::string("_") + sVar + "_"; + + int nOrigVarEnd = nEnd; + cout << "variable detected!\n"; + cout << " Expr: " << *pExpr << "\n"; + cout << " Start: " << nStart << "\n"; + cout << " End: " << nEnd << "\n"; + cout << " Var: \"" << sVar << "\"\n"; + cout << " Repl: \"" << sRepl << "\"\n"; + nEnd = nStart + sRepl.length(); + cout << " End: " << nEnd << "\n"; + pExpr->replace(pExpr->begin()+nStart, pExpr->begin()+nOrigVarEnd, sRepl); + cout << " New expr: " << *pExpr << "\n"; + */ + } + + //--------------------------------------------------------------------------- + /** \brief Numerically differentiate with regard to a variable. + \param [in] a_Var Pointer to the differentiation variable. + \param [in] a_fPos Position at which the differentiation should take place. + \param [in] a_fEpsilon Epsilon used for the numerical differentiation. + + Numerical differentiation uses a 5 point operator yielding a 4th order + formula. The default value for epsilon is 0.00074 which is + numeric_limits::epsilon() ^ (1/5). + */ + value_type Parser::Diff(value_type* a_Var, value_type a_fPos, value_type a_fEpsilon) const + { + value_type fRes(0); + value_type fBuf(*a_Var); + value_type f[4] = { 0,0,0,0 }; + value_type fEpsilon(a_fEpsilon); + + // Backwards compatible calculation of epsilon inc case the user doesn't provide + // his own epsilon + if (fEpsilon == 0) + fEpsilon = (a_fPos == 0) ? (value_type)1e-10 : (value_type)1e-7 * a_fPos; + + *a_Var = a_fPos + 2 * fEpsilon; f[0] = Eval(); + *a_Var = a_fPos + 1 * fEpsilon; f[1] = Eval(); + *a_Var = a_fPos - 1 * fEpsilon; f[2] = Eval(); + *a_Var = a_fPos - 2 * fEpsilon; f[3] = Eval(); + *a_Var = fBuf; // restore variable + + fRes = (-f[0] + 8 * f[1] - 8 * f[2] + f[3]) / (12 * fEpsilon); + return fRes; + } +} // namespace mu diff --git a/3rdparty/muparser/muParser.h b/3rdparty/muparser/muParser.h index 39fe137f..d00a9761 100644 --- a/3rdparty/muparser/muParser.h +++ b/3rdparty/muparser/muParser.h @@ -1,115 +1,71 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2013 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -#ifndef MU_PARSER_H -#define MU_PARSER_H - -//--- Standard includes ------------------------------------------------------------------------ -#include - -//--- Parser includes -------------------------------------------------------------------------- -#include "muParserBase.h" -#include "muParserTemplateMagic.h" - -/** \file - \brief Definition of the standard floating point parser. -*/ - -namespace mu -{ - /** \brief Mathematical expressions parser. - - Standard implementation of the mathematical expressions parser. - Can be used as a reference implementation for subclassing the parser. - - - (C) 2011 Ingo Berg
- muparser(at)beltoforion.de -
- */ - /* final */ class Parser : public ParserBase - { - public: - - Parser(); - - virtual void InitCharSets(); - virtual void InitFun(); - virtual void InitConst(); - virtual void InitOprt(); - virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd); - - value_type Diff(value_type *a_Var, - value_type a_fPos, - value_type a_fEpsilon = 0) const; - - protected: - - // Trigonometric functions - static value_type Sin(value_type); - static value_type Cos(value_type); - static value_type Tan(value_type); - static value_type Tan2(value_type, value_type); - // arcus functions - static value_type ASin(value_type); - static value_type ACos(value_type); - static value_type ATan(value_type); - static value_type ATan2(value_type, value_type); - - // hyperbolic functions - static value_type Sinh(value_type); - static value_type Cosh(value_type); - static value_type Tanh(value_type); - // arcus hyperbolic functions - static value_type ASinh(value_type); - static value_type ACosh(value_type); - static value_type ATanh(value_type); - // Logarithm functions - static value_type Log2(value_type); // Logarithm Base 2 - static value_type Log10(value_type); // Logarithm Base 10 - static value_type Ln(value_type); // Logarithm Base e (natural logarithm) - // misc - static value_type Exp(value_type); - static value_type Abs(value_type); - static value_type Sqrt(value_type); - static value_type Rint(value_type); - static value_type Sign(value_type); - - // Prefix operators - // !!! Unary Minus is a MUST if you want to use negative signs !!! - static value_type UnaryMinus(value_type); - static value_type UnaryPlus(value_type); - - // Functions with variable number of arguments - static value_type Sum(const value_type*, int); // sum - static value_type Avg(const value_type*, int); // mean value - static value_type Min(const value_type*, int); // minimum - static value_type Max(const value_type*, int); // maximum - - static int IsVal(const char_type* a_szExpr, int *a_iPos, value_type *a_fVal); - }; -} // namespace mu - -#endif - +/* + + _____ __ _____________ _______ ______ ___________ + / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ + | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ + |__|_| /____/| __(____ /__| /____ >\___ >__| + \/ |__| \/ \/ \/ + Copyright (C) 2004 - 2022 Ingo Berg + + Redistribution and use in source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef MU_PARSER_H +#define MU_PARSER_H + +//--- Standard includes ------------------------------------------------------------------------ +#include + +//--- Parser includes -------------------------------------------------------------------------- +#include "muParserBase.h" +#include "muParserTemplateMagic.h" + +/** \file + \brief Definition of the standard floating point parser. +*/ + +namespace mu +{ + /** \brief Mathematical expressions parser. + + Standard implementation of the mathematical expressions parser. + Can be used as a reference implementation for subclassing the parser. + */ + class API_EXPORT_CXX Parser : public ParserBase + { + public: + + Parser(); + + void InitCharSets() override; + void InitFun() override; + void InitConst() override; + void InitOprt() override; + void OnDetectVar(string_type* pExpr, int& nStart, int& nEnd) override; + + value_type Diff(value_type* a_Var, value_type a_fPos, value_type a_fEpsilon = 0) const; + + protected: + + static int IsVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal); + }; +} // namespace mu + +#endif + diff --git a/3rdparty/muparser/muParserBase.cpp b/3rdparty/muparser/muParserBase.cpp index ea3699a1..1ee8875f 100644 --- a/3rdparty/muparser/muParserBase.cpp +++ b/3rdparty/muparser/muParserBase.cpp @@ -1,1778 +1,1949 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2011 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "muParserBase.h" -#include "muParserTemplateMagic.h" - -//--- Standard includes ------------------------------------------------------------------------ -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef MUP_USE_OPENMP - #include -#endif - -using namespace std; - -/** \file - \brief This file contains the basic implementation of the muparser engine. -*/ - -namespace mu -{ - std::locale ParserBase::s_locale = std::locale(std::locale::classic(), new change_dec_sep('.')); - - bool ParserBase::g_DbgDumpCmdCode = false; - bool ParserBase::g_DbgDumpStack = false; - - //------------------------------------------------------------------------------ - /** \brief Identifiers for built in binary operators. - - When defining custom binary operators with #AddOprt(...) make sure not to choose - names conflicting with these definitions. - */ - const char_type* ParserBase::c_DefaultOprt[] = - { - _T("<="), _T(">="), _T("!="), - _T("=="), _T("<"), _T(">"), - _T("+"), _T("-"), _T("*"), - _T("/"), _T("^"), _T("&&"), - _T("||"), _T("="), _T("("), - _T(")"), _T("?"), _T(":"), 0 - }; - - //------------------------------------------------------------------------------ - /** \brief Constructor. - \param a_szFormula the formula to interpret. - \throw ParserException if a_szFormula is null. - */ - ParserBase::ParserBase() - :m_pParseFormula(&ParserBase::ParseString) - ,m_vRPN() - ,m_vStringBuf() - ,m_pTokenReader() - ,m_FunDef() - ,m_PostOprtDef() - ,m_InfixOprtDef() - ,m_OprtDef() - ,m_ConstDef() - ,m_StrVarDef() - ,m_VarDef() - ,m_bBuiltInOp(true) - ,m_sNameChars() - ,m_sOprtChars() - ,m_sInfixOprtChars() - ,m_nIfElseCounter(0) - ,m_vStackBuffer() - ,m_nFinalResultIdx(0) - { - InitTokenReader(); - } - - //--------------------------------------------------------------------------- - /** \brief Copy constructor. - - The parser can be safely copy constructed but the bytecode is reset during - copy construction. - */ - ParserBase::ParserBase(const ParserBase &a_Parser) - :m_pParseFormula(&ParserBase::ParseString) - ,m_vRPN() - ,m_vStringBuf() - ,m_pTokenReader() - ,m_FunDef() - ,m_PostOprtDef() - ,m_InfixOprtDef() - ,m_OprtDef() - ,m_ConstDef() - ,m_StrVarDef() - ,m_VarDef() - ,m_bBuiltInOp(true) - ,m_sNameChars() - ,m_sOprtChars() - ,m_sInfixOprtChars() - ,m_nIfElseCounter(0) - { - m_pTokenReader.reset(new token_reader_type(this)); - Assign(a_Parser); - } - - //--------------------------------------------------------------------------- - ParserBase::~ParserBase() - {} - - //--------------------------------------------------------------------------- - /** \brief Assignment operator. - - Implemented by calling Assign(a_Parser). Self assignment is suppressed. - \param a_Parser Object to copy to this. - \return *this - \throw nothrow - */ - ParserBase& ParserBase::operator=(const ParserBase &a_Parser) - { - Assign(a_Parser); - return *this; - } - - //--------------------------------------------------------------------------- - /** \brief Copy state of a parser object to this. - - Clears Variables and Functions of this parser. - Copies the states of all internal variables. - Resets parse function to string parse mode. - - \param a_Parser the source object. - */ - void ParserBase::Assign(const ParserBase &a_Parser) - { - if (&a_Parser==this) - return; - - // Don't copy bytecode instead cause the parser to create new bytecode - // by resetting the parse function. - ReInit(); - - m_ConstDef = a_Parser.m_ConstDef; // Copy user define constants - m_VarDef = a_Parser.m_VarDef; // Copy user defined variables - m_bBuiltInOp = a_Parser.m_bBuiltInOp; - m_vStringBuf = a_Parser.m_vStringBuf; - m_vStackBuffer = a_Parser.m_vStackBuffer; - m_nFinalResultIdx = a_Parser.m_nFinalResultIdx; - m_StrVarDef = a_Parser.m_StrVarDef; - m_vStringVarBuf = a_Parser.m_vStringVarBuf; - m_nIfElseCounter = a_Parser.m_nIfElseCounter; - m_pTokenReader.reset(a_Parser.m_pTokenReader->Clone(this)); - - // Copy function and operator callbacks - m_FunDef = a_Parser.m_FunDef; // Copy function definitions - m_PostOprtDef = a_Parser.m_PostOprtDef; // post value unary operators - m_InfixOprtDef = a_Parser.m_InfixOprtDef; // unary operators for infix notation - m_OprtDef = a_Parser.m_OprtDef; // binary operators - - m_sNameChars = a_Parser.m_sNameChars; - m_sOprtChars = a_Parser.m_sOprtChars; - m_sInfixOprtChars = a_Parser.m_sInfixOprtChars; - } - - //--------------------------------------------------------------------------- - /** \brief Set the decimal separator. - \param cDecSep Decimal separator as a character value. - \sa SetThousandsSep - - By default muparser uses the "C" locale. The decimal separator of this - locale is overwritten by the one provided here. - */ - void ParserBase::SetDecSep(char_type cDecSep) - { - char_type cThousandsSep = std::use_facet< change_dec_sep >(s_locale).thousands_sep(); - s_locale = std::locale(std::locale("C"), new change_dec_sep(cDecSep, cThousandsSep)); - } - - //--------------------------------------------------------------------------- - /** \brief Sets the thousands operator. - \param cThousandsSep The thousands separator as a character - \sa SetDecSep - - By default muparser uses the "C" locale. The thousands separator of this - locale is overwritten by the one provided here. - */ - void ParserBase::SetThousandsSep(char_type cThousandsSep) - { - char_type cDecSep = std::use_facet< change_dec_sep >(s_locale).decimal_point(); - s_locale = std::locale(std::locale("C"), new change_dec_sep(cDecSep, cThousandsSep)); - } - - //--------------------------------------------------------------------------- - /** \brief Resets the locale. - - The default locale used "." as decimal separator, no thousands separator and - "," as function argument separator. - */ - void ParserBase::ResetLocale() - { - s_locale = std::locale(std::locale("C"), new change_dec_sep('.')); - SetArgSep(','); - } - - //--------------------------------------------------------------------------- - /** \brief Initialize the token reader. - - Create new token reader object and submit pointers to function, operator, - constant and variable definitions. - - \post m_pTokenReader.get()!=0 - \throw nothrow - */ - void ParserBase::InitTokenReader() - { - m_pTokenReader.reset(new token_reader_type(this)); - } - - //--------------------------------------------------------------------------- - /** \brief Reset parser to string parsing mode and clear internal buffers. - - Clear bytecode, reset the token reader. - \throw nothrow - */ - void ParserBase::ReInit() const - { - m_pParseFormula = &ParserBase::ParseString; - m_vStringBuf.clear(); - m_vRPN.clear(); - m_pTokenReader->ReInit(); - m_nIfElseCounter = 0; - } - - //--------------------------------------------------------------------------- - void ParserBase::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/) - {} - - //--------------------------------------------------------------------------- - /** \brief Returns the version of muparser. - \param eInfo A flag indicating whether the full version info should be - returned or not. - - Format is as follows: "MAJOR.MINOR (COMPILER_FLAGS)" The COMPILER_FLAGS - are returned only if eInfo==pviFULL. - */ - string_type ParserBase::GetVersion(EParserVersionInfo eInfo) const - { - stringstream_type ss; - - ss << MUP_VERSION; - - if (eInfo==pviFULL) - { - ss << _T(" (") << MUP_VERSION_DATE; - ss << std::dec << _T("; ") << sizeof(void*)*8 << _T("BIT"); - -#ifdef _DEBUG - ss << _T("; DEBUG"); -#else - ss << _T("; RELEASE"); -#endif - -#ifdef _UNICODE - ss << _T("; UNICODE"); -#else - #ifdef _MBCS - ss << _T("; MBCS"); - #else - ss << _T("; ASCII"); - #endif -#endif - -#ifdef MUP_USE_OPENMP - ss << _T("; OPENMP"); -//#else -// ss << _T("; NO_OPENMP"); -#endif - -#if defined(MUP_MATH_EXCEPTIONS) - ss << _T("; MATHEXC"); -//#else -// ss << _T("; NO_MATHEXC"); -#endif - - ss << _T(")"); - } - - return ss.str(); - } - - //--------------------------------------------------------------------------- - /** \brief Add a value parsing function. - - When parsing an expression muParser tries to detect values in the expression - string using different valident callbacks. Thus it's possible to parse - for hex values, binary values and floating point values. - */ - void ParserBase::AddValIdent(identfun_type a_pCallback) - { - m_pTokenReader->AddValIdent(a_pCallback); - } - - //--------------------------------------------------------------------------- - /** \brief Set a function that can create variable pointer for unknown expression variables. - \param a_pFactory A pointer to the variable factory. - \param pUserData A user defined context pointer. - */ - void ParserBase::SetVarFactory(facfun_type a_pFactory, void *pUserData) - { - m_pTokenReader->SetVarCreator(a_pFactory, pUserData); - } - - //--------------------------------------------------------------------------- - /** \brief Add a function or operator callback to the parser. */ - void ParserBase::AddCallback( const string_type &a_strName, - const ParserCallback &a_Callback, - funmap_type &a_Storage, - const char_type *a_szCharSet ) - { - if (a_Callback.GetAddr()==0) - Error(ecINVALID_FUN_PTR); - - const funmap_type *pFunMap = &a_Storage; - - // Check for conflicting operator or function names - if ( pFunMap!=&m_FunDef && m_FunDef.find(a_strName)!=m_FunDef.end() ) - Error(ecNAME_CONFLICT, -1, a_strName); - - if ( pFunMap!=&m_PostOprtDef && m_PostOprtDef.find(a_strName)!=m_PostOprtDef.end() ) - Error(ecNAME_CONFLICT, -1, a_strName); - - if ( pFunMap!=&m_InfixOprtDef && pFunMap!=&m_OprtDef && m_InfixOprtDef.find(a_strName)!=m_InfixOprtDef.end() ) - Error(ecNAME_CONFLICT, -1, a_strName); - - if ( pFunMap!=&m_InfixOprtDef && pFunMap!=&m_OprtDef && m_OprtDef.find(a_strName)!=m_OprtDef.end() ) - Error(ecNAME_CONFLICT, -1, a_strName); - - CheckOprt(a_strName, a_Callback, a_szCharSet); - a_Storage[a_strName] = a_Callback; - ReInit(); - } - - //--------------------------------------------------------------------------- - /** \brief Check if a name contains invalid characters. - - \throw ParserException if the name contains invalid characters. - */ - void ParserBase::CheckOprt(const string_type &a_sName, - const ParserCallback &a_Callback, - const string_type &a_szCharSet) const - { - if ( !a_sName.length() || - (a_sName.find_first_not_of(a_szCharSet)!=string_type::npos) || - (a_sName[0]>='0' && a_sName[0]<='9')) - { - switch(a_Callback.GetCode()) - { - case cmOPRT_POSTFIX: Error(ecINVALID_POSTFIX_IDENT, -1, a_sName); - case cmOPRT_INFIX: Error(ecINVALID_INFIX_IDENT, -1, a_sName); - default: Error(ecINVALID_NAME, -1, a_sName); - } - } - } - - //--------------------------------------------------------------------------- - /** \brief Check if a name contains invalid characters. - - \throw ParserException if the name contains invalid characters. - */ - void ParserBase::CheckName(const string_type &a_sName, - const string_type &a_szCharSet) const - { - if ( !a_sName.length() || - (a_sName.find_first_not_of(a_szCharSet)!=string_type::npos) || - (a_sName[0]>='0' && a_sName[0]<='9')) - { - Error(ecINVALID_NAME); - } - } - - //--------------------------------------------------------------------------- - /** \brief Set the formula. - \param a_strFormula Formula as string_type - \throw ParserException in case of syntax errors. - - Triggers first time calculation thus the creation of the bytecode and - scanning of used variables. - */ - void ParserBase::SetExpr(const string_type &a_sExpr) - { - // Check locale compatibility - std::locale loc; - if (m_pTokenReader->GetArgSep()==std::use_facet >(loc).decimal_point()) - Error(ecLOCALE); - - // 20060222: Bugfix for Borland-Kylix: - // adding a space to the expression will keep Borlands KYLIX from going wild - // when calling tellg on a stringstream created from the expression after - // reading a value at the end of an expression. (mu::Parser::IsVal function) - // (tellg returns -1 otherwise causing the parser to ignore the value) - string_type sBuf(a_sExpr + _T(" ") ); - m_pTokenReader->SetFormula(sBuf); - ReInit(); - } - - //--------------------------------------------------------------------------- - /** \brief Get the default symbols used for the built in operators. - \sa c_DefaultOprt - */ - const char_type** ParserBase::GetOprtDef() const - { - return (const char_type **)(&c_DefaultOprt[0]); - } - - //--------------------------------------------------------------------------- - /** \brief Define the set of valid characters to be used in names of - functions, variables, constants. - */ - void ParserBase::DefineNameChars(const char_type *a_szCharset) - { - m_sNameChars = a_szCharset; - } - - //--------------------------------------------------------------------------- - /** \brief Define the set of valid characters to be used in names of - binary operators and postfix operators. - */ - void ParserBase::DefineOprtChars(const char_type *a_szCharset) - { - m_sOprtChars = a_szCharset; - } - - //--------------------------------------------------------------------------- - /** \brief Define the set of valid characters to be used in names of - infix operators. - */ - void ParserBase::DefineInfixOprtChars(const char_type *a_szCharset) - { - m_sInfixOprtChars = a_szCharset; - } - - //--------------------------------------------------------------------------- - /** \brief Virtual function that defines the characters allowed in name identifiers. - \sa #ValidOprtChars, #ValidPrefixOprtChars - */ - const char_type* ParserBase::ValidNameChars() const - { - assert(m_sNameChars.size()); - return m_sNameChars.c_str(); - } - - //--------------------------------------------------------------------------- - /** \brief Virtual function that defines the characters allowed in operator definitions. - \sa #ValidNameChars, #ValidPrefixOprtChars - */ - const char_type* ParserBase::ValidOprtChars() const - { - assert(m_sOprtChars.size()); - return m_sOprtChars.c_str(); - } - - //--------------------------------------------------------------------------- - /** \brief Virtual function that defines the characters allowed in infix operator definitions. - \sa #ValidNameChars, #ValidOprtChars - */ - const char_type* ParserBase::ValidInfixOprtChars() const - { - assert(m_sInfixOprtChars.size()); - return m_sInfixOprtChars.c_str(); - } - - //--------------------------------------------------------------------------- - /** \brief Add a user defined operator. - \post Will reset the Parser to string parsing mode. - */ - void ParserBase::DefinePostfixOprt(const string_type &a_sName, - fun_type1 a_pFun, - bool a_bAllowOpt) - { - AddCallback(a_sName, - ParserCallback(a_pFun, a_bAllowOpt, prPOSTFIX, cmOPRT_POSTFIX), - m_PostOprtDef, - ValidOprtChars() ); - } - - //--------------------------------------------------------------------------- - /** \brief Initialize user defined functions. - - Calls the virtual functions InitFun(), InitConst() and InitOprt(). - */ - void ParserBase::Init() - { - InitCharSets(); - InitFun(); - InitConst(); - InitOprt(); - } - - //--------------------------------------------------------------------------- - /** \brief Add a user defined operator. - \post Will reset the Parser to string parsing mode. - \param [in] a_sName operator Identifier - \param [in] a_pFun Operator callback function - \param [in] a_iPrec Operator Precedence (default=prSIGN) - \param [in] a_bAllowOpt True if operator is volatile (default=false) - \sa EPrec - */ - void ParserBase::DefineInfixOprt(const string_type &a_sName, - fun_type1 a_pFun, - int a_iPrec, - bool a_bAllowOpt) - { - AddCallback(a_sName, - ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, cmOPRT_INFIX), - m_InfixOprtDef, - ValidInfixOprtChars() ); - } - - - //--------------------------------------------------------------------------- - /** \brief Define a binary operator. - \param [in] a_sName The identifier of the operator. - \param [in] a_pFun Pointer to the callback function. - \param [in] a_iPrec Precedence of the operator. - \param [in] a_eAssociativity The associativity of the operator. - \param [in] a_bAllowOpt If this is true the operator may be optimized away. - - Adds a new Binary operator the the parser instance. - */ - void ParserBase::DefineOprt( const string_type &a_sName, - fun_type2 a_pFun, - unsigned a_iPrec, - EOprtAssociativity a_eAssociativity, - bool a_bAllowOpt ) - { - // Check for conflicts with built in operator names - for (int i=0; m_bBuiltInOp && iIgnoreUndefVar(true); - CreateRPN(); // try to create bytecode, but don't use it for any further calculations since it - // may contain references to nonexisting variables. - m_pParseFormula = &ParserBase::ParseString; - m_pTokenReader->IgnoreUndefVar(false); - } - catch(exception_type & /*e*/) - { - // Make sure to stay in string parse mode, dont call ReInit() - // because it deletes the array with the used variables - m_pParseFormula = &ParserBase::ParseString; - m_pTokenReader->IgnoreUndefVar(false); - throw; - } - - return m_pTokenReader->GetUsedVar(); - } - - //--------------------------------------------------------------------------- - /** \brief Return a map containing the used variables only. */ - const varmap_type& ParserBase::GetVar() const - { - return m_VarDef; - } - - //--------------------------------------------------------------------------- - /** \brief Return a map containing all parser constants. */ - const valmap_type& ParserBase::GetConst() const - { - return m_ConstDef; - } - - //--------------------------------------------------------------------------- - /** \brief Return prototypes of all parser functions. - \return #m_FunDef - \sa FunProt - \throw nothrow - - The return type is a map of the public type #funmap_type containing the prototype - definitions for all numerical parser functions. String functions are not part of - this map. The Prototype definition is encapsulated in objects of the class FunProt - one per parser function each associated with function names via a map construct. - */ - const funmap_type& ParserBase::GetFunDef() const - { - return m_FunDef; - } - - //--------------------------------------------------------------------------- - /** \brief Retrieve the formula. */ - const string_type& ParserBase::GetExpr() const - { - return m_pTokenReader->GetExpr(); - } - - //--------------------------------------------------------------------------- - /** \brief Execute a function that takes a single string argument. - \param a_FunTok Function token. - \throw exception_type If the function token is not a string function - */ - ParserBase::token_type ParserBase::ApplyStrFunc(const token_type &a_FunTok, - const std::vector &a_vArg) const - { - if (a_vArg.back().GetCode()!=cmSTRING) - Error(ecSTRING_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString()); - - token_type valTok; - generic_fun_type pFunc = a_FunTok.GetFuncAddr(); - assert(pFunc); - - try - { - // Check function arguments; write dummy value into valtok to represent the result - switch(a_FunTok.GetArgCount()) - { - case 0: valTok.SetVal(1); a_vArg[0].GetAsString(); break; - case 1: valTok.SetVal(1); a_vArg[1].GetAsString(); a_vArg[0].GetVal(); break; - case 2: valTok.SetVal(1); a_vArg[2].GetAsString(); a_vArg[1].GetVal(); a_vArg[0].GetVal(); break; - default: Error(ecINTERNAL_ERROR); - } - } - catch(ParserError& ) - { - Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString()); - } - - // string functions won't be optimized - m_vRPN.AddStrFun(pFunc, a_FunTok.GetArgCount(), a_vArg.back().GetIdx()); - - // Push dummy value representing the function result to the stack - return valTok; - } - - //--------------------------------------------------------------------------- - /** \brief Apply a function token. - \param iArgCount Number of Arguments actually gathered used only for multiarg functions. - \post The result is pushed to the value stack - \post The function token is removed from the stack - \throw exception_type if Argument count does not match function requirements. - */ - void ParserBase::ApplyFunc( ParserStack &a_stOpt, - ParserStack &a_stVal, - int a_iArgCount) const - { - assert(m_pTokenReader.get()); - - // Operator stack empty or does not contain tokens with callback functions - if (a_stOpt.empty() || a_stOpt.top().GetFuncAddr()==0 ) - return; - - token_type funTok = a_stOpt.pop(); - assert(funTok.GetFuncAddr()); - - // Binary operators must rely on their internal operator number - // since counting of operators relies on commas for function arguments - // binary operators do not have commas in their expression - int iArgCount = (funTok.GetCode()==cmOPRT_BIN) ? funTok.GetArgCount() : a_iArgCount; - - // determine how many parameters the function needs. To remember iArgCount includes the - // string parameter whilst GetArgCount() counts only numeric parameters. - int iArgRequired = funTok.GetArgCount() + ((funTok.GetType()==tpSTR) ? 1 : 0); - - // Thats the number of numerical parameters - int iArgNumerical = iArgCount - ((funTok.GetType()==tpSTR) ? 1 : 0); - - if (funTok.GetCode()==cmFUNC_STR && iArgCount-iArgNumerical>1) - Error(ecINTERNAL_ERROR); - - if (funTok.GetArgCount()>=0 && iArgCount>iArgRequired) - Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos()-1, funTok.GetAsString()); - - if (funTok.GetCode()!=cmOPRT_BIN && iArgCountGetPos()-1, funTok.GetAsString()); - - if (funTok.GetCode()==cmFUNC_STR && iArgCount>iArgRequired ) - Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos()-1, funTok.GetAsString()); - - // Collect the numeric function arguments from the value stack and store them - // in a vector - std::vector stArg; - for (int i=0; iGetPos(), funTok.GetAsString()); - } - - switch(funTok.GetCode()) - { - case cmFUNC_STR: - stArg.push_back(a_stVal.pop()); - - if ( stArg.back().GetType()==tpSTR && funTok.GetType()!=tpSTR ) - Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString()); - - ApplyStrFunc(funTok, stArg); - break; - - case cmFUNC_BULK: - m_vRPN.AddBulkFun(funTok.GetFuncAddr(), (int)stArg.size()); - break; - - case cmOPRT_BIN: - case cmOPRT_POSTFIX: - case cmOPRT_INFIX: - case cmFUNC: - if (funTok.GetArgCount()==-1 && iArgCount==0) - Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos(), funTok.GetAsString()); - - m_vRPN.AddFun(funTok.GetFuncAddr(), (funTok.GetArgCount()==-1) ? -iArgNumerical : iArgNumerical); - break; - } - - // Push dummy value representing the function result to the stack - token_type token; - token.SetVal(1); - a_stVal.push(token); - } - - //--------------------------------------------------------------------------- - void ParserBase::ApplyIfElse(ParserStack &a_stOpt, - ParserStack &a_stVal) const - { - // Check if there is an if Else clause to be calculated - while (a_stOpt.size() && a_stOpt.top().GetCode()==cmELSE) - { - token_type opElse = a_stOpt.pop(); - MUP_ASSERT(a_stOpt.size()>0); - - // Take the value associated with the else branch from the value stack - token_type vVal2 = a_stVal.pop(); - - MUP_ASSERT(a_stOpt.size()>0); - MUP_ASSERT(a_stVal.size()>=2); - - // it then else is a ternary operator Pop all three values from the value s - // tack and just return the right value - token_type vVal1 = a_stVal.pop(); - token_type vExpr = a_stVal.pop(); - - a_stVal.push( (vExpr.GetVal()!=0) ? vVal1 : vVal2); - - token_type opIf = a_stOpt.pop(); - MUP_ASSERT(opElse.GetCode()==cmELSE); - MUP_ASSERT(opIf.GetCode()==cmIF); - - m_vRPN.AddIfElse(cmENDIF); - } // while pending if-else-clause found - } - - //--------------------------------------------------------------------------- - /** \brief Performs the necessary steps to write code for - the execution of binary operators into the bytecode. - */ - void ParserBase::ApplyBinOprt(ParserStack &a_stOpt, - ParserStack &a_stVal) const - { - // is it a user defined binary operator? - if (a_stOpt.top().GetCode()==cmOPRT_BIN) - { - ApplyFunc(a_stOpt, a_stVal, 2); - } - else - { - MUP_ASSERT(a_stVal.size()>=2); - token_type valTok1 = a_stVal.pop(), - valTok2 = a_stVal.pop(), - optTok = a_stOpt.pop(), - resTok; - - if ( valTok1.GetType()!=valTok2.GetType() || - (valTok1.GetType()==tpSTR && valTok2.GetType()==tpSTR) ) - Error(ecOPRT_TYPE_CONFLICT, m_pTokenReader->GetPos(), optTok.GetAsString()); - - if (optTok.GetCode()==cmASSIGN) - { - if (valTok2.GetCode()!=cmVAR) - Error(ecUNEXPECTED_OPERATOR, -1, _T("=")); - - m_vRPN.AddAssignOp(valTok2.GetVar()); - } - else - m_vRPN.AddOp(optTok.GetCode()); - - resTok.SetVal(1); - a_stVal.push(resTok); - } - } - - //--------------------------------------------------------------------------- - /** \brief Apply a binary operator. - \param a_stOpt The operator stack - \param a_stVal The value stack - */ - void ParserBase::ApplyRemainingOprt(ParserStack &stOpt, - ParserStack &stVal) const - { - while (stOpt.size() && - stOpt.top().GetCode() != cmBO && - stOpt.top().GetCode() != cmIF) - { - token_type tok = stOpt.top(); - switch (tok.GetCode()) - { - case cmOPRT_INFIX: - case cmOPRT_BIN: - case cmLE: - case cmGE: - case cmNEQ: - case cmEQ: - case cmLT: - case cmGT: - case cmADD: - case cmSUB: - case cmMUL: - case cmDIV: - case cmPOW: - case cmLAND: - case cmLOR: - case cmASSIGN: - if (stOpt.top().GetCode()==cmOPRT_INFIX) - ApplyFunc(stOpt, stVal, 1); - else - ApplyBinOprt(stOpt, stVal); - break; - - case cmELSE: - ApplyIfElse(stOpt, stVal); - break; - - default: - Error(ecINTERNAL_ERROR); - } - } - } - - //--------------------------------------------------------------------------- - /** \brief Parse the command code. - \sa ParseString(...) - - Command code contains precalculated stack positions of the values and the - associated operators. The Stack is filled beginning from index one the - value at index zero is not used at all. - */ - value_type ParserBase::ParseCmdCode() const - { - return ParseCmdCodeBulk(0, 0); - } - - //--------------------------------------------------------------------------- - /** \brief Evaluate the RPN. - \param nOffset The offset added to variable addresses (for bulk mode) - \param nThreadID OpenMP Thread id of the calling thread - */ - value_type ParserBase::ParseCmdCodeBulk(int nOffset, int nThreadID) const - { - assert(nThreadID<=s_MaxNumOpenMPThreads); - - // Note: The check for nOffset==0 and nThreadID here is not necessary but - // brings a minor performance gain when not in bulk mode. - value_type *Stack = ((nOffset==0) && (nThreadID==0)) ? &m_vStackBuffer[0] : &m_vStackBuffer[nThreadID * (m_vStackBuffer.size() / s_MaxNumOpenMPThreads)]; - value_type buf; - int sidx(0); - for (const SToken *pTok = m_vRPN.GetBase(); pTok->Cmd!=cmEND ; ++pTok) - { - switch (pTok->Cmd) - { - // built in binary operators - case cmLE: --sidx; Stack[sidx] = Stack[sidx] <= Stack[sidx+1]; continue; - case cmGE: --sidx; Stack[sidx] = Stack[sidx] >= Stack[sidx+1]; continue; - case cmNEQ: --sidx; Stack[sidx] = Stack[sidx] != Stack[sidx+1]; continue; - case cmEQ: --sidx; Stack[sidx] = Stack[sidx] == Stack[sidx+1]; continue; - case cmLT: --sidx; Stack[sidx] = Stack[sidx] < Stack[sidx+1]; continue; - case cmGT: --sidx; Stack[sidx] = Stack[sidx] > Stack[sidx+1]; continue; - case cmADD: --sidx; Stack[sidx] += Stack[1+sidx]; continue; - case cmSUB: --sidx; Stack[sidx] -= Stack[1+sidx]; continue; - case cmMUL: --sidx; Stack[sidx] *= Stack[1+sidx]; continue; - case cmDIV: --sidx; - - #if defined(MUP_MATH_EXCEPTIONS) - if (Stack[1+sidx]==0) - Error(ecDIV_BY_ZERO); - #endif - Stack[sidx] /= Stack[1+sidx]; - continue; - - case cmPOW: - --sidx; Stack[sidx] = MathImpl::Pow(Stack[sidx], Stack[1+sidx]); - continue; - - case cmLAND: --sidx; Stack[sidx] = Stack[sidx] && Stack[sidx+1]; continue; - case cmLOR: --sidx; Stack[sidx] = Stack[sidx] || Stack[sidx+1]; continue; - - case cmASSIGN: - // Bugfix for Bulkmode: - // for details see: - // https://groups.google.com/forum/embed/?place=forum/muparser-dev&showsearch=true&showpopout=true&showtabs=false&parenturl=http://muparser.beltoforion.de/mup_forum.html&afterlogin&pli=1#!topic/muparser-dev/szgatgoHTws - --sidx; Stack[sidx] = *(pTok->Oprt.ptr + nOffset) = Stack[sidx + 1]; continue; - // original code: - //--sidx; Stack[sidx] = *pTok->Oprt.ptr = Stack[sidx+1]; continue; - - //case cmBO: // unused, listed for compiler optimization purposes - //case cmBC: - // MUP_FAIL(INVALID_CODE_IN_BYTECODE); - // continue; - - case cmIF: - if (Stack[sidx--]==0) - pTok += pTok->Oprt.offset; - continue; - - case cmELSE: - pTok += pTok->Oprt.offset; - continue; - - case cmENDIF: - continue; - - //case cmARG_SEP: - // MUP_FAIL(INVALID_CODE_IN_BYTECODE); - // continue; - - // value and variable tokens - case cmVAR: Stack[++sidx] = *(pTok->Val.ptr + nOffset); continue; - case cmVAL: Stack[++sidx] = pTok->Val.data2; continue; - - case cmVARPOW2: buf = *(pTok->Val.ptr + nOffset); - Stack[++sidx] = buf*buf; - continue; - - case cmVARPOW3: buf = *(pTok->Val.ptr + nOffset); - Stack[++sidx] = buf*buf*buf; - continue; - - case cmVARPOW4: buf = *(pTok->Val.ptr + nOffset); - Stack[++sidx] = buf*buf*buf*buf; - continue; - - case cmVARMUL: Stack[++sidx] = *(pTok->Val.ptr + nOffset) * pTok->Val.data + pTok->Val.data2; - continue; - - // Next is treatment of numeric functions - case cmFUNC: - { - int iArgCount = pTok->Fun.argc; - - // switch according to argument count - switch(iArgCount) - { - case 0: sidx += 1; Stack[sidx] = (*(fun_type0)pTok->Fun.ptr)(); continue; - case 1: Stack[sidx] = (*(fun_type1)pTok->Fun.ptr)(Stack[sidx]); continue; - case 2: sidx -= 1; Stack[sidx] = (*(fun_type2)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1]); continue; - case 3: sidx -= 2; Stack[sidx] = (*(fun_type3)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2]); continue; - case 4: sidx -= 3; Stack[sidx] = (*(fun_type4)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3]); continue; - case 5: sidx -= 4; Stack[sidx] = (*(fun_type5)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4]); continue; - case 6: sidx -= 5; Stack[sidx] = (*(fun_type6)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5]); continue; - case 7: sidx -= 6; Stack[sidx] = (*(fun_type7)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6]); continue; - case 8: sidx -= 7; Stack[sidx] = (*(fun_type8)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7]); continue; - case 9: sidx -= 8; Stack[sidx] = (*(fun_type9)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8]); continue; - case 10:sidx -= 9; Stack[sidx] = (*(fun_type10)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8], Stack[sidx+9]); continue; - default: - if (iArgCount>0) // function with variable arguments store the number as a negative value - Error(ecINTERNAL_ERROR, 1); - - sidx -= -iArgCount - 1; - Stack[sidx] =(*(multfun_type)pTok->Fun.ptr)(&Stack[sidx], -iArgCount); - continue; - } - } - - // Next is treatment of string functions - case cmFUNC_STR: - { - sidx -= pTok->Fun.argc -1; - - // The index of the string argument in the string table - int iIdxStack = pTok->Fun.idx; - MUP_ASSERT( iIdxStack>=0 && iIdxStack<(int)m_vStringBuf.size() ); - - switch(pTok->Fun.argc) // switch according to argument count - { - case 0: Stack[sidx] = (*(strfun_type1)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str()); continue; - case 1: Stack[sidx] = (*(strfun_type2)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx]); continue; - case 2: Stack[sidx] = (*(strfun_type3)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx], Stack[sidx+1]); continue; - } - - continue; - } - - case cmFUNC_BULK: - { - int iArgCount = pTok->Fun.argc; - - // switch according to argument count - switch(iArgCount) - { - case 0: sidx += 1; Stack[sidx] = (*(bulkfun_type0 )pTok->Fun.ptr)(nOffset, nThreadID); continue; - case 1: Stack[sidx] = (*(bulkfun_type1 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx]); continue; - case 2: sidx -= 1; Stack[sidx] = (*(bulkfun_type2 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1]); continue; - case 3: sidx -= 2; Stack[sidx] = (*(bulkfun_type3 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2]); continue; - case 4: sidx -= 3; Stack[sidx] = (*(bulkfun_type4 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3]); continue; - case 5: sidx -= 4; Stack[sidx] = (*(bulkfun_type5 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4]); continue; - case 6: sidx -= 5; Stack[sidx] = (*(bulkfun_type6 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5]); continue; - case 7: sidx -= 6; Stack[sidx] = (*(bulkfun_type7 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6]); continue; - case 8: sidx -= 7; Stack[sidx] = (*(bulkfun_type8 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7]); continue; - case 9: sidx -= 8; Stack[sidx] = (*(bulkfun_type9 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8]); continue; - case 10:sidx -= 9; Stack[sidx] = (*(bulkfun_type10)pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8], Stack[sidx+9]); continue; - default: - Error(ecINTERNAL_ERROR, 2); - continue; - } - } - - default: - Error(ecINTERNAL_ERROR, 3); - return 0; - } // switch CmdCode - } // for all bytecode tokens - - return Stack[m_nFinalResultIdx]; - } - - //--------------------------------------------------------------------------- - void ParserBase::CreateRPN() const - { - if (!m_pTokenReader->GetExpr().length()) - Error(ecUNEXPECTED_EOF, 0); - - ParserStack stOpt, stVal; - ParserStack stArgCount; - token_type opta, opt; // for storing operators - token_type val, tval; // for storing value - - ReInit(); - - // The outermost counter counts the number of separated items - // such as in "a=10,b=20,c=c+a" - stArgCount.push(1); - - for(;;) - { - opt = m_pTokenReader->ReadNextToken(); - - switch (opt.GetCode()) - { - // - // Next three are different kind of value entries - // - case cmSTRING: - opt.SetIdx((int)m_vStringBuf.size()); // Assign buffer index to token - stVal.push(opt); - m_vStringBuf.push_back(opt.GetAsString()); // Store string in internal buffer - break; - - case cmVAR: - stVal.push(opt); - m_vRPN.AddVar( static_cast(opt.GetVar()) ); - break; - - case cmVAL: - stVal.push(opt); - m_vRPN.AddVal( opt.GetVal() ); - break; - - case cmELSE: - m_nIfElseCounter--; - if (m_nIfElseCounter<0) - Error(ecMISPLACED_COLON, m_pTokenReader->GetPos()); - - ApplyRemainingOprt(stOpt, stVal); - m_vRPN.AddIfElse(cmELSE); - stOpt.push(opt); - break; - - - case cmARG_SEP: - if (stArgCount.empty()) - Error(ecUNEXPECTED_ARG_SEP, m_pTokenReader->GetPos()); - - ++stArgCount.top(); - // fallthrough intentional (no break!) - - case cmEND: - ApplyRemainingOprt(stOpt, stVal); - break; - - case cmBC: - { - // The argument count for parameterless functions is zero - // by default an opening bracket sets parameter count to 1 - // in preparation of arguments to come. If the last token - // was an opening bracket we know better... - if (opta.GetCode()==cmBO) - --stArgCount.top(); - - ApplyRemainingOprt(stOpt, stVal); - - // Check if the bracket content has been evaluated completely - if (stOpt.size() && stOpt.top().GetCode()==cmBO) - { - // if opt is ")" and opta is "(" the bracket has been evaluated, now its time to check - // if there is either a function or a sign pending - // neither the opening nor the closing bracket will be pushed back to - // the operator stack - // Check if a function is standing in front of the opening bracket, - // if yes evaluate it afterwards check for infix operators - assert(stArgCount.size()); - int iArgCount = stArgCount.pop(); - - stOpt.pop(); // Take opening bracket from stack - - if (iArgCount>1 && ( stOpt.size()==0 || - (stOpt.top().GetCode()!=cmFUNC && - stOpt.top().GetCode()!=cmFUNC_BULK && - stOpt.top().GetCode()!=cmFUNC_STR) ) ) - Error(ecUNEXPECTED_ARG, m_pTokenReader->GetPos()); - - // The opening bracket was popped from the stack now check if there - // was a function before this bracket - if (stOpt.size() && - stOpt.top().GetCode()!=cmOPRT_INFIX && - stOpt.top().GetCode()!=cmOPRT_BIN && - stOpt.top().GetFuncAddr()!=0) - { - ApplyFunc(stOpt, stVal, iArgCount); - } - } - } // if bracket content is evaluated - break; - - // - // Next are the binary operator entries - // - //case cmAND: // built in binary operators - //case cmOR: - //case cmXOR: - case cmIF: - m_nIfElseCounter++; - // fallthrough intentional (no break!) - - case cmLAND: - case cmLOR: - case cmLT: - case cmGT: - case cmLE: - case cmGE: - case cmNEQ: - case cmEQ: - case cmADD: - case cmSUB: - case cmMUL: - case cmDIV: - case cmPOW: - case cmASSIGN: - case cmOPRT_BIN: - - // A binary operator (user defined or built in) has been found. - while ( stOpt.size() && - stOpt.top().GetCode() != cmBO && - stOpt.top().GetCode() != cmELSE && - stOpt.top().GetCode() != cmIF) - { - int nPrec1 = GetOprtPrecedence(stOpt.top()), - nPrec2 = GetOprtPrecedence(opt); - - if (stOpt.top().GetCode()==opt.GetCode()) - { - - // Deal with operator associativity - EOprtAssociativity eOprtAsct = GetOprtAssociativity(opt); - if ( (eOprtAsct==oaRIGHT && (nPrec1 <= nPrec2)) || - (eOprtAsct==oaLEFT && (nPrec1 < nPrec2)) ) - { - break; - } - } - else if (nPrec1 < nPrec2) - { - // In case the operators are not equal the precedence decides alone... - break; - } - - if (stOpt.top().GetCode()==cmOPRT_INFIX) - ApplyFunc(stOpt, stVal, 1); - else - ApplyBinOprt(stOpt, stVal); - } // while ( ... ) - - if (opt.GetCode()==cmIF) - m_vRPN.AddIfElse(opt.GetCode()); - - // The operator can't be evaluated right now, push back to the operator stack - stOpt.push(opt); - break; - - // - // Last section contains functions and operators implicitly mapped to functions - // - case cmBO: - stArgCount.push(1); - stOpt.push(opt); - break; - - case cmOPRT_INFIX: - case cmFUNC: - case cmFUNC_BULK: - case cmFUNC_STR: - stOpt.push(opt); - break; - - case cmOPRT_POSTFIX: - stOpt.push(opt); - ApplyFunc(stOpt, stVal, 1); // this is the postfix operator - break; - - default: Error(ecINTERNAL_ERROR, 3); - } // end of switch operator-token - - opta = opt; - - if ( opt.GetCode() == cmEND ) - { - m_vRPN.Finalize(); - break; - } - - if (ParserBase::g_DbgDumpStack) - { - StackDump(stVal, stOpt); - m_vRPN.AsciiDump(); - } - } // while (true) - - if (ParserBase::g_DbgDumpCmdCode) - m_vRPN.AsciiDump(); - - if (m_nIfElseCounter>0) - Error(ecMISSING_ELSE_CLAUSE); - - // get the last value (= final result) from the stack - MUP_ASSERT(stArgCount.size()==1); - m_nFinalResultIdx = stArgCount.top(); - if (m_nFinalResultIdx==0) - Error(ecINTERNAL_ERROR, 9); - - if (stVal.size()==0) - Error(ecEMPTY_EXPRESSION); - - if (stVal.top().GetType()!=tpDBL) - Error(ecSTR_RESULT); - - m_vStackBuffer.resize(m_vRPN.GetMaxStackSize() * s_MaxNumOpenMPThreads); - } - - //--------------------------------------------------------------------------- - /** \brief One of the two main parse functions. - \sa ParseCmdCode(...) - - Parse expression from input string. Perform syntax checking and create - bytecode. After parsing the string and creating the bytecode the function - pointer #m_pParseFormula will be changed to the second parse routine the - uses bytecode instead of string parsing. - */ - value_type ParserBase::ParseString() const - { - try - { - CreateRPN(); - m_pParseFormula = &ParserBase::ParseCmdCode; - return (this->*m_pParseFormula)(); - } - catch(ParserError &exc) - { - exc.SetFormula(m_pTokenReader->GetExpr()); - throw; - } - } - - //--------------------------------------------------------------------------- - /** \brief Create an error containing the parse error position. - - This function will create an Parser Exception object containing the error text and - its position. - - \param a_iErrc [in] The error code of type #EErrorCodes. - \param a_iPos [in] The position where the error was detected. - \param a_strTok [in] The token string representation associated with the error. - \throw ParserException always throws thats the only purpose of this function. - */ - void ParserBase::Error(EErrorCodes a_iErrc, int a_iPos, const string_type &a_sTok) const - { - throw exception_type(a_iErrc, a_sTok, m_pTokenReader->GetExpr(), a_iPos); - } - - //------------------------------------------------------------------------------ - /** \brief Clear all user defined variables. - \throw nothrow - - Resets the parser to string parsing mode by calling #ReInit. - */ - void ParserBase::ClearVar() - { - m_VarDef.clear(); - ReInit(); - } - - //------------------------------------------------------------------------------ - /** \brief Remove a variable from internal storage. - \throw nothrow - - Removes a variable if it exists. If the Variable does not exist nothing will be done. - */ - void ParserBase::RemoveVar(const string_type &a_strVarName) - { - varmap_type::iterator item = m_VarDef.find(a_strVarName); - if (item!=m_VarDef.end()) - { - m_VarDef.erase(item); - ReInit(); - } - } - - //------------------------------------------------------------------------------ - /** \brief Clear all functions. - \post Resets the parser to string parsing mode. - \throw nothrow - */ - void ParserBase::ClearFun() - { - m_FunDef.clear(); - ReInit(); - } - - //------------------------------------------------------------------------------ - /** \brief Clear all user defined constants. - - Both numeric and string constants will be removed from the internal storage. - \post Resets the parser to string parsing mode. - \throw nothrow - */ - void ParserBase::ClearConst() - { - m_ConstDef.clear(); - m_StrVarDef.clear(); - ReInit(); - } - - //------------------------------------------------------------------------------ - /** \brief Clear all user defined postfix operators. - \post Resets the parser to string parsing mode. - \throw nothrow - */ - void ParserBase::ClearPostfixOprt() - { - m_PostOprtDef.clear(); - ReInit(); - } - - //------------------------------------------------------------------------------ - /** \brief Clear all user defined binary operators. - \post Resets the parser to string parsing mode. - \throw nothrow - */ - void ParserBase::ClearOprt() - { - m_OprtDef.clear(); - ReInit(); - } - - //------------------------------------------------------------------------------ - /** \brief Clear the user defined Prefix operators. - \post Resets the parser to string parser mode. - \throw nothrow - */ - void ParserBase::ClearInfixOprt() - { - m_InfixOprtDef.clear(); - ReInit(); - } - - //------------------------------------------------------------------------------ - /** \brief Enable or disable the formula optimization feature. - \post Resets the parser to string parser mode. - \throw nothrow - */ - void ParserBase::EnableOptimizer(bool a_bIsOn) - { - m_vRPN.EnableOptimizer(a_bIsOn); - ReInit(); - } - - //--------------------------------------------------------------------------- - /** \brief Enable the dumping of bytecode and stack content on the console. - \param bDumpCmd Flag to enable dumping of the current bytecode to the console. - \param bDumpStack Flag to enable dumping of the stack content is written to the console. - - This function is for debug purposes only! - */ - void ParserBase::EnableDebugDump(bool bDumpCmd, bool bDumpStack) - { - ParserBase::g_DbgDumpCmdCode = bDumpCmd; - ParserBase::g_DbgDumpStack = bDumpStack; - } - - //------------------------------------------------------------------------------ - /** \brief Enable or disable the built in binary operators. - \throw nothrow - \sa m_bBuiltInOp, ReInit() - - If you disable the built in binary operators there will be no binary operators - defined. Thus you must add them manually one by one. It is not possible to - disable built in operators selectively. This function will Reinitialize the - parser by calling ReInit(). - */ - void ParserBase::EnableBuiltInOprt(bool a_bIsOn) - { - m_bBuiltInOp = a_bIsOn; - ReInit(); - } - - //------------------------------------------------------------------------------ - /** \brief Query status of built in variables. - \return #m_bBuiltInOp; true if built in operators are enabled. - \throw nothrow - */ - bool ParserBase::HasBuiltInOprt() const - { - return m_bBuiltInOp; - } - - //------------------------------------------------------------------------------ - /** \brief Get the argument separator character. - */ - char_type ParserBase::GetArgSep() const - { - return m_pTokenReader->GetArgSep(); - } - - //------------------------------------------------------------------------------ - /** \brief Set argument separator. - \param cArgSep the argument separator character. - */ - void ParserBase::SetArgSep(char_type cArgSep) - { - m_pTokenReader->SetArgSep(cArgSep); - } - - //------------------------------------------------------------------------------ - /** \brief Dump stack content. - - This function is used for debugging only. - */ - void ParserBase::StackDump(const ParserStack &a_stVal, - const ParserStack &a_stOprt) const - { - ParserStack stOprt(a_stOprt), - stVal(a_stVal); - - mu::console() << _T("\nValue stack:\n"); - while ( !stVal.empty() ) - { - token_type val = stVal.pop(); - if (val.GetType()==tpSTR) - mu::console() << _T(" \"") << val.GetAsString() << _T("\" "); - else - mu::console() << _T(" ") << val.GetVal() << _T(" "); - } - mu::console() << "\nOperator stack:\n"; - - while ( !stOprt.empty() ) - { - if (stOprt.top().GetCode()<=cmASSIGN) - { - mu::console() << _T("OPRT_INTRNL \"") - << ParserBase::c_DefaultOprt[stOprt.top().GetCode()] - << _T("\" \n"); - } - else - { - switch(stOprt.top().GetCode()) - { - case cmVAR: mu::console() << _T("VAR\n"); break; - case cmVAL: mu::console() << _T("VAL\n"); break; - case cmFUNC: mu::console() << _T("FUNC \"") - << stOprt.top().GetAsString() - << _T("\"\n"); break; - case cmFUNC_BULK: mu::console() << _T("FUNC_BULK \"") - << stOprt.top().GetAsString() - << _T("\"\n"); break; - case cmOPRT_INFIX: mu::console() << _T("OPRT_INFIX \"") - << stOprt.top().GetAsString() - << _T("\"\n"); break; - case cmOPRT_BIN: mu::console() << _T("OPRT_BIN \"") - << stOprt.top().GetAsString() - << _T("\"\n"); break; - case cmFUNC_STR: mu::console() << _T("FUNC_STR\n"); break; - case cmEND: mu::console() << _T("END\n"); break; - case cmUNKNOWN: mu::console() << _T("UNKNOWN\n"); break; - case cmBO: mu::console() << _T("BRACKET \"(\"\n"); break; - case cmBC: mu::console() << _T("BRACKET \")\"\n"); break; - case cmIF: mu::console() << _T("IF\n"); break; - case cmELSE: mu::console() << _T("ELSE\n"); break; - case cmENDIF: mu::console() << _T("ENDIF\n"); break; - default: mu::console() << stOprt.top().GetCode() << _T(" "); break; - } - } - stOprt.pop(); - } - - mu::console() << dec << endl; - } - - //------------------------------------------------------------------------------ - /** \brief Evaluate an expression containing comma separated subexpressions - \param [out] nStackSize The total number of results available - \return Pointer to the array containing all expression results - - This member function can be used to retrieve all results of an expression - made up of multiple comma separated subexpressions (i.e. "x+y,sin(x),cos(y)") - */ - value_type* ParserBase::Eval(int &nStackSize) const - { - (this->*m_pParseFormula)(); - nStackSize = m_nFinalResultIdx; - - // (for historic reasons the stack starts at position 1) - return &m_vStackBuffer[1]; - } - - //--------------------------------------------------------------------------- - /** \brief Return the number of results on the calculation stack. - - If the expression contains comma separated subexpressions (i.e. "sin(y), x+y"). - There may be more than one return value. This function returns the number of - available results. - */ - int ParserBase::GetNumResults() const - { - return m_nFinalResultIdx; - } - - //--------------------------------------------------------------------------- - /** \brief Calculate the result. - - A note on const correctness: - I consider it important that Calc is a const function. - Due to caching operations Calc changes only the state of internal variables with one exception - m_UsedVar this is reset during string parsing and accessible from the outside. Instead of making - Calc non const GetUsedVar is non const because it explicitly calls Eval() forcing this update. - - \pre A formula must be set. - \pre Variables must have been set (if needed) - - \sa #m_pParseFormula - \return The evaluation result - \throw ParseException if no Formula is set or in case of any other error related to the formula. - */ - value_type ParserBase::Eval() const - { - return (this->*m_pParseFormula)(); - } - - //--------------------------------------------------------------------------- - void ParserBase::Eval(value_type *results, int nBulkSize) - { -/* Commented because it is making a unit test impossible - - // Parallelization does not make sense for fewer than 10000 computations - // due to thread creation overhead. If the bulk size is below 2000 - // computation is refused. - if (nBulkSize<2000) - { - throw ParserError(ecUNREASONABLE_NUMBER_OF_COMPUTATIONS); - } -*/ - CreateRPN(); - - int i = 0; - -#ifdef MUP_USE_OPENMP -//#define DEBUG_OMP_STUFF - #ifdef DEBUG_OMP_STUFF - int *pThread = new int[nBulkSize]; - int *pIdx = new int[nBulkSize]; - #endif - - int nMaxThreads = std::min(omp_get_max_threads(), s_MaxNumOpenMPThreads); - int nThreadID = 0, ct = 0; - omp_set_num_threads(nMaxThreads); - - #pragma omp parallel for schedule(static, nBulkSize/nMaxThreads) private(nThreadID) - for (i=0; i > __ \| | \/\___ \\ ___/| | \/ + |__|_| /____/| __(____ /__| /____ >\___ >__| + \/ |__| \/ \/ \/ + Copyright (C) 2022 Ingo Berg + + Redistribution and use in source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "muParserBase.h" +#include "muParserTemplateMagic.h" + +//--- Standard includes ------------------------------------------------------------------------ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef MUP_USE_OPENMP + +#include + +#endif + +#if defined(_MSC_VER) + #pragma warning(push) + #pragma warning(disable : 26812) +#endif + +using namespace std; + +/** \file + \brief This file contains the basic implementation of the muparser engine. +*/ + +namespace mu +{ + std::locale ParserBase::s_locale = std::locale(std::locale::classic(), new change_dec_sep('.')); + + bool ParserBase::g_DbgDumpCmdCode = false; + bool ParserBase::g_DbgDumpStack = false; + + //------------------------------------------------------------------------------ + /** \brief Identifiers for built in binary operators. + + When defining custom binary operators with #AddOprt(...) make sure not to choose + names conflicting with these definitions. + */ + const char_type* ParserBase::c_DefaultOprt[] = + { + _T("<="), _T(">="), _T("!="), + _T("=="), _T("<"), _T(">"), + _T("+"), _T("-"), _T("*"), + _T("/"), _T("^"), _T("&&"), + _T("||"), _T("="), _T("("), + _T(")"), _T("?"), _T(":"), 0 + }; + + const int ParserBase::s_MaxNumOpenMPThreads = 16; + + //------------------------------------------------------------------------------ + /** \brief Constructor. + \param a_szFormula the formula to interpret. + \throw ParserException if a_szFormula is nullptr. + */ + ParserBase::ParserBase() + : m_pParseFormula(&ParserBase::ParseString) + , m_vRPN() + , m_vStringBuf() + , m_pTokenReader() + , m_FunDef() + , m_PostOprtDef() + , m_InfixOprtDef() + , m_OprtDef() + , m_ConstDef() + , m_StrVarDef() + , m_VarDef() + , m_bBuiltInOp(true) + , m_sNameChars() + , m_sOprtChars() + , m_sInfixOprtChars() + , m_vStackBuffer() + , m_nFinalResultIdx(0) + { + InitTokenReader(); + } + + //--------------------------------------------------------------------------- + /** \brief Copy constructor. + + The parser can be safely copy constructed but the bytecode is reset during + copy construction. + */ + ParserBase::ParserBase(const ParserBase& a_Parser) + : m_pParseFormula(&ParserBase::ParseString) + , m_vRPN() + , m_vStringBuf() + , m_pTokenReader() + , m_FunDef() + , m_PostOprtDef() + , m_InfixOprtDef() + , m_OprtDef() + , m_ConstDef() + , m_StrVarDef() + , m_VarDef() + , m_bBuiltInOp(true) + , m_sNameChars() + , m_sOprtChars() + , m_sInfixOprtChars() + { + m_pTokenReader.reset(new token_reader_type(this)); + Assign(a_Parser); + } + + //--------------------------------------------------------------------------- + ParserBase::~ParserBase() + {} + + //--------------------------------------------------------------------------- + /** \brief Assignment operator. + + Implemented by calling Assign(a_Parser). Self assignment is suppressed. + \param a_Parser Object to copy to this. + \return *this + \throw nothrow + */ + ParserBase& ParserBase::operator=(const ParserBase& a_Parser) + { + Assign(a_Parser); + return *this; + } + + //--------------------------------------------------------------------------- + /** \brief Copy state of a parser object to this. + + Clears Variables and Functions of this parser. + Copies the states of all internal variables. + Resets parse function to string parse mode. + + \param a_Parser the source object. + */ + void ParserBase::Assign(const ParserBase& a_Parser) + { + if (&a_Parser == this) + return; + + // Don't copy bytecode instead cause the parser to create new bytecode + // by resetting the parse function. + ReInit(); + + m_ConstDef = a_Parser.m_ConstDef; // Copy user define constants + m_VarDef = a_Parser.m_VarDef; // Copy user defined variables + m_bBuiltInOp = a_Parser.m_bBuiltInOp; + m_vStringBuf = a_Parser.m_vStringBuf; + m_vStackBuffer = a_Parser.m_vStackBuffer; + m_nFinalResultIdx = a_Parser.m_nFinalResultIdx; + m_StrVarDef = a_Parser.m_StrVarDef; + m_vStringVarBuf = a_Parser.m_vStringVarBuf; + m_pTokenReader.reset(a_Parser.m_pTokenReader->Clone(this)); + + // Copy function and operator callbacks + m_FunDef = a_Parser.m_FunDef; // Copy function definitions + m_PostOprtDef = a_Parser.m_PostOprtDef; // post value unary operators + m_InfixOprtDef = a_Parser.m_InfixOprtDef; // unary operators for infix notation + m_OprtDef = a_Parser.m_OprtDef; // binary operators + + m_sNameChars = a_Parser.m_sNameChars; + m_sOprtChars = a_Parser.m_sOprtChars; + m_sInfixOprtChars = a_Parser.m_sInfixOprtChars; + } + + //--------------------------------------------------------------------------- + /** \brief Set the decimal separator. + \param cDecSep Decimal separator as a character value. + \sa SetThousandsSep + + By default muparser uses the "C" locale. The decimal separator of this + locale is overwritten by the one provided here. + */ + void ParserBase::SetDecSep(char_type cDecSep) + { + char_type cThousandsSep = std::use_facet< change_dec_sep >(s_locale).thousands_sep(); + s_locale = std::locale(std::locale("C"), new change_dec_sep(cDecSep, cThousandsSep)); + } + + //--------------------------------------------------------------------------- + /** \brief Sets the thousands operator. + \param cThousandsSep The thousands separator as a character + \sa SetDecSep + + By default muparser uses the "C" locale. The thousands separator of this + locale is overwritten by the one provided here. + */ + void ParserBase::SetThousandsSep(char_type cThousandsSep) + { + char_type cDecSep = std::use_facet< change_dec_sep >(s_locale).decimal_point(); + s_locale = std::locale(std::locale("C"), new change_dec_sep(cDecSep, cThousandsSep)); + } + + //--------------------------------------------------------------------------- + /** \brief Resets the locale. + + The default locale used "." as decimal separator, no thousands separator and + "," as function argument separator. + */ + void ParserBase::ResetLocale() + { + s_locale = std::locale(std::locale("C"), new change_dec_sep('.')); + SetArgSep(','); + } + + //--------------------------------------------------------------------------- + /** \brief Initialize the token reader. + + Create new token reader object and submit pointers to function, operator, + constant and variable definitions. + + \post m_pTokenReader.get()!=0 + \throw nothrow + */ + void ParserBase::InitTokenReader() + { + m_pTokenReader.reset(new token_reader_type(this)); + } + + //--------------------------------------------------------------------------- + /** \brief Reset parser to string parsing mode and clear internal buffers. + + Clear bytecode, reset the token reader. + \throw nothrow + */ + void ParserBase::ReInit() const + { + m_pParseFormula = &ParserBase::ParseString; + m_vStringBuf.clear(); + m_vRPN.clear(); + m_pTokenReader->ReInit(); + } + + + void ParserBase::OnDetectVar(string_type* /*pExpr*/, int& /*nStart*/, int& /*nEnd*/) + {} + + + /** \brief Returns a copy of the bytecode of the current expression. + */ + const ParserByteCode& ParserBase::GetByteCode() const + { + // If a variable factory is defined the bytecode may contain references to implicitely + // created variables. +// if (m_pTokenReader->HasVarCreator()) +// Error(ecBYTECODE_IMPORT_EXPORT_DISABLED); + + return m_vRPN; + } + + + /** \brief Restore a previously saved bytecode. */ + void ParserBase::SetByteCode(const ParserByteCode& a_ByteCode) + { + // If a variable factory is defined the bytecode may contain references to dynamically + // created variables. +// if (m_pTokenReader->HasVarCreator()) +// Error(ecBYTECODE_IMPORT_EXPORT_DISABLED); + + m_vRPN = a_ByteCode; + + // restore expression environment + string_type expr; + std::tie(expr, m_vStringBuf) = a_ByteCode.RestoreEnvironment(); + m_pTokenReader->SetFormula(expr); + + m_pParseFormula = &ParserBase::ParseCmdCode; + } + + + /** \brief Returns the version of muparser. + \param eInfo A flag indicating whether the full version info should be + returned or not. + + Format is as follows: "MAJOR.MINOR (COMPILER_FLAGS)" The COMPILER_FLAGS + are returned only if eInfo==pviFULL. + */ + string_type ParserBase::GetVersion(EParserVersionInfo eInfo) const + { + stringstream_type ss; + + ss << ParserVersion; + + if (eInfo == pviFULL) + { + ss << _T(" (") << ParserVersionDate; + ss << std::dec << _T("; ") << sizeof(void*) * 8 << _T("BIT"); + +#ifdef _DEBUG + ss << _T("; DEBUG"); +#else + ss << _T("; RELEASE"); +#endif + +#ifdef _UNICODE + ss << _T("; UNICODE"); +#else +#ifdef _MBCS + ss << _T("; MBCS"); +#else + ss << _T("; ASCII"); +#endif +#endif + +#ifdef MUP_USE_OPENMP + ss << _T("; OPENMP"); +#endif + + ss << _T(")"); + } + + return ss.str(); + } + + //--------------------------------------------------------------------------- + /** \brief Add a value parsing function. + + When parsing an expression muParser tries to detect values in the expression + string using different valident callbacks. Thus it's possible to parse + for hex values, binary values and floating point values. + */ + void ParserBase::AddValIdent(identfun_type a_pCallback) + { + m_pTokenReader->AddValIdent(a_pCallback); + } + + //--------------------------------------------------------------------------- + /** \brief Set a function that can create variable pointer for unknown expression variables. + \param a_pFactory A pointer to the variable factory. + \param pUserData A user defined context pointer. + */ + void ParserBase::SetVarFactory(facfun_type a_pFactory, void* pUserData) + { + m_pTokenReader->SetVarCreator(a_pFactory, pUserData); + } + + //--------------------------------------------------------------------------- + /** \brief Add a function or operator callback to the parser. */ + void ParserBase::AddCallback( + const string_type& a_strName, + const ParserCallback& a_Callback, + funmap_type& a_Storage, + const char_type* a_szCharSet) + { + if (!a_Callback.IsValid()) + Error(ecINVALID_FUN_PTR); + + const funmap_type* pFunMap = &a_Storage; + + // Check for conflicting operator or function names + if (pFunMap != &m_FunDef && m_FunDef.find(a_strName) != m_FunDef.end()) + Error(ecNAME_CONFLICT, -1, a_strName); + + if (pFunMap != &m_PostOprtDef && m_PostOprtDef.find(a_strName) != m_PostOprtDef.end()) + Error(ecNAME_CONFLICT, -1, a_strName); + + if (pFunMap != &m_InfixOprtDef && pFunMap != &m_OprtDef && m_InfixOprtDef.find(a_strName) != m_InfixOprtDef.end()) + Error(ecNAME_CONFLICT, -1, a_strName); + + if (pFunMap != &m_InfixOprtDef && pFunMap != &m_OprtDef && m_OprtDef.find(a_strName) != m_OprtDef.end()) + Error(ecNAME_CONFLICT, -1, a_strName); + + CheckOprt(a_strName, a_Callback, a_szCharSet); + a_Storage[a_strName] = a_Callback; + ReInit(); + } + + //--------------------------------------------------------------------------- + /** \brief Check if a name contains invalid characters. + + \throw ParserException if the name contains invalid characters. + */ + void ParserBase::CheckOprt(const string_type& a_sName, + const ParserCallback& a_Callback, + const string_type& a_szCharSet) const + { + if (!a_sName.length() || + (a_sName.find_first_not_of(a_szCharSet) != string_type::npos) || + (a_sName[0] >= '0' && a_sName[0] <= '9')) + { + switch (a_Callback.GetCode()) + { + case cmOPRT_POSTFIX: Error(ecINVALID_POSTFIX_IDENT, -1, a_sName); break; + case cmOPRT_INFIX: Error(ecINVALID_INFIX_IDENT, -1, a_sName); break; + default: Error(ecINVALID_NAME, -1, a_sName); + } + } + } + + + /** \brief Check if a name contains invalid characters. + \throw ParserException if the name contains invalid characters. + */ + void ParserBase::CheckName(const string_type& a_sName, const string_type& a_szCharSet) const + { + if (!a_sName.length() || + (a_sName.find_first_not_of(a_szCharSet) != string_type::npos) || + (a_sName[0] >= '0' && a_sName[0] <= '9')) + { + Error(ecINVALID_NAME); + } + } + + /** \brief Set the formula. + \param a_strFormula Formula as string_type + \throw ParserException in case of syntax errors. + + Triggers first time calculation thus the creation of the bytecode and + scanning of used variables. + */ + void ParserBase::SetExpr(const string_type& a_sExpr) + { + // Check locale compatibility + if (m_pTokenReader->GetArgSep() == std::use_facet >(s_locale).decimal_point()) + Error(ecLOCALE); + + // Check maximum allowed expression length. An arbitrary value small enough so i can debug expressions sent to me + if (a_sExpr.length() >= MaxLenExpression) + Error(ecEXPRESSION_TOO_LONG, 0, a_sExpr); + + m_pTokenReader->SetFormula(a_sExpr + _T(" ")); + ReInit(); + } + + //--------------------------------------------------------------------------- + /** \brief Get the default symbols used for the built in operators. + \sa c_DefaultOprt + */ + const char_type** ParserBase::GetOprtDef() const + { + return (const char_type**)(&c_DefaultOprt[0]); + } + + //--------------------------------------------------------------------------- + /** \brief Define the set of valid characters to be used in names of + functions, variables, constants. + */ + void ParserBase::DefineNameChars(const char_type* a_szCharset) + { + m_sNameChars = a_szCharset; + } + + //--------------------------------------------------------------------------- + /** \brief Define the set of valid characters to be used in names of + binary operators and postfix operators. + */ + void ParserBase::DefineOprtChars(const char_type* a_szCharset) + { + m_sOprtChars = a_szCharset; + } + + //--------------------------------------------------------------------------- + /** \brief Define the set of valid characters to be used in names of + infix operators. + */ + void ParserBase::DefineInfixOprtChars(const char_type* a_szCharset) + { + m_sInfixOprtChars = a_szCharset; + } + + //--------------------------------------------------------------------------- + /** \brief Virtual function that defines the characters allowed in name identifiers. + \sa #ValidOprtChars, #ValidPrefixOprtChars + */ + const char_type* ParserBase::ValidNameChars() const + { + MUP_ASSERT(m_sNameChars.size()); + return m_sNameChars.c_str(); + } + + //--------------------------------------------------------------------------- + /** \brief Virtual function that defines the characters allowed in operator definitions. + \sa #ValidNameChars, #ValidPrefixOprtChars + */ + const char_type* ParserBase::ValidOprtChars() const + { + MUP_ASSERT(m_sOprtChars.size()); + return m_sOprtChars.c_str(); + } + + //--------------------------------------------------------------------------- + /** \brief Virtual function that defines the characters allowed in infix operator definitions. + \sa #ValidNameChars, #ValidOprtChars + */ + const char_type* ParserBase::ValidInfixOprtChars() const + { + MUP_ASSERT(m_sInfixOprtChars.size()); + return m_sInfixOprtChars.c_str(); + } + + //--------------------------------------------------------------------------- + /** \brief Add a user defined operator. + \post Will reset the Parser to string parsing mode. + */ + void ParserBase::DefinePostfixOprt(const string_type& a_sName, fun_type1 a_pFun, bool a_bAllowOpt) + { + if (a_sName.length() > MaxLenIdentifier) + Error(ecIDENTIFIER_TOO_LONG); + + AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, prPOSTFIX, cmOPRT_POSTFIX), m_PostOprtDef, ValidOprtChars()); + } + + //--------------------------------------------------------------------------- + /** \brief Initialize user defined functions. + + Calls the virtual functions InitFun(), InitConst() and InitOprt(). + */ + void ParserBase::Init() + { + InitCharSets(); + InitFun(); + InitConst(); + InitOprt(); + } + + //--------------------------------------------------------------------------- + /** \brief Add a user defined operator. + \post Will reset the Parser to string parsing mode. + \param [in] a_sName operator Identifier + \param [in] a_pFun Operator callback function + \param [in] a_iPrec Operator Precedence (default=prSIGN) + \param [in] a_bAllowOpt True if operator is volatile (default=false) + \sa EPrec + */ + void ParserBase::DefineInfixOprt(const string_type& a_sName, fun_type1 a_pFun, int a_iPrec, bool a_bAllowOpt) + { + if (a_sName.length() > MaxLenIdentifier) + Error(ecIDENTIFIER_TOO_LONG); + + AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, cmOPRT_INFIX), m_InfixOprtDef, ValidInfixOprtChars()); + } + + + //--------------------------------------------------------------------------- + /** \brief Define a binary operator. + \param [in] a_sName The identifier of the operator. + \param [in] a_pFun Pointer to the callback function. + \param [in] a_iPrec Precedence of the operator. + \param [in] a_eAssociativity The associativity of the operator. + \param [in] a_bAllowOpt If this is true the operator may be optimized away. + + Adds a new Binary operator the the parser instance. + */ + void ParserBase::DefineOprt(const string_type& a_sName, fun_type2 a_pFun, unsigned a_iPrec, EOprtAssociativity a_eAssociativity, bool a_bAllowOpt) + { + if (a_sName.length() > MaxLenIdentifier) + Error(ecIDENTIFIER_TOO_LONG); + + // Check for conflicts with built in operator names + for (int i = 0; m_bBuiltInOp && i < cmENDIF; ++i) + { + if (a_sName == string_type(c_DefaultOprt[i])) + { + Error(ecBUILTIN_OVERLOAD, -1, a_sName); + } + } + + AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, a_eAssociativity), m_OprtDef, ValidOprtChars()); + } + + //--------------------------------------------------------------------------- + /** \brief Define a new string constant. + \param [in] a_strName The name of the constant. + \param [in] a_strVal the value of the constant. + */ + void ParserBase::DefineStrConst(const string_type& a_strName, const string_type& a_strVal) + { + // Test if a constant with that names already exists + if (m_StrVarDef.find(a_strName) != m_StrVarDef.end()) + Error(ecNAME_CONFLICT); + + CheckName(a_strName, ValidNameChars()); + + m_vStringVarBuf.push_back(a_strVal); // Store variable string in internal buffer + m_StrVarDef[a_strName] = m_vStringVarBuf.size() - 1; // bind buffer index to variable name + + ReInit(); + } + + //--------------------------------------------------------------------------- + /** \brief Add a user defined variable. + \param [in] a_sName the variable name + \param [in] a_pVar A pointer to the variable value. + \post Will reset the Parser to string parsing mode. + \throw ParserException in case the name contains invalid signs or a_pVar is nullptr. + */ + void ParserBase::DefineVar(const string_type& a_sName, value_type* a_pVar) + { + if (a_pVar == 0) + Error(ecINVALID_VAR_PTR); + + if (a_sName.length() > MaxLenIdentifier) + Error(ecIDENTIFIER_TOO_LONG); + + // Test if a constant with that names already exists + if (m_ConstDef.find(a_sName) != m_ConstDef.end()) + Error(ecNAME_CONFLICT); + + CheckName(a_sName, ValidNameChars()); + m_VarDef[a_sName] = a_pVar; + ReInit(); + } + + //--------------------------------------------------------------------------- + /** \brief Add a user defined constant. + \param [in] a_sName The name of the constant. + \param [in] a_fVal the value of the constant. + \post Will reset the Parser to string parsing mode. + \throw ParserException in case the name contains invalid signs. + */ + void ParserBase::DefineConst(const string_type& a_sName, value_type a_fVal) + { + if (a_sName.length() > MaxLenIdentifier) + Error(ecIDENTIFIER_TOO_LONG); + + CheckName(a_sName, ValidNameChars()); + m_ConstDef[a_sName] = a_fVal; + ReInit(); + } + + //--------------------------------------------------------------------------- + /** \brief Get operator priority. + \throw ParserException if a_Oprt is no operator code + */ + int ParserBase::GetOprtPrecedence(const token_type& a_Tok) const + { + switch (a_Tok.GetCode()) + { + // built in operators + case cmEND: return -5; + case cmARG_SEP: return -4; + case cmASSIGN: return -1; + case cmELSE: + case cmIF: return 0; + case cmLAND: return prLAND; + case cmLOR: return prLOR; + case cmLT: + case cmGT: + case cmLE: + case cmGE: + case cmNEQ: + case cmEQ: return prCMP; + case cmADD: + case cmSUB: return prADD_SUB; + case cmMUL: + case cmDIV: return prMUL_DIV; + case cmPOW: return prPOW; + + // user defined binary operators + case cmOPRT_INFIX: + case cmOPRT_BIN: return a_Tok.GetPri(); + default: + throw exception_type(ecINTERNAL_ERROR, 5, _T("")); + } + } + + //--------------------------------------------------------------------------- + /** \brief Get operator priority. + \throw ParserException if a_Oprt is no operator code + */ + EOprtAssociativity ParserBase::GetOprtAssociativity(const token_type& a_Tok) const + { + switch (a_Tok.GetCode()) + { + case cmASSIGN: + case cmLAND: + case cmLOR: + case cmLT: + case cmGT: + case cmLE: + case cmGE: + case cmNEQ: + case cmEQ: + case cmADD: + case cmSUB: + case cmMUL: + case cmDIV: return oaLEFT; + case cmPOW: return oaRIGHT; + case cmOPRT_BIN: return a_Tok.GetAssociativity(); + default: return oaNONE; + } + } + + //--------------------------------------------------------------------------- + /** \brief Return a map containing the used variables only. */ + const varmap_type& ParserBase::GetUsedVar() const + { + try + { + m_pTokenReader->IgnoreUndefVar(true); + CreateRPN(); // try to create bytecode, but don't use it for any further calculations since it + // may contain references to nonexisting variables. + m_pParseFormula = &ParserBase::ParseString; + m_pTokenReader->IgnoreUndefVar(false); + } + catch (exception_type& /*e*/) + { + // Make sure to stay in string parse mode, don't call ReInit() + // because it deletes the array with the used variables + m_pParseFormula = &ParserBase::ParseString; + m_pTokenReader->IgnoreUndefVar(false); + throw; + } + + return m_pTokenReader->GetUsedVar(); + } + + //--------------------------------------------------------------------------- + /** \brief Return a map containing the used variables only. */ + const varmap_type& ParserBase::GetVar() const + { + return m_VarDef; + } + + //--------------------------------------------------------------------------- + /** \brief Return a map containing all parser constants. */ + const valmap_type& ParserBase::GetConst() const + { + return m_ConstDef; + } + + //--------------------------------------------------------------------------- + /** \brief Return prototypes of all parser functions. + \return #m_FunDef + \sa FunProt + \throw nothrow + + The return type is a map of the public type #funmap_type containing the prototype + definitions for all numerical parser functions. String functions are not part of + this map. The Prototype definition is encapsulated in objects of the class FunProt + one per parser function each associated with function names via a map construct. + */ + const funmap_type& ParserBase::GetFunDef() const + { + return m_FunDef; + } + + //--------------------------------------------------------------------------- + /** \brief Retrieve the formula. */ + const string_type& ParserBase::GetExpr() const + { + return m_pTokenReader->GetExpr(); + } + + //--------------------------------------------------------------------------- + /** \brief Execute a function that takes a single string argument. + \param a_FunTok Function token. + \throw exception_type If the function token is not a string function + */ + ParserBase::token_type ParserBase::ApplyStrFunc( + const token_type& a_FunTok, + const std::vector& a_vArg) const + { + if (a_vArg.back().GetCode() != cmSTRING) + Error(ecSTRING_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString()); + + token_type valTok; + generic_callable_type pFunc = a_FunTok.GetFuncAddr(); + MUP_ASSERT(pFunc); + + try + { + // Check function arguments; write dummy value into valtok to represent the result + switch (a_FunTok.GetArgCount()) + { + case 0: valTok.SetVal(1); a_vArg[0].GetAsString(); break; + case 1: valTok.SetVal(1); a_vArg[1].GetAsString(); a_vArg[0].GetVal(); break; + case 2: valTok.SetVal(1); a_vArg[2].GetAsString(); a_vArg[1].GetVal(); a_vArg[0].GetVal(); break; + case 3: valTok.SetVal(1); a_vArg[3].GetAsString(); a_vArg[2].GetVal(); a_vArg[1].GetVal(); a_vArg[0].GetVal(); break; + case 4: valTok.SetVal(1); a_vArg[4].GetAsString(); a_vArg[3].GetVal(); a_vArg[2].GetVal(); a_vArg[1].GetVal(); a_vArg[0].GetVal(); break; + case 5: valTok.SetVal(1); a_vArg[5].GetAsString(); a_vArg[4].GetVal(); a_vArg[3].GetVal(); a_vArg[2].GetVal(); a_vArg[1].GetVal(); a_vArg[0].GetVal(); break; + default: Error(ecINTERNAL_ERROR); + } + } + catch (ParserError&) + { + Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString()); + } + + // string functions won't be optimized + m_vRPN.AddStrFun(pFunc, a_FunTok.GetArgCount(), a_vArg.back().GetIdx()); + + // Push dummy value representing the function result to the stack + return valTok; + } + + //--------------------------------------------------------------------------- + /** \brief Apply a function token. + \param iArgCount Number of Arguments actually gathered used only for multiarg functions. + \post The result is pushed to the value stack + \post The function token is removed from the stack + \throw exception_type if Argument count does not match function requirements. + */ + void ParserBase::ApplyFunc(std::stack& a_stOpt, std::stack& a_stVal, int a_iArgCount) const + { + MUP_ASSERT(m_pTokenReader.get()); + + // Operator stack empty or does not contain tokens with callback functions + if (a_stOpt.empty() || a_stOpt.top().GetFuncAddr() == 0) + return; + + token_type funTok = a_stOpt.top(); + a_stOpt.pop(); + MUP_ASSERT(funTok.GetFuncAddr() != nullptr); + + // Binary operators must rely on their internal operator number + // since counting of operators relies on commas for function arguments + // binary operators do not have commas in their expression + int iArgCount = (funTok.GetCode() == cmOPRT_BIN) ? funTok.GetArgCount() : a_iArgCount; + + // determine how many parameters the function needs. To remember iArgCount includes the + // string parameter whilst GetArgCount() counts only numeric parameters. + int iArgRequired = funTok.GetArgCount() + ((funTok.GetType() == tpSTR) ? 1 : 0); + + // That's the number of numerical parameters + int iArgNumerical = iArgCount - ((funTok.GetType() == tpSTR) ? 1 : 0); + + if (funTok.GetCode() == cmFUNC_STR && iArgCount - iArgNumerical > 1) + Error(ecINTERNAL_ERROR); + + if (funTok.GetArgCount() >= 0 && iArgCount > iArgRequired) + Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos() - 1, funTok.GetAsString()); + + if (funTok.GetCode() != cmOPRT_BIN && iArgCount < iArgRequired) + Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos() - 1, funTok.GetAsString()); + + if (funTok.GetCode() == cmFUNC_STR && iArgCount > iArgRequired) + Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos() - 1, funTok.GetAsString()); + + // Collect the numeric function arguments from the value stack and store them + // in a vector + std::vector stArg; + for (int i = 0; i < iArgNumerical; ++i) + { + if (a_stVal.empty()) + Error(ecINTERNAL_ERROR, m_pTokenReader->GetPos(), funTok.GetAsString()); + + stArg.push_back(a_stVal.top()); + a_stVal.pop(); + + if (stArg.back().GetType() == tpSTR && funTok.GetType() != tpSTR) + Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString()); + } + + switch (funTok.GetCode()) + { + case cmFUNC_STR: + if (a_stVal.empty()) + Error(ecINTERNAL_ERROR, m_pTokenReader->GetPos(), funTok.GetAsString()); + + stArg.push_back(a_stVal.top()); + a_stVal.pop(); + + if (stArg.back().GetType() == tpSTR && funTok.GetType() != tpSTR) + Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString()); + + ApplyStrFunc(funTok, stArg); + break; + + case cmFUNC_BULK: + m_vRPN.AddBulkFun(funTok.GetFuncAddr(), (int)stArg.size()); + break; + + case cmOPRT_BIN: + case cmOPRT_POSTFIX: + case cmOPRT_INFIX: + case cmFUNC: + if (funTok.GetArgCount() == -1 && iArgCount == 0) + Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos(), funTok.GetAsString()); + + m_vRPN.AddFun(funTok.GetFuncAddr(), (funTok.GetArgCount() == -1) ? -iArgNumerical : iArgNumerical, funTok.IsOptimizable()); + break; + default: + break; + } + + // Push dummy value representing the function result to the stack + token_type token; + token.SetVal(1); + a_stVal.push(token); + } + + //--------------------------------------------------------------------------- + void ParserBase::ApplyIfElse(std::stack& a_stOpt, std::stack& a_stVal) const + { + // Check if there is an if Else clause to be calculated + while (a_stOpt.size() && a_stOpt.top().GetCode() == cmELSE) + { + MUP_ASSERT(!a_stOpt.empty()) + token_type opElse = a_stOpt.top(); + a_stOpt.pop(); + + // Take the value associated with the else branch from the value stack + MUP_ASSERT(!a_stVal.empty()); + token_type vVal2 = a_stVal.top(); + if (vVal2.GetType() != tpDBL) + Error(ecUNEXPECTED_STR, m_pTokenReader->GetPos()); + + a_stVal.pop(); + + // it then else is a ternary operator Pop all three values from the value s + // tack and just return the right value + MUP_ASSERT(!a_stVal.empty()); + token_type vVal1 = a_stVal.top(); + if (vVal1.GetType() != tpDBL) + Error(ecUNEXPECTED_STR, m_pTokenReader->GetPos()); + + a_stVal.pop(); + + MUP_ASSERT(!a_stVal.empty()); + token_type vExpr = a_stVal.top(); + a_stVal.pop(); + + a_stVal.push((vExpr.GetVal() != 0) ? vVal1 : vVal2); + + token_type opIf = a_stOpt.top(); + a_stOpt.pop(); + + MUP_ASSERT(opElse.GetCode() == cmELSE); + + if (opIf.GetCode() != cmIF) + Error(ecMISPLACED_COLON, m_pTokenReader->GetPos()); + + m_vRPN.AddIfElse(cmENDIF); + } // while pending if-else-clause found + } + + //--------------------------------------------------------------------------- + /** \brief Performs the necessary steps to write code for + the execution of binary operators into the bytecode. + */ + void ParserBase::ApplyBinOprt(std::stack& a_stOpt, std::stack& a_stVal) const + { + // is it a user defined binary operator? + if (a_stOpt.top().GetCode() == cmOPRT_BIN) + { + ApplyFunc(a_stOpt, a_stVal, 2); + } + else + { + if (a_stVal.size() < 2) + Error(ecINTERNAL_ERROR, m_pTokenReader->GetPos(), _T("ApplyBinOprt: not enough values in value stack!")); + + token_type valTok1 = a_stVal.top(); + a_stVal.pop(); + + token_type valTok2 = a_stVal.top(); + a_stVal.pop(); + + token_type optTok = a_stOpt.top(); + a_stOpt.pop(); + + token_type resTok; + + if (valTok1.GetType() != valTok2.GetType() || + (valTok1.GetType() == tpSTR && valTok2.GetType() == tpSTR)) + Error(ecOPRT_TYPE_CONFLICT, m_pTokenReader->GetPos(), optTok.GetAsString()); + + if (optTok.GetCode() == cmASSIGN) + { + if (valTok2.GetCode() != cmVAR) + Error(ecUNEXPECTED_OPERATOR, -1, _T("=")); + + m_vRPN.AddAssignOp(valTok2.GetVar()); + } + else + m_vRPN.AddOp(optTok.GetCode()); + + resTok.SetVal(1); + a_stVal.push(resTok); + } + } + + //--------------------------------------------------------------------------- + /** \brief Apply a binary operator. + \param a_stOpt The operator stack + \param a_stVal The value stack + */ + void ParserBase::ApplyRemainingOprt(std::stack& stOpt, std::stack& stVal) const + { + while (stOpt.size() && + stOpt.top().GetCode() != cmBO && + stOpt.top().GetCode() != cmIF) + { + token_type tok = stOpt.top(); + switch (tok.GetCode()) + { + case cmOPRT_INFIX: + case cmOPRT_BIN: + case cmLE: + case cmGE: + case cmNEQ: + case cmEQ: + case cmLT: + case cmGT: + case cmADD: + case cmSUB: + case cmMUL: + case cmDIV: + case cmPOW: + case cmLAND: + case cmLOR: + case cmASSIGN: + if (stOpt.top().GetCode() == cmOPRT_INFIX) + ApplyFunc(stOpt, stVal, 1); + else + ApplyBinOprt(stOpt, stVal); + break; + + case cmELSE: + ApplyIfElse(stOpt, stVal); + break; + + default: + Error(ecINTERNAL_ERROR); + } + } + } + + //--------------------------------------------------------------------------- + /** \brief Parse the command code. + \sa ParseString(...) + + Command code contains precalculated stack positions of the values and the + associated operators. The Stack is filled beginning from index one the + value at index zero is not used at all. + */ + value_type ParserBase::ParseCmdCode() const + { + return ParseCmdCodeBulk(0, 0); + } + + value_type ParserBase::ParseCmdCodeShort() const + { + const SToken *const tok = m_vRPN.GetBase(); + value_type buf; + + switch (tok->Cmd) + { + case cmVAL: + return tok->Val.data2; + + case cmVAR: + return *tok->Val.ptr; + + case cmVARMUL: + return *tok->Val.ptr * tok->Val.data + tok->Val.data2; + + case cmVARPOW2: + buf = *(tok->Val.ptr); + return buf * buf; + + case cmVARPOW3: + buf = *(tok->Val.ptr); + return buf * buf * buf; + + case cmVARPOW4: + buf = *(tok->Val.ptr); + return buf * buf * buf * buf; + + // numerical function without any argument + case cmFUNC: + return tok->Fun.cb.call_fun<0>(); + + // String function without a numerical argument + case cmFUNC_STR: + return tok->Fun.cb.call_strfun<1>(m_vStringBuf[0].c_str()); + + default: + throw ParserError(ecINTERNAL_ERROR); + } + } + + //--------------------------------------------------------------------------- + /** \brief Evaluate the RPN. + \param nOffset The offset added to variable addresses (for bulk mode) + \param nThreadID OpenMP Thread id of the calling thread + */ + value_type ParserBase::ParseCmdCodeBulk(int nOffset, int nThreadID) const + { + assert(nThreadID <= s_MaxNumOpenMPThreads); + + // Note: The check for nOffset==0 and nThreadID here is not necessary but + // brings a minor performance gain when not in bulk mode. + value_type *stack = ((nOffset == 0) && (nThreadID == 0)) ? &m_vStackBuffer[0] : &m_vStackBuffer[nThreadID * (m_vStackBuffer.size() / s_MaxNumOpenMPThreads)]; + value_type buf; + int sidx(0); + for (const SToken* pTok = m_vRPN.GetBase(); pTok->Cmd != cmEND; ++pTok) + { + switch (pTok->Cmd) + { + // built in binary operators + case cmLE: --sidx; stack[sidx] = stack[sidx] <= stack[sidx + 1]; continue; + case cmGE: --sidx; stack[sidx] = stack[sidx] >= stack[sidx + 1]; continue; + case cmNEQ: --sidx; stack[sidx] = stack[sidx] != stack[sidx + 1]; continue; + case cmEQ: --sidx; stack[sidx] = stack[sidx] == stack[sidx + 1]; continue; + case cmLT: --sidx; stack[sidx] = stack[sidx] < stack[sidx + 1]; continue; + case cmGT: --sidx; stack[sidx] = stack[sidx] > stack[sidx + 1]; continue; + case cmADD: --sidx; stack[sidx] += stack[1 + sidx]; continue; + case cmSUB: --sidx; stack[sidx] -= stack[1 + sidx]; continue; + case cmMUL: --sidx; stack[sidx] *= stack[1 + sidx]; continue; + case cmDIV: --sidx; + stack[sidx] /= stack[1 + sidx]; + continue; + + case cmPOW: + --sidx; stack[sidx] = MathImpl::Pow(stack[sidx], stack[1 + sidx]); + continue; + + case cmLAND: --sidx; stack[sidx] = stack[sidx] && stack[sidx + 1]; continue; + case cmLOR: --sidx; stack[sidx] = stack[sidx] || stack[sidx + 1]; continue; + + case cmASSIGN: + // Bugfix for Bulkmode: + // for details see: + // https://groups.google.com/forum/embed/?place=forum/muparser-dev&showsearch=true&showpopout=true&showtabs=false&parenturl=http://muparser.beltoforion.de/mup_forum.html&afterlogin&pli=1#!topic/muparser-dev/szgatgoHTws + --sidx; + stack[sidx] = *(pTok->Oprt.ptr + nOffset) = stack[sidx + 1]; + continue; + // original code: + //--sidx; Stack[sidx] = *pTok->Oprt.ptr = Stack[sidx+1]; continue; + + case cmIF: + if (stack[sidx--] == 0) + { + MUP_ASSERT(sidx >= 0); + pTok += pTok->Oprt.offset; + } + continue; + + case cmELSE: + pTok += pTok->Oprt.offset; + continue; + + case cmENDIF: + continue; + + // value and variable tokens + case cmVAR: stack[++sidx] = *(pTok->Val.ptr + nOffset); continue; + case cmVAL: stack[++sidx] = pTok->Val.data2; continue; + + case cmVARPOW2: buf = *(pTok->Val.ptr + nOffset); + stack[++sidx] = buf * buf; + continue; + + case cmVARPOW3: buf = *(pTok->Val.ptr + nOffset); + stack[++sidx] = buf * buf * buf; + continue; + + case cmVARPOW4: buf = *(pTok->Val.ptr + nOffset); + stack[++sidx] = buf * buf * buf * buf; + continue; + + case cmVARMUL: + stack[++sidx] = *(pTok->Val.ptr + nOffset) * pTok->Val.data + pTok->Val.data2; + continue; + + // Next is treatment of numeric functions + case cmFUNC: + { + int iArgCount = pTok->Fun.argc; + + // switch according to argument count + switch (iArgCount) + { + case 0: sidx += 1; stack[sidx] = pTok->Fun.cb.call_fun<0 >(); continue; + case 1: stack[sidx] = pTok->Fun.cb.call_fun<1 >(stack[sidx]); continue; + case 2: sidx -= 1; stack[sidx] = pTok->Fun.cb.call_fun<2 >(stack[sidx], stack[sidx + 1]); continue; + case 3: sidx -= 2; stack[sidx] = pTok->Fun.cb.call_fun<3 >(stack[sidx], stack[sidx + 1], stack[sidx + 2]); continue; + case 4: sidx -= 3; stack[sidx] = pTok->Fun.cb.call_fun<4 >(stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3]); continue; + case 5: sidx -= 4; stack[sidx] = pTok->Fun.cb.call_fun<5 >(stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4]); continue; + case 6: sidx -= 5; stack[sidx] = pTok->Fun.cb.call_fun<6 >(stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4], stack[sidx + 5]); continue; + case 7: sidx -= 6; stack[sidx] = pTok->Fun.cb.call_fun<7 >(stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4], stack[sidx + 5], stack[sidx + 6]); continue; + case 8: sidx -= 7; stack[sidx] = pTok->Fun.cb.call_fun<8 >(stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4], stack[sidx + 5], stack[sidx + 6], stack[sidx + 7]); continue; + case 9: sidx -= 8; stack[sidx] = pTok->Fun.cb.call_fun<9 >(stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4], stack[sidx + 5], stack[sidx + 6], stack[sidx + 7], stack[sidx + 8]); continue; + case 10:sidx -= 9; stack[sidx] = pTok->Fun.cb.call_fun<10>(stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4], stack[sidx + 5], stack[sidx + 6], stack[sidx + 7], stack[sidx + 8], stack[sidx + 9]); continue; + default: + // function with variable arguments store the number as a negative value + if (iArgCount > 0) + Error(ecINTERNAL_ERROR, -1); + + sidx -= -iArgCount - 1; + + // From oss-fuzz. Happend when Multiarg functions and if-then-else are used incorrectly. + // Expressions where this was observed: + // sum(0?1,2,3,4,5:6) -> fixed + // avg(0>3?4:(""),0^3?4:("")) + // + // The final result normally lieas at position 1. If sixd is smaller there is something wrong. + if (sidx <= 0) + Error(ecINTERNAL_ERROR, -1); + // + + stack[sidx] = pTok->Fun.cb.call_multfun(&stack[sidx], -iArgCount); + continue; + } + } + + // Next is treatment of string functions + case cmFUNC_STR: + { + sidx -= pTok->Fun.argc - 1; + + // The index of the string argument in the string table + int iIdxStack = pTok->Fun.idx; + if (iIdxStack < 0 || iIdxStack >= (int)m_vStringBuf.size()) + Error(ecINTERNAL_ERROR, m_pTokenReader->GetPos()); + + switch (pTok->Fun.argc) // switch according to argument count + { + case 0: stack[sidx] = pTok->Fun.cb.call_strfun<1>(m_vStringBuf[iIdxStack].c_str()); continue; + case 1: stack[sidx] = pTok->Fun.cb.call_strfun<2>(m_vStringBuf[iIdxStack].c_str(), stack[sidx]); continue; + case 2: stack[sidx] = pTok->Fun.cb.call_strfun<3>(m_vStringBuf[iIdxStack].c_str(), stack[sidx], stack[sidx + 1]); continue; + case 3: stack[sidx] = pTok->Fun.cb.call_strfun<4>(m_vStringBuf[iIdxStack].c_str(), stack[sidx], stack[sidx + 1], stack[sidx + 2]); continue; + case 4: stack[sidx] = pTok->Fun.cb.call_strfun<5>(m_vStringBuf[iIdxStack].c_str(), stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3]); continue; + case 5: stack[sidx] = pTok->Fun.cb.call_strfun<6>(m_vStringBuf[iIdxStack].c_str(), stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4]); continue; + } + + continue; + } + + case cmFUNC_BULK: + { + int iArgCount = pTok->Fun.argc; + + // switch according to argument count + switch (iArgCount) + { + case 0: sidx += 1; stack[sidx] = pTok->Fun.cb.call_bulkfun<0 >(nOffset, nThreadID); continue; + case 1: stack[sidx] = pTok->Fun.cb.call_bulkfun<1 >(nOffset, nThreadID, stack[sidx]); continue; + case 2: sidx -= 1; stack[sidx] = pTok->Fun.cb.call_bulkfun<2 >(nOffset, nThreadID, stack[sidx], stack[sidx + 1]); continue; + case 3: sidx -= 2; stack[sidx] = pTok->Fun.cb.call_bulkfun<3 >(nOffset, nThreadID, stack[sidx], stack[sidx + 1], stack[sidx + 2]); continue; + case 4: sidx -= 3; stack[sidx] = pTok->Fun.cb.call_bulkfun<4 >(nOffset, nThreadID, stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3]); continue; + case 5: sidx -= 4; stack[sidx] = pTok->Fun.cb.call_bulkfun<5 >(nOffset, nThreadID, stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4]); continue; + case 6: sidx -= 5; stack[sidx] = pTok->Fun.cb.call_bulkfun<6 >(nOffset, nThreadID, stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4], stack[sidx + 5]); continue; + case 7: sidx -= 6; stack[sidx] = pTok->Fun.cb.call_bulkfun<7 >(nOffset, nThreadID, stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4], stack[sidx + 5], stack[sidx + 6]); continue; + case 8: sidx -= 7; stack[sidx] = pTok->Fun.cb.call_bulkfun<8 >(nOffset, nThreadID, stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4], stack[sidx + 5], stack[sidx + 6], stack[sidx + 7]); continue; + case 9: sidx -= 8; stack[sidx] = pTok->Fun.cb.call_bulkfun<9 >(nOffset, nThreadID, stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4], stack[sidx + 5], stack[sidx + 6], stack[sidx + 7], stack[sidx + 8]); continue; + case 10:sidx -= 9; stack[sidx] = pTok->Fun.cb.call_bulkfun<10>(nOffset, nThreadID, stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4], stack[sidx + 5], stack[sidx + 6], stack[sidx + 7], stack[sidx + 8], stack[sidx + 9]); continue; + default: + throw exception_type(ecINTERNAL_ERROR, 2, _T("")); + } + } + + default: + throw exception_type(ecINTERNAL_ERROR, 3, _T("")); + } // switch CmdCode + } // for all bytecode tokens + + return stack[m_nFinalResultIdx]; + } + + //--------------------------------------------------------------------------- + void ParserBase::CreateRPN() const + { + if (!m_pTokenReader->GetExpr().length()) + Error(ecUNEXPECTED_EOF, 0); + + std::stack stOpt, stVal; + std::stack stArgCount; + token_type opta, opt; // for storing operators + token_type val, tval; // for storing value + int ifElseCounter = 0; + + ReInit(); + + // The outermost counter counts the number of separated items + // such as in "a=10,b=20,c=c+a" + stArgCount.push(1); + + for (;;) + { + opt = m_pTokenReader->ReadNextToken(); + + switch (opt.GetCode()) + { + // + // Next three are different kind of value entries + // + case cmSTRING: + if (stOpt.empty()) + Error(ecSTR_RESULT, m_pTokenReader->GetPos(), opt.GetAsString()); + + opt.SetIdx((int)m_vStringBuf.size()); // Assign buffer index to token + stVal.push(opt); + m_vStringBuf.push_back(opt.GetAsString()); // Store string in internal buffer + break; + + case cmVAR: + stVal.push(opt); + m_vRPN.AddVar(static_cast(opt.GetVar())); + break; + + case cmVAL: + stVal.push(opt); + m_vRPN.AddVal(opt.GetVal()); + break; + + case cmELSE: + if (stArgCount.empty()) + Error(ecMISPLACED_COLON, m_pTokenReader->GetPos()); + + if (stArgCount.top() > 1) + Error(ecUNEXPECTED_ARG_SEP, m_pTokenReader->GetPos()); + + stArgCount.pop(); + + ifElseCounter--; + if (ifElseCounter < 0) + Error(ecMISPLACED_COLON, m_pTokenReader->GetPos()); + + ApplyRemainingOprt(stOpt, stVal); + m_vRPN.AddIfElse(cmELSE); + stOpt.push(opt); + break; + + case cmARG_SEP: + if (!stOpt.empty() && stOpt.top().GetCode() == cmIF) + Error(ecUNEXPECTED_ARG_SEP, m_pTokenReader->GetPos()); + + if (stArgCount.empty()) + Error(ecUNEXPECTED_ARG_SEP, m_pTokenReader->GetPos()); + + ++stArgCount.top(); + // Falls through. + // intentional (no break!) + + case cmEND: + ApplyRemainingOprt(stOpt, stVal); + break; + + case cmBC: + { + // The argument count for parameterless functions is zero + // by default an opening bracket sets parameter count to 1 + // in preparation of arguments to come. If the last token + // was an opening bracket we know better... + if (opta.GetCode() == cmBO) + --stArgCount.top(); + + ApplyRemainingOprt(stOpt, stVal); + + // Check if the bracket content has been evaluated completely + if (stOpt.size() && stOpt.top().GetCode() == cmBO) + { + // if opt is ")" and opta is "(" the bracket has been evaluated, now its time to check + // if there is either a function or a sign pending + // neither the opening nor the closing bracket will be pushed back to + // the operator stack + // Check if a function is standing in front of the opening bracket, + // if yes evaluate it afterwards check for infix operators + MUP_ASSERT(stArgCount.size()); + int iArgCount = stArgCount.top(); + stArgCount.pop(); + + stOpt.pop(); // Take opening bracket from stack + + if (iArgCount > 1 && (stOpt.size() == 0 || + (stOpt.top().GetCode() != cmFUNC && + stOpt.top().GetCode() != cmFUNC_BULK && + stOpt.top().GetCode() != cmFUNC_STR))) + Error(ecUNEXPECTED_ARG, m_pTokenReader->GetPos()); + + // The opening bracket was popped from the stack now check if there + // was a function before this bracket + if (stOpt.size() && + stOpt.top().GetCode() != cmOPRT_INFIX && + stOpt.top().GetCode() != cmOPRT_BIN && + stOpt.top().GetFuncAddr() != 0) + { + ApplyFunc(stOpt, stVal, iArgCount); + } + } + } // if bracket content is evaluated + break; + + // + // Next are the binary operator entries + // + case cmIF: + ifElseCounter++; + stArgCount.push(1); + // Falls through. + // intentional (no break!) + + case cmLAND: + case cmLOR: + case cmLT: + case cmGT: + case cmLE: + case cmGE: + case cmNEQ: + case cmEQ: + case cmADD: + case cmSUB: + case cmMUL: + case cmDIV: + case cmPOW: + case cmASSIGN: + case cmOPRT_BIN: + + // A binary operator (user defined or built in) has been found. + while ( + stOpt.size() && + stOpt.top().GetCode() != cmBO && + stOpt.top().GetCode() != cmELSE && + stOpt.top().GetCode() != cmIF) + { + int nPrec1 = GetOprtPrecedence(stOpt.top()), + nPrec2 = GetOprtPrecedence(opt); + + if (stOpt.top().GetCode() == opt.GetCode()) + { + + // Deal with operator associativity + EOprtAssociativity eOprtAsct = GetOprtAssociativity(opt); + if ((eOprtAsct == oaRIGHT && (nPrec1 <= nPrec2)) || + (eOprtAsct == oaLEFT && (nPrec1 < nPrec2))) + { + break; + } + } + else if (nPrec1 < nPrec2) + { + // In case the operators are not equal the precedence decides alone... + break; + } + + if (stOpt.top().GetCode() == cmOPRT_INFIX) + ApplyFunc(stOpt, stVal, 1); + else + ApplyBinOprt(stOpt, stVal); + } // while ( ... ) + + if (opt.GetCode() == cmIF) + m_vRPN.AddIfElse(opt.GetCode()); + + // The operator can't be evaluated right now, push back to the operator stack + stOpt.push(opt); + break; + + // + // Last section contains functions and operators implicitly mapped to functions + // + case cmBO: + stArgCount.push(1); + stOpt.push(opt); + break; + + case cmOPRT_INFIX: + case cmFUNC: + case cmFUNC_BULK: + case cmFUNC_STR: + stOpt.push(opt); + break; + + case cmOPRT_POSTFIX: + stOpt.push(opt); + ApplyFunc(stOpt, stVal, 1); // this is the postfix operator + break; + + default: Error(ecINTERNAL_ERROR, 3); + } // end of switch operator-token + + opta = opt; + + if (opt.GetCode() == cmEND) + { + m_vRPN.Finalize(); + break; + } + + if (ParserBase::g_DbgDumpStack) + { + StackDump(stVal, stOpt); + m_vRPN.AsciiDump(); + } + +// if (ParserBase::g_DbgDumpCmdCode) + //m_vRPN.AsciiDump(); + } // while (true) + + if (ParserBase::g_DbgDumpCmdCode) + m_vRPN.AsciiDump(); + + if (ifElseCounter > 0) + Error(ecMISSING_ELSE_CLAUSE); + + // get the last value (= final result) from the stack + MUP_ASSERT(stArgCount.size() == 1); + m_nFinalResultIdx = stArgCount.top(); + if (m_nFinalResultIdx == 0) + Error(ecINTERNAL_ERROR, 9); + + if (stVal.size() == 0) + Error(ecEMPTY_EXPRESSION); + + // 2020-09-17; fix for https://oss-fuzz.com/testcase-detail/5758791700971520 + // I don't need the value stack any more. Destructively check if all values in the value + // stack represent floating point values + while (stVal.size()) + { + if (stVal.top().GetType() != tpDBL) + Error(ecSTR_RESULT); + + stVal.pop(); + } + + m_vStackBuffer.resize(m_vRPN.GetMaxStackSize() * s_MaxNumOpenMPThreads); + } + + //--------------------------------------------------------------------------- + /** \brief One of the two main parse functions. + \sa ParseCmdCode(...) + + Parse expression from input string. Perform syntax checking and create + bytecode. After parsing the string and creating the bytecode the function + pointer #m_pParseFormula will be changed to the second parse routine the + uses bytecode instead of string parsing. + */ + value_type ParserBase::ParseString() const + { + try + { + CreateRPN(); + + if (m_vRPN.GetSize() == 2) + { + m_vRPN.StoreEnvironment(m_pTokenReader->GetExpr(), m_vStringBuf); + m_pParseFormula = &ParserBase::ParseCmdCodeShort; + m_vStackBuffer[1] = (this->*m_pParseFormula)(); + return m_vStackBuffer[1]; + } + else + { + m_vRPN.StoreEnvironment(m_pTokenReader->GetExpr(), m_vStringBuf); + m_pParseFormula = &ParserBase::ParseCmdCode; + return (this->*m_pParseFormula)(); + } + } + catch (ParserError& exc) + { + exc.SetFormula(m_pTokenReader->GetExpr()); + throw; + } + } + + //--------------------------------------------------------------------------- + /** \brief Create an error containing the parse error position. + + This function will create an Parser Exception object containing the error text and + its position. + + \param a_iErrc [in] The error code of type #EErrorCodes. + \param a_iPos [in] The position where the error was detected. + \param a_strTok [in] The token string representation associated with the error. + \throw ParserException always throws that's the only purpose of this function. + */ + void ParserBase::Error(EErrorCodes a_iErrc, int a_iPos, const string_type& a_sTok) const + { + throw exception_type(a_iErrc, a_sTok, m_pTokenReader->GetExpr(), a_iPos); + } + + //------------------------------------------------------------------------------ + /** \brief Clear all user defined variables. + \throw nothrow + + Resets the parser to string parsing mode by calling #ReInit. + */ + void ParserBase::ClearVar() + { + m_VarDef.clear(); + ReInit(); + } + + //------------------------------------------------------------------------------ + /** \brief Remove a variable from internal storage. + \throw nothrow + + Removes a variable if it exists. If the Variable does not exist nothing will be done. + */ + void ParserBase::RemoveVar(const string_type& a_strVarName) + { + varmap_type::iterator item = m_VarDef.find(a_strVarName); + if (item != m_VarDef.end()) + { + m_VarDef.erase(item); + ReInit(); + } + } + + //------------------------------------------------------------------------------ + /** \brief Clear all functions. + \post Resets the parser to string parsing mode. + \throw nothrow + */ + void ParserBase::ClearFun() + { + m_FunDef.clear(); + ReInit(); + } + + //------------------------------------------------------------------------------ + /** \brief Clear all user defined constants. + + Both numeric and string constants will be removed from the internal storage. + \post Resets the parser to string parsing mode. + \throw nothrow + */ + void ParserBase::ClearConst() + { + m_ConstDef.clear(); + m_StrVarDef.clear(); + ReInit(); + } + + //------------------------------------------------------------------------------ + /** \brief Clear all user defined postfix operators. + \post Resets the parser to string parsing mode. + \throw nothrow + */ + void ParserBase::ClearPostfixOprt() + { + m_PostOprtDef.clear(); + ReInit(); + } + + //------------------------------------------------------------------------------ + /** \brief Clear all user defined binary operators. + \post Resets the parser to string parsing mode. + \throw nothrow + */ + void ParserBase::ClearOprt() + { + m_OprtDef.clear(); + ReInit(); + } + + //------------------------------------------------------------------------------ + /** \brief Clear the user defined Prefix operators. + \post Resets the parser to string parser mode. + \throw nothrow + */ + void ParserBase::ClearInfixOprt() + { + m_InfixOprtDef.clear(); + ReInit(); + } + + //------------------------------------------------------------------------------ + /** \brief Enable or disable the formula optimization feature. + \post Resets the parser to string parser mode. + \throw nothrow + */ + void ParserBase::EnableOptimizer(bool a_bIsOn) + { + m_vRPN.EnableOptimizer(a_bIsOn); + ReInit(); + } + + //--------------------------------------------------------------------------- + /** \brief Enable the dumping of bytecode and stack content on the console. + \param bDumpCmd Flag to enable dumping of the current bytecode to the console. + \param bDumpStack Flag to enable dumping of the stack content is written to the console. + + This function is for debug purposes only! + */ + void ParserBase::EnableDebugDump(bool bDumpCmd, bool bDumpStack) + { + ParserBase::g_DbgDumpCmdCode = bDumpCmd; + ParserBase::g_DbgDumpStack = bDumpStack; + } + + //------------------------------------------------------------------------------ + /** \brief Enable or disable the built in binary operators. + \throw nothrow + \sa m_bBuiltInOp, ReInit() + + If you disable the built in binary operators there will be no binary operators + defined. Thus you must add them manually one by one. It is not possible to + disable built in operators selectively. This function will Reinitialize the + parser by calling ReInit(). + */ + void ParserBase::EnableBuiltInOprt(bool a_bIsOn) + { + m_bBuiltInOp = a_bIsOn; + ReInit(); + } + + //------------------------------------------------------------------------------ + /** \brief Query status of built in variables. + \return #m_bBuiltInOp; true if built in operators are enabled. + \throw nothrow + */ + bool ParserBase::HasBuiltInOprt() const + { + return m_bBuiltInOp; + } + + //------------------------------------------------------------------------------ + /** \brief Get the argument separator character. + */ + char_type ParserBase::GetArgSep() const + { + return m_pTokenReader->GetArgSep(); + } + + //------------------------------------------------------------------------------ + /** \brief Set argument separator. + \param cArgSep the argument separator character. + */ + void ParserBase::SetArgSep(char_type cArgSep) + { + m_pTokenReader->SetArgSep(cArgSep); + } + + //------------------------------------------------------------------------------ + /** \brief Dump stack content. + + This function is used for debugging only. + */ + void ParserBase::StackDump(const std::stack& a_stVal, const std::stack& a_stOprt) const + { + std::stack stOprt(a_stOprt); + std::stack stVal(a_stVal); + + mu::console() << _T("\nValue stack:\n"); + while (!stVal.empty()) + { + token_type val = stVal.top(); + stVal.pop(); + + if (val.GetType() == tpSTR) + mu::console() << _T(" \"") << val.GetAsString() << _T("\" "); + else + mu::console() << _T(" ") << val.GetVal() << _T(" "); + } + mu::console() << "\nOperator stack:\n"; + + while (!stOprt.empty()) + { + if (stOprt.top().GetCode() <= cmASSIGN) + { + mu::console() << _T("OPRT_INTRNL \"") + << ParserBase::c_DefaultOprt[stOprt.top().GetCode()] + << _T("\" \n"); + } + else + { + switch (stOprt.top().GetCode()) + { + case cmVAR: mu::console() << _T("VAR\n"); break; + case cmVAL: mu::console() << _T("VAL\n"); break; + case cmFUNC: + mu::console() + << _T("FUNC \"") + << stOprt.top().GetAsString() + << _T("\"\n"); + break; + + case cmFUNC_BULK: + mu::console() + << _T("FUNC_BULK \"") + << stOprt.top().GetAsString() + << _T("\"\n"); + break; + + case cmOPRT_INFIX: + mu::console() << _T("OPRT_INFIX \"") + << stOprt.top().GetAsString() + << _T("\"\n"); + break; + + case cmOPRT_BIN: + mu::console() << _T("OPRT_BIN \"") + << stOprt.top().GetAsString() + << _T("\"\n"); + break; + + case cmFUNC_STR: mu::console() << _T("FUNC_STR\n"); break; + case cmEND: mu::console() << _T("END\n"); break; + case cmUNKNOWN: mu::console() << _T("UNKNOWN\n"); break; + case cmBO: mu::console() << _T("BRACKET \"(\"\n"); break; + case cmBC: mu::console() << _T("BRACKET \")\"\n"); break; + case cmIF: mu::console() << _T("IF\n"); break; + case cmELSE: mu::console() << _T("ELSE\n"); break; + case cmENDIF: mu::console() << _T("ENDIF\n"); break; + default: mu::console() << stOprt.top().GetCode() << _T(" "); break; + } + } + stOprt.pop(); + } + + mu::console() << dec << endl; + } + + /** \brief Calculate the result. + + A note on const correctness: + I consider it important that Calc is a const function. + Due to caching operations Calc changes only the state of internal variables with one exception + m_UsedVar this is reset during string parsing and accessible from the outside. Instead of making + Calc non const GetUsedVar is non const because it explicitly calls Eval() forcing this update. + + \pre A formula must be set. + \pre Variables must have been set (if needed) + + \sa #m_pParseFormula + \return The evaluation result + \throw ParseException if no Formula is set or in case of any other error related to the formula. + */ + value_type ParserBase::Eval() const + { + return (this->*m_pParseFormula)(); + } + + //------------------------------------------------------------------------------ + /** \brief Evaluate an expression containing comma separated subexpressions + \param [out] nStackSize The total number of results available + \return Pointer to the array containing all expression results + + This member function can be used to retrieve all results of an expression + made up of multiple comma separated subexpressions (i.e. "x+y,sin(x),cos(y)") + */ + value_type* ParserBase::Eval(int& nStackSize) const + { + if (m_vRPN.GetSize() > 0) + { + ParseCmdCode(); + } + else + { + ParseString(); + } + + nStackSize = m_nFinalResultIdx; + + // (for historic reasons the stack starts at position 1) + return &m_vStackBuffer[1]; + } + + //--------------------------------------------------------------------------- + /** \brief Return the number of results on the calculation stack. + + If the expression contains comma separated subexpressions (i.e. "sin(y), x+y"). + There may be more than one return value. This function returns the number of + available results. + */ + int ParserBase::GetNumResults() const + { + return m_nFinalResultIdx; + } + + //--------------------------------------------------------------------------- + void ParserBase::Eval(value_type* results, int nBulkSize) + { + CreateRPN(); + + int i = 0; + +#ifdef MUP_USE_OPENMP + //#define DEBUG_OMP_STUFF +#ifdef DEBUG_OMP_STUFF + int* pThread = new int[nBulkSize]; + int* pIdx = new int[nBulkSize]; +#endif + + int nMaxThreads = std::min(omp_get_max_threads(), s_MaxNumOpenMPThreads); + int nThreadID = 0; + +#ifdef DEBUG_OMP_STUFF + int ct = 0; +#endif + omp_set_num_threads(nMaxThreads); + + const int chunkSize = std::max(nBulkSize/nMaxThreads, 1); +#pragma omp parallel for schedule(static, chunkSize) private(nThreadID) + for (i = 0; i < nBulkSize; ++i) + { + nThreadID = omp_get_thread_num(); + results[i] = ParseCmdCodeBulk(i, nThreadID); + +#ifdef DEBUG_OMP_STUFF +#pragma omp critical + { + pThread[ct] = nThreadID; + pIdx[ct] = i; + ct++; + } +#endif + } + +#ifdef DEBUG_OMP_STUFF + FILE* pFile = fopen("bulk_dbg.txt", "w"); + for (i = 0; i < nBulkSize; ++i) + { + fprintf(pFile, "idx: %d thread: %d \n", pIdx[i], pThread[i]); + } + + delete[] pIdx; + delete[] pThread; + + fclose(pFile); +#endif + +#else + for (i = 0; i < nBulkSize; ++i) + { + results[i] = ParseCmdCodeBulk(i, 0); + } +#endif + + } +} // namespace mu + +#if defined(_MSC_VER) + #pragma warning(pop) +#endif + diff --git a/3rdparty/muparser/muParserBase.h b/3rdparty/muparser/muParserBase.h index 685f59fb..15ac151a 100644 --- a/3rdparty/muparser/muParserBase.h +++ b/3rdparty/muparser/muParserBase.h @@ -1,317 +1,319 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2013 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -#ifndef MU_PARSER_BASE_H -#define MU_PARSER_BASE_H - -//--- Standard includes ------------------------------------------------------------------------ -#include -#include -#include -#include -#include -#include -#include - -//--- Parser includes -------------------------------------------------------------------------- -#include "muParserDef.h" -#include "muParserStack.h" -#include "muParserTokenReader.h" -#include "muParserBytecode.h" -#include "muParserError.h" - - -namespace mu -{ -/** \file - \brief This file contains the class definition of the muparser engine. -*/ - -//-------------------------------------------------------------------------------------------------- -/** \brief Mathematical expressions parser (base parser engine). - \author (C) 2013 Ingo Berg - - This is the implementation of a bytecode based mathematical expressions parser. - The formula will be parsed from string and converted into a bytecode. - Future calculations will be done with the bytecode instead the formula string - resulting in a significant performance increase. - Complementary to a set of internally implemented functions the parser is able to handle - user defined functions and variables. -*/ -class ParserBase -{ -friend class ParserTokenReader; - -private: - - /** \brief Typedef for the parse functions. - - The parse function do the actual work. The parser exchanges - the function pointer to the parser function depending on - which state it is in. (i.e. bytecode parser vs. string parser) - */ - typedef value_type (ParserBase::*ParseFunction)() const; - - /** \brief Type used for storing an array of values. */ - typedef std::vector valbuf_type; - - /** \brief Type for a vector of strings. */ - typedef std::vector stringbuf_type; - - /** \brief Typedef for the token reader. */ - typedef ParserTokenReader token_reader_type; - - /** \brief Type used for parser tokens. */ - typedef ParserToken token_type; - - /** \brief Maximum number of threads spawned by OpenMP when using the bulk mode. */ - static const int s_MaxNumOpenMPThreads = 16; - - public: - - /** \brief Type of the error class. - - Included for backwards compatibility. - */ - typedef ParserError exception_type; - - static void EnableDebugDump(bool bDumpCmd, bool bDumpStack); - - ParserBase(); - ParserBase(const ParserBase &a_Parser); - ParserBase& operator=(const ParserBase &a_Parser); - - virtual ~ParserBase(); - - value_type Eval() const; - value_type* Eval(int &nStackSize) const; - void Eval(value_type *results, int nBulkSize); - - int GetNumResults() const; - - void SetExpr(const string_type &a_sExpr); - void SetVarFactory(facfun_type a_pFactory, void *pUserData = NULL); - - void SetDecSep(char_type cDecSep); - void SetThousandsSep(char_type cThousandsSep = 0); - void ResetLocale(); - - void EnableOptimizer(bool a_bIsOn=true); - void EnableBuiltInOprt(bool a_bIsOn=true); - - bool HasBuiltInOprt() const; - void AddValIdent(identfun_type a_pCallback); - - /** \fn void mu::ParserBase::DefineFun(const string_type &a_strName, fun_type0 a_pFun, bool a_bAllowOpt = true) - \brief Define a parser function without arguments. - \param a_strName Name of the function - \param a_pFun Pointer to the callback function - \param a_bAllowOpt A flag indicating this function may be optimized - */ - template - void DefineFun(const string_type &a_strName, T a_pFun, bool a_bAllowOpt = true) - { - AddCallback( a_strName, ParserCallback(a_pFun, a_bAllowOpt), m_FunDef, ValidNameChars() ); - } - - void DefineOprt(const string_type &a_strName, - fun_type2 a_pFun, - unsigned a_iPri=0, - EOprtAssociativity a_eAssociativity = oaLEFT, - bool a_bAllowOpt = false); - void DefineConst(const string_type &a_sName, value_type a_fVal); - void DefineStrConst(const string_type &a_sName, const string_type &a_strVal); - void DefineVar(const string_type &a_sName, value_type *a_fVar); - void DefinePostfixOprt(const string_type &a_strFun, fun_type1 a_pOprt, bool a_bAllowOpt=true); - void DefineInfixOprt(const string_type &a_strName, fun_type1 a_pOprt, int a_iPrec=prINFIX, bool a_bAllowOpt=true); - - // Clear user defined variables, constants or functions - void ClearVar(); - void ClearFun(); - void ClearConst(); - void ClearInfixOprt(); - void ClearPostfixOprt(); - void ClearOprt(); - - void RemoveVar(const string_type &a_strVarName); - const varmap_type& GetUsedVar() const; - const varmap_type& GetVar() const; - const valmap_type& GetConst() const; - const string_type& GetExpr() const; - const funmap_type& GetFunDef() const; - string_type GetVersion(EParserVersionInfo eInfo = pviFULL) const; - - const char_type ** GetOprtDef() const; - void DefineNameChars(const char_type *a_szCharset); - void DefineOprtChars(const char_type *a_szCharset); - void DefineInfixOprtChars(const char_type *a_szCharset); - - const char_type* ValidNameChars() const; - const char_type* ValidOprtChars() const; - const char_type* ValidInfixOprtChars() const; - - void SetArgSep(char_type cArgSep); - char_type GetArgSep() const; - - void Error(EErrorCodes a_iErrc, - int a_iPos = (int)mu::string_type::npos, - const string_type &a_strTok = string_type() ) const; - - protected: - - void Init(); - - virtual void InitCharSets() = 0; - virtual void InitFun() = 0; - virtual void InitConst() = 0; - virtual void InitOprt() = 0; - - virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd); - - static const char_type *c_DefaultOprt[]; - static std::locale s_locale; ///< The locale used by the parser - static bool g_DbgDumpCmdCode; - static bool g_DbgDumpStack; - - /** \brief A facet class used to change decimal and thousands separator. */ - template - class change_dec_sep : public std::numpunct - { - public: - - explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3) - :std::numpunct() - ,m_nGroup(nGroup) - ,m_cDecPoint(cDecSep) - ,m_cThousandsSep(cThousandsSep) - {} - - protected: - - virtual char_type do_decimal_point() const - { - return m_cDecPoint; - } - - virtual char_type do_thousands_sep() const - { - return m_cThousandsSep; - } - - virtual std::string do_grouping() const - { - // fix for issue 4: https://code.google.com/p/muparser/issues/detail?id=4 - // courtesy of Jens Bartsch - // original code: - // return std::string(1, (char)m_nGroup); - // new code: - return std::string(1, (char)(m_cThousandsSep > 0 ? m_nGroup : CHAR_MAX)); - } - - private: - - int m_nGroup; - char_type m_cDecPoint; - char_type m_cThousandsSep; - }; - - private: - - void Assign(const ParserBase &a_Parser); - void InitTokenReader(); - void ReInit() const; - - void AddCallback( const string_type &a_strName, - const ParserCallback &a_Callback, - funmap_type &a_Storage, - const char_type *a_szCharSet ); - - void ApplyRemainingOprt(ParserStack &a_stOpt, - ParserStack &a_stVal) const; - void ApplyBinOprt(ParserStack &a_stOpt, - ParserStack &a_stVal) const; - - void ApplyIfElse(ParserStack &a_stOpt, - ParserStack &a_stVal) const; - - void ApplyFunc(ParserStack &a_stOpt, - ParserStack &a_stVal, - int iArgCount) const; - - token_type ApplyStrFunc(const token_type &a_FunTok, - const std::vector &a_vArg) const; - - int GetOprtPrecedence(const token_type &a_Tok) const; - EOprtAssociativity GetOprtAssociativity(const token_type &a_Tok) const; - - void CreateRPN() const; - - value_type ParseString() const; - value_type ParseCmdCode() const; - value_type ParseCmdCodeBulk(int nOffset, int nThreadID) const; - - void CheckName(const string_type &a_strName, const string_type &a_CharSet) const; - void CheckOprt(const string_type &a_sName, - const ParserCallback &a_Callback, - const string_type &a_szCharSet) const; - - void StackDump(const ParserStack &a_stVal, - const ParserStack &a_stOprt) const; - - /** \brief Pointer to the parser function. - - Eval() calls the function whose address is stored there. - */ - mutable ParseFunction m_pParseFormula; - mutable ParserByteCode m_vRPN; ///< The Bytecode class. - mutable stringbuf_type m_vStringBuf; ///< String buffer, used for storing string function arguments - stringbuf_type m_vStringVarBuf; - - std::unique_ptr m_pTokenReader; ///< Managed pointer to the token reader object. - - funmap_type m_FunDef; ///< Map of function names and pointers. - funmap_type m_PostOprtDef; ///< Postfix operator callbacks - funmap_type m_InfixOprtDef; ///< unary infix operator. - funmap_type m_OprtDef; ///< Binary operator callbacks - valmap_type m_ConstDef; ///< user constants. - strmap_type m_StrVarDef; ///< user defined string constants - varmap_type m_VarDef; ///< user defind variables. - - bool m_bBuiltInOp; ///< Flag that can be used for switching built in operators on and off - - string_type m_sNameChars; ///< Charset for names - string_type m_sOprtChars; ///< Charset for postfix/ binary operator tokens - string_type m_sInfixOprtChars; ///< Charset for infix operator tokens - - mutable int m_nIfElseCounter; ///< Internal counter for keeping track of nested if-then-else clauses - - // items merely used for caching state information - mutable valbuf_type m_vStackBuffer; ///< This is merely a buffer used for the stack in the cmd parsing routine - mutable int m_nFinalResultIdx; -}; - -} // namespace mu - -#endif - +/* + + _____ __ _____________ _______ ______ ___________ + / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ + | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ + |__|_| /____/| __(____ /__| /____ >\___ >__| + \/ |__| \/ \/ \/ + Copyright (C) 2004 - 2022 Ingo Berg + + Redistribution and use in source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef MU_PARSER_BASE_H +#define MU_PARSER_BASE_H + +//--- Standard includes ------------------------------------------------------------------------ +#include +#include +#include +#include +#include +#include +#include + +//--- Parser includes -------------------------------------------------------------------------- +#include "muParserDef.h" +#include "muParserTokenReader.h" +#include "muParserBytecode.h" +#include "muParserError.h" + +#if defined(_MSC_VER) + #pragma warning(push) + #pragma warning(disable : 4251) // ...needs to have dll-interface to be used by clients of class ... +#endif + + +namespace mu +{ + /** \file + \brief This file contains the class definition of the muparser engine. + */ + + /** \brief Mathematical expressions parser (base parser engine). + + This is the implementation of a bytecode based mathematical expressions parser. + The formula will be parsed from string and converted into a bytecode. + Future calculations will be done with the bytecode instead the formula string + resulting in a significant performance increase. + Complementary to a set of internally implemented functions the parser is able to handle + user defined functions and variables. + */ + class API_EXPORT_CXX ParserBase + { + friend class ParserTokenReader; + + private: + + /** \brief Typedef for the parse functions. + + The parse function do the actual work. The parser exchanges + the function pointer to the parser function depending on + which state it is in. (i.e. bytecode parser vs. string parser) + */ + typedef value_type(ParserBase::* ParseFunction)() const; + + /** \brief Type used for storing an array of values. */ + typedef std::vector valbuf_type; + + /** \brief Type for a vector of strings. */ + typedef std::vector stringbuf_type; + + /** \brief Typedef for the token reader. */ + typedef ParserTokenReader token_reader_type; + + /** \brief Type used for parser tokens. */ + typedef ParserToken token_type; + + /** \brief Maximum number of threads spawned by OpenMP when using the bulk mode. */ + static const int s_MaxNumOpenMPThreads; + + public: + + /** \brief Type of the error class. + + Included for backwards compatibility. + */ + typedef ParserError exception_type; + + static void EnableDebugDump(bool bDumpCmd, bool bDumpStack); + + ParserBase(); + ParserBase(const ParserBase& a_Parser); + ParserBase& operator=(const ParserBase& a_Parser); + + virtual ~ParserBase(); + + value_type Eval() const; + value_type* Eval(int& nStackSize) const; + void Eval(value_type* results, int nBulkSize); + + int GetNumResults() const; + + void SetExpr(const string_type& a_sExpr); + void SetVarFactory(facfun_type a_pFactory, void* pUserData = nullptr); + + void SetDecSep(char_type cDecSep); + void SetThousandsSep(char_type cThousandsSep = 0); + void ResetLocale(); + + void EnableOptimizer(bool a_bIsOn = true); + void EnableBuiltInOprt(bool a_bIsOn = true); + + bool HasBuiltInOprt() const; + void AddValIdent(identfun_type a_pCallback); + + /** \fn void mu::ParserBase::DefineFun(const string_type &a_strName, fun_type0 a_pFun, bool a_bAllowOpt = true) + \brief Define a parser function without arguments. + \param a_strName Name of the function + \param a_pFun Pointer to the callback function + \param a_bAllowOpt A flag indicating this function may be optimized + */ + template + void DefineFun(const string_type& a_strName, T a_pFun, bool a_bAllowOpt = true) + { + AddCallback(a_strName, ParserCallback(a_pFun, a_bAllowOpt), m_FunDef, ValidNameChars()); + } + + /** \fn void mu::ParserBase::DefineFunUserData + \brief Define a parser function with user data (not null). + \param a_strName Name of the function + \param a_pFun Pointer to the callback function + \param a_pUserData Pointer that will be passed back to callback (shall not be nullptr) + \param a_bAllowOpt A flag indicating this function may be optimized + */ + template + void DefineFunUserData(const string_type& a_strName, T a_pFun, void* a_pUserData, bool a_bAllowOpt = true) + { + AddCallback(a_strName, ParserCallback(a_pFun, a_pUserData, a_bAllowOpt), m_FunDef, ValidNameChars()); + } + + void DefineOprt(const string_type& a_strName, fun_type2 a_pFun, unsigned a_iPri = 0, EOprtAssociativity a_eAssociativity = oaLEFT, bool a_bAllowOpt = false); + void DefineConst(const string_type& a_sName, value_type a_fVal); + void DefineStrConst(const string_type& a_sName, const string_type& a_strVal); + void DefineVar(const string_type& a_sName, value_type* a_fVar); + void DefinePostfixOprt(const string_type& a_strFun, fun_type1 a_pOprt, bool a_bAllowOpt = true); + void DefineInfixOprt(const string_type& a_strName, fun_type1 a_pOprt, int a_iPrec = prINFIX, bool a_bAllowOpt = true); + + // Clear user defined variables, constants or functions + void ClearVar(); + void ClearFun(); + void ClearConst(); + void ClearInfixOprt(); + void ClearPostfixOprt(); + void ClearOprt(); + + void RemoveVar(const string_type& a_strVarName); + const varmap_type& GetUsedVar() const; + const varmap_type& GetVar() const; + const valmap_type& GetConst() const; + const string_type& GetExpr() const; + const funmap_type& GetFunDef() const; + string_type GetVersion(EParserVersionInfo eInfo = pviFULL) const; + const ParserByteCode& GetByteCode() const; + + const char_type** GetOprtDef() const; + void DefineNameChars(const char_type* a_szCharset); + void DefineOprtChars(const char_type* a_szCharset); + void DefineInfixOprtChars(const char_type* a_szCharset); + + const char_type* ValidNameChars() const; + const char_type* ValidOprtChars() const; + const char_type* ValidInfixOprtChars() const; + + void SetArgSep(char_type cArgSep); + void SetByteCode(const ParserByteCode& a_ByteCode); + + char_type GetArgSep() const; + + protected: + + void Init(); + void Error(EErrorCodes a_iErrc, int a_iPos = static_cast(mu::string_type::npos), const string_type& a_strTok = string_type()) const; + + virtual void InitCharSets() = 0; + virtual void InitFun() = 0; + virtual void InitConst() = 0; + virtual void InitOprt() = 0; + + virtual void OnDetectVar(string_type* pExpr, int& nStart, int& nEnd); + + static const char_type* c_DefaultOprt[]; + static std::locale s_locale; ///< The locale used by the parser + static bool g_DbgDumpCmdCode; + static bool g_DbgDumpStack; + + /** \brief A facet class used to change decimal and thousands separator. */ + template + class change_dec_sep : public std::numpunct + { + public: + + explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3) + :std::numpunct() + ,m_nGroup(nGroup) + ,m_cDecPoint(cDecSep) + ,m_cThousandsSep(cThousandsSep) + {} + + protected: + + char_type do_decimal_point() const override + { + return m_cDecPoint; + } + + char_type do_thousands_sep() const override + { + return m_cThousandsSep; + } + + std::string do_grouping() const override + { + // fix for issue 4: https://code.google.com/p/muparser/issues/detail?id=4 + // courtesy of Jens Bartsch + // original code: + // return std::string(1, (char)m_nGroup); + // new code: + return std::string(1, (char)(m_cThousandsSep > 0 ? m_nGroup : CHAR_MAX)); + } + + private: + + int m_nGroup; + char_type m_cDecPoint; + char_type m_cThousandsSep; + }; + + private: + + void Assign(const ParserBase& a_Parser); + void InitTokenReader(); + void ReInit() const; + + void AddCallback(const string_type& a_strName, const ParserCallback& a_Callback, funmap_type& a_Storage, const char_type* a_szCharSet); + void ApplyRemainingOprt(std::stack& a_stOpt, std::stack& a_stVal) const; + void ApplyBinOprt(std::stack& a_stOpt, std::stack& a_stVal) const; + void ApplyIfElse(std::stack& a_stOpt, std::stack& a_stVal) const; + void ApplyFunc(std::stack& a_stOpt, std::stack& a_stVal, int iArgCount) const; + + token_type ApplyStrFunc(const token_type& a_FunTok, const std::vector& a_vArg) const; + + int GetOprtPrecedence(const token_type& a_Tok) const; + EOprtAssociativity GetOprtAssociativity(const token_type& a_Tok) const; + + void CreateRPN() const; + + value_type ParseString() const; + value_type ParseCmdCode() const; + value_type ParseCmdCodeShort() const; + value_type ParseCmdCodeBulk(int nOffset, int nThreadID) const; + + void CheckName(const string_type& a_strName, const string_type& a_CharSet) const; + void CheckOprt(const string_type& a_sName, const ParserCallback& a_Callback, const string_type& a_szCharSet) const; + + void StackDump(const std::stack& a_stVal, const std::stack& a_stOprt) const; + + /** \brief Pointer to the parser function. + + Eval() calls the function whose address is stored there. + */ + mutable ParseFunction m_pParseFormula; + mutable ParserByteCode m_vRPN; ///< The Bytecode class. + mutable stringbuf_type m_vStringBuf; ///< String buffer, used for storing string function arguments + stringbuf_type m_vStringVarBuf; + + std::unique_ptr m_pTokenReader; ///< Managed pointer to the token reader object. + + funmap_type m_FunDef; ///< Map of function names and pointers. + funmap_type m_PostOprtDef; ///< Postfix operator callbacks + funmap_type m_InfixOprtDef; ///< unary infix operator. + funmap_type m_OprtDef; ///< Binary operator callbacks + valmap_type m_ConstDef; ///< user constants. + strmap_type m_StrVarDef; ///< user defined string constants + varmap_type m_VarDef; ///< user defind variables. + + bool m_bBuiltInOp; ///< Flag that can be used for switching built in operators on and off + + string_type m_sNameChars; ///< Charset for names + string_type m_sOprtChars; ///< Charset for postfix/ binary operator tokens + string_type m_sInfixOprtChars; ///< Charset for infix operator tokens + + // items merely used for caching state information + mutable valbuf_type m_vStackBuffer; ///< This is merely a buffer used for the stack in the cmd parsing routine + mutable int m_nFinalResultIdx; + }; + +} // namespace mu + +#if defined(_MSC_VER) + #pragma warning(pop) +#endif + +#endif diff --git a/3rdparty/muparser/muParserBytecode.cpp b/3rdparty/muparser/muParserBytecode.cpp index 3964998f..1bc61c3a 100644 --- a/3rdparty/muparser/muParserBytecode.cpp +++ b/3rdparty/muparser/muParserBytecode.cpp @@ -1,588 +1,649 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2011 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "muParserBytecode.h" - -#include -#include -#include -#include -#include -#include - -#include "muParserDef.h" -#include "muParserError.h" -#include "muParserToken.h" -#include "muParserStack.h" -#include "muParserTemplateMagic.h" - - -namespace mu -{ - //--------------------------------------------------------------------------- - /** \brief Bytecode default constructor. */ - ParserByteCode::ParserByteCode() - :m_iStackPos(0) - ,m_iMaxStackSize(0) - ,m_vRPN() - ,m_bEnableOptimizer(true) - { - m_vRPN.reserve(50); - } - - //--------------------------------------------------------------------------- - /** \brief Copy constructor. - - Implemented in Terms of Assign(const ParserByteCode &a_ByteCode) - */ - ParserByteCode::ParserByteCode(const ParserByteCode &a_ByteCode) - { - Assign(a_ByteCode); - } - - //--------------------------------------------------------------------------- - /** \brief Assignment operator. - - Implemented in Terms of Assign(const ParserByteCode &a_ByteCode) - */ - ParserByteCode& ParserByteCode::operator=(const ParserByteCode &a_ByteCode) - { - Assign(a_ByteCode); - return *this; - } - - //--------------------------------------------------------------------------- - void ParserByteCode::EnableOptimizer(bool bStat) - { - m_bEnableOptimizer = bStat; - } - - //--------------------------------------------------------------------------- - /** \brief Copy state of another object to this. - - \throw nowthrow - */ - void ParserByteCode::Assign(const ParserByteCode &a_ByteCode) - { - if (this==&a_ByteCode) - return; - - m_iStackPos = a_ByteCode.m_iStackPos; - m_vRPN = a_ByteCode.m_vRPN; - m_iMaxStackSize = a_ByteCode.m_iMaxStackSize; - m_bEnableOptimizer = a_ByteCode.m_bEnableOptimizer; - } - - //--------------------------------------------------------------------------- - /** \brief Add a Variable pointer to bytecode. - \param a_pVar Pointer to be added. - \throw nothrow - */ - void ParserByteCode::AddVar(value_type *a_pVar) - { - ++m_iStackPos; - m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); - - // optimization does not apply - SToken tok; - tok.Cmd = cmVAR; - tok.Val.ptr = a_pVar; - tok.Val.data = 1; - tok.Val.data2 = 0; - m_vRPN.push_back(tok); - } - - //--------------------------------------------------------------------------- - /** \brief Add a Variable pointer to bytecode. - - Value entries in byte code consist of: -
    -
  • value array position of the value
  • -
  • the operator code according to ParserToken::cmVAL
  • -
  • the value stored in #mc_iSizeVal number of bytecode entries.
  • -
- - \param a_pVal Value to be added. - \throw nothrow - */ - void ParserByteCode::AddVal(value_type a_fVal) - { - ++m_iStackPos; - m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); - - // If optimization does not apply - SToken tok; - tok.Cmd = cmVAL; - tok.Val.ptr = NULL; - tok.Val.data = 0; - tok.Val.data2 = a_fVal; - m_vRPN.push_back(tok); - } - - //--------------------------------------------------------------------------- - void ParserByteCode::ConstantFolding(ECmdCode a_Oprt) - { - std::size_t sz = m_vRPN.size(); - value_type &x = m_vRPN[sz-2].Val.data2, - &y = m_vRPN[sz-1].Val.data2; - switch (a_Oprt) - { - case cmLAND: x = (int)x && (int)y; m_vRPN.pop_back(); break; - case cmLOR: x = (int)x || (int)y; m_vRPN.pop_back(); break; - case cmLT: x = x < y; m_vRPN.pop_back(); break; - case cmGT: x = x > y; m_vRPN.pop_back(); break; - case cmLE: x = x <= y; m_vRPN.pop_back(); break; - case cmGE: x = x >= y; m_vRPN.pop_back(); break; - case cmNEQ: x = x != y; m_vRPN.pop_back(); break; - case cmEQ: x = x == y; m_vRPN.pop_back(); break; - case cmADD: x = x + y; m_vRPN.pop_back(); break; - case cmSUB: x = x - y; m_vRPN.pop_back(); break; - case cmMUL: x = x * y; m_vRPN.pop_back(); break; - case cmDIV: - -#if defined(MUP_MATH_EXCEPTIONS) - if (y==0) - throw ParserError(ecDIV_BY_ZERO, _T("0")); -#endif - - x = x / y; - m_vRPN.pop_back(); - break; - - case cmPOW: x = MathImpl::Pow(x, y); - m_vRPN.pop_back(); - break; - - default: - break; - } // switch opcode - } - - //--------------------------------------------------------------------------- - /** \brief Add an operator identifier to bytecode. - - Operator entries in byte code consist of: -
    -
  • value array position of the result
  • -
  • the operator code according to ParserToken::ECmdCode
  • -
- - \sa ParserToken::ECmdCode - */ - void ParserByteCode::AddOp(ECmdCode a_Oprt) - { - bool bOptimized = false; - - if (m_bEnableOptimizer) - { - std::size_t sz = m_vRPN.size(); - - // Check for foldable constants like: - // cmVAL cmVAL cmADD - // where cmADD can stand fopr any binary operator applied to - // two constant values. - if (sz>=2 && m_vRPN[sz-2].Cmd == cmVAL && m_vRPN[sz-1].Cmd == cmVAL) - { - ConstantFolding(a_Oprt); - bOptimized = true; - } - else - { - switch(a_Oprt) - { - case cmPOW: - // Optimization for polynomials of low order - if (m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-1].Cmd == cmVAL) - { - if (m_vRPN[sz-1].Val.data2==2) - m_vRPN[sz-2].Cmd = cmVARPOW2; - else if (m_vRPN[sz-1].Val.data2==3) - m_vRPN[sz-2].Cmd = cmVARPOW3; - else if (m_vRPN[sz-1].Val.data2==4) - m_vRPN[sz-2].Cmd = cmVARPOW4; - else - break; - - m_vRPN.pop_back(); - bOptimized = true; - } - break; - - case cmSUB: - case cmADD: - // Simple optimization based on pattern recognition for a shitload of different - // bytecode combinations of addition/subtraction - if ( (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAL) || - (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVAR) || - (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL) || - (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAL) || - (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) || - (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) || - (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) || - (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) ) - { - assert( (m_vRPN[sz-2].Val.ptr==NULL && m_vRPN[sz-1].Val.ptr!=NULL) || - (m_vRPN[sz-2].Val.ptr!=NULL && m_vRPN[sz-1].Val.ptr==NULL) || - (m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) ); - - m_vRPN[sz-2].Cmd = cmVARMUL; - m_vRPN[sz-2].Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr)); // variable - m_vRPN[sz-2].Val.data2 += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].Val.data2; // offset - m_vRPN[sz-2].Val.data += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].Val.data; // multiplicand - m_vRPN.pop_back(); - bOptimized = true; - } - break; - - case cmMUL: - if ( (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAL) || - (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVAR) ) - { - m_vRPN[sz-2].Cmd = cmVARMUL; - m_vRPN[sz-2].Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr)); - m_vRPN[sz-2].Val.data = m_vRPN[sz-2].Val.data2 + m_vRPN[sz-1].Val.data2; - m_vRPN[sz-2].Val.data2 = 0; - m_vRPN.pop_back(); - bOptimized = true; - } - else if ( (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL) || - (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAL) ) - { - // Optimization: 2*(3*b+1) or (3*b+1)*2 -> 6*b+2 - m_vRPN[sz-2].Cmd = cmVARMUL; - m_vRPN[sz-2].Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr)); - if (m_vRPN[sz-1].Cmd == cmVAL) - { - m_vRPN[sz-2].Val.data *= m_vRPN[sz-1].Val.data2; - m_vRPN[sz-2].Val.data2 *= m_vRPN[sz-1].Val.data2; - } - else - { - m_vRPN[sz-2].Val.data = m_vRPN[sz-1].Val.data * m_vRPN[sz-2].Val.data2; - m_vRPN[sz-2].Val.data2 = m_vRPN[sz-1].Val.data2 * m_vRPN[sz-2].Val.data2; - } - m_vRPN.pop_back(); - bOptimized = true; - } - else if (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAR && - m_vRPN[sz-1].Val.ptr == m_vRPN[sz-2].Val.ptr) - { - // Optimization: a*a -> a^2 - m_vRPN[sz-2].Cmd = cmVARPOW2; - m_vRPN.pop_back(); - bOptimized = true; - } - break; - - case cmDIV: - if (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-1].Val.data2!=0) - { - // Optimization: 4*a/2 -> 2*a - m_vRPN[sz-2].Val.data /= m_vRPN[sz-1].Val.data2; - m_vRPN[sz-2].Val.data2 /= m_vRPN[sz-1].Val.data2; - m_vRPN.pop_back(); - bOptimized = true; - } - break; - - } // switch a_Oprt - } - } - - // If optimization can't be applied just write the value - if (!bOptimized) - { - --m_iStackPos; - SToken tok; - tok.Cmd = a_Oprt; - m_vRPN.push_back(tok); - } - } - - //--------------------------------------------------------------------------- - void ParserByteCode::AddIfElse(ECmdCode a_Oprt) - { - SToken tok; - tok.Cmd = a_Oprt; - m_vRPN.push_back(tok); - } - - //--------------------------------------------------------------------------- - /** \brief Add an assignment operator - - Operator entries in byte code consist of: -
    -
  • cmASSIGN code
  • -
  • the pointer of the destination variable
  • -
- - \sa ParserToken::ECmdCode - */ - void ParserByteCode::AddAssignOp(value_type *a_pVar) - { - --m_iStackPos; - - SToken tok; - tok.Cmd = cmASSIGN; - tok.Oprt.ptr = a_pVar; - m_vRPN.push_back(tok); - } - - //--------------------------------------------------------------------------- - /** \brief Add function to bytecode. - - \param a_iArgc Number of arguments, negative numbers indicate multiarg functions. - \param a_pFun Pointer to function callback. - */ - void ParserByteCode::AddFun(generic_fun_type a_pFun, int a_iArgc) - { - if (a_iArgc>=0) - { - m_iStackPos = m_iStackPos - a_iArgc + 1; - } - else - { - // function with unlimited number of arguments - m_iStackPos = m_iStackPos + a_iArgc + 1; - } - m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); - - SToken tok; - tok.Cmd = cmFUNC; - tok.Fun.argc = a_iArgc; - tok.Fun.ptr = a_pFun; - m_vRPN.push_back(tok); - } - - //--------------------------------------------------------------------------- - /** \brief Add a bulk function to bytecode. - - \param a_iArgc Number of arguments, negative numbers indicate multiarg functions. - \param a_pFun Pointer to function callback. - */ - void ParserByteCode::AddBulkFun(generic_fun_type a_pFun, int a_iArgc) - { - m_iStackPos = m_iStackPos - a_iArgc + 1; - m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); - - SToken tok; - tok.Cmd = cmFUNC_BULK; - tok.Fun.argc = a_iArgc; - tok.Fun.ptr = a_pFun; - m_vRPN.push_back(tok); - } - - //--------------------------------------------------------------------------- - /** \brief Add Strung function entry to the parser bytecode. - \throw nothrow - - A string function entry consists of the stack position of the return value, - followed by a cmSTRFUNC code, the function pointer and an index into the - string buffer maintained by the parser. - */ - void ParserByteCode::AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx) - { - m_iStackPos = m_iStackPos - a_iArgc + 1; - - SToken tok; - tok.Cmd = cmFUNC_STR; - tok.Fun.argc = a_iArgc; - tok.Fun.idx = a_iIdx; - tok.Fun.ptr = a_pFun; - m_vRPN.push_back(tok); - - m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); - } - - //--------------------------------------------------------------------------- - /** \brief Add end marker to bytecode. - - \throw nothrow - */ - void ParserByteCode::Finalize() - { - SToken tok; - tok.Cmd = cmEND; - m_vRPN.push_back(tok); - rpn_type(m_vRPN).swap(m_vRPN); // shrink bytecode vector to fit - - // Determine the if-then-else jump offsets - ParserStack stIf, stElse; - int idx; - for (int i=0; i<(int)m_vRPN.size(); ++i) - { - switch(m_vRPN[i].Cmd) - { - case cmIF: - stIf.push(i); - break; - - case cmELSE: - stElse.push(i); - idx = stIf.pop(); - m_vRPN[idx].Oprt.offset = i - idx; - break; - - case cmENDIF: - idx = stElse.pop(); - m_vRPN[idx].Oprt.offset = i - idx; - break; - - default: - break; - } - } - } - - //--------------------------------------------------------------------------- - const SToken* ParserByteCode::GetBase() const - { - if (m_vRPN.size()==0) - throw ParserError(ecINTERNAL_ERROR); - else - return &m_vRPN[0]; - } - - //--------------------------------------------------------------------------- - std::size_t ParserByteCode::GetMaxStackSize() const - { - return m_iMaxStackSize+1; - } - - //--------------------------------------------------------------------------- - /** \brief Returns the number of entries in the bytecode. */ - std::size_t ParserByteCode::GetSize() const - { - return m_vRPN.size(); - } - - //--------------------------------------------------------------------------- - /** \brief Delete the bytecode. - - \throw nothrow - - The name of this function is a violation of my own coding guidelines - but this way it's more in line with the STL functions thus more - intuitive. - */ - void ParserByteCode::clear() - { - m_vRPN.clear(); - m_iStackPos = 0; - m_iMaxStackSize = 0; - } - - //--------------------------------------------------------------------------- - /** \brief Dump bytecode (for debugging only!). */ - void ParserByteCode::AsciiDump() - { - if (!m_vRPN.size()) - { - mu::console() << _T("No bytecode available\n"); - return; - } - - mu::console() << _T("Number of RPN tokens:") << (int)m_vRPN.size() << _T("\n"); - for (std::size_t i=0; i > __ \| | \/\___ \\ ___/| | \/ + |__|_| /____/| __(____ /__| /____ >\___ >__| + \/ |__| \/ \/ \/ + Copyright (C) 2004 - 2022 Ingo Berg + + Redistribution and use in source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "muParserBytecode.h" + +#include +#include +#include +#include +#include + +#include "muParserDef.h" +#include "muParserError.h" +#include "muParserToken.h" +#include "muParserTemplateMagic.h" + +#if defined(_MSC_VER) + #pragma warning(push) + #pragma warning(disable : 26812) +#endif + + +namespace mu +{ + /** \brief Bytecode default constructor. */ + ParserByteCode::ParserByteCode() + : m_iStackPos(0) + , m_stringBuffer() + , m_expr() + , m_iMaxStackSize(0) + , m_vRPN() + , m_bEnableOptimizer(true) + { + m_vRPN.reserve(50); + } + + + /** \brief Copy constructor. + + Implemented in Terms of Assign(const ParserByteCode &a_ByteCode) + */ + ParserByteCode::ParserByteCode(const ParserByteCode& a_ByteCode) + { + Assign(a_ByteCode); + } + + + /** \brief Assignment operator. + + Implemented in Terms of Assign(const ParserByteCode &a_ByteCode) + */ + ParserByteCode& ParserByteCode::operator=(const ParserByteCode& a_ByteCode) + { + Assign(a_ByteCode); + return *this; + } + + + void ParserByteCode::EnableOptimizer(bool bStat) + { + m_bEnableOptimizer = bStat; + } + + + /** \brief Copy state of another object to this. + + \throw nowthrow + */ + void ParserByteCode::Assign(const ParserByteCode& a_ByteCode) + { + if (this == &a_ByteCode) + return; + + m_iStackPos = a_ByteCode.m_iStackPos; + m_vRPN = a_ByteCode.m_vRPN; + m_iMaxStackSize = a_ByteCode.m_iMaxStackSize; + m_bEnableOptimizer = a_ByteCode.m_bEnableOptimizer; + + m_stringBuffer = a_ByteCode.m_stringBuffer; + m_expr = a_ByteCode.m_expr; + } + + + /** \brief Add a Variable pointer to bytecode. + \param a_pVar Pointer to be added. + \throw nothrow + */ + void ParserByteCode::AddVar(value_type* a_pVar) + { + ++m_iStackPos; + m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); + + // optimization does not apply + SToken tok; + tok.Cmd = cmVAR; + tok.Val.ptr = a_pVar; + tok.Val.data = 1; + tok.Val.data2 = 0; + m_vRPN.push_back(tok); + } + + + /** \brief Add a Variable pointer to bytecode. + + Value entries in byte code consist of: +
    +
  • value array position of the value
  • +
  • the operator code according to ParserToken::cmVAL
  • +
  • the value stored in #mc_iSizeVal number of bytecode entries.
  • +
+ + \param a_pVal Value to be added. + \throw nothrow + */ + void ParserByteCode::AddVal(value_type a_fVal) + { + ++m_iStackPos; + m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); + + // If optimization does not apply + SToken tok; + tok.Cmd = cmVAL; + tok.Val.ptr = nullptr; + tok.Val.data = 0; + tok.Val.data2 = a_fVal; + m_vRPN.push_back(tok); + } + + + void ParserByteCode::ConstantFolding(ECmdCode a_Oprt) + { + std::size_t sz = m_vRPN.size(); + value_type& x = m_vRPN[sz - 2].Val.data2; + value_type& y = m_vRPN[sz - 1].Val.data2; + + switch (a_Oprt) + { + case cmLAND: x = (int)x && (int)y; m_vRPN.pop_back(); break; + case cmLOR: x = (int)x || (int)y; m_vRPN.pop_back(); break; + case cmLT: x = x < y; m_vRPN.pop_back(); break; + case cmGT: x = x > y; m_vRPN.pop_back(); break; + case cmLE: x = x <= y; m_vRPN.pop_back(); break; + case cmGE: x = x >= y; m_vRPN.pop_back(); break; + case cmNEQ: x = x != y; m_vRPN.pop_back(); break; + case cmEQ: x = x == y; m_vRPN.pop_back(); break; + case cmADD: x = x + y; m_vRPN.pop_back(); break; + case cmSUB: x = x - y; m_vRPN.pop_back(); break; + case cmMUL: x = x * y; m_vRPN.pop_back(); break; + case cmDIV: + x = x / y; + m_vRPN.pop_back(); + break; + + case cmPOW: x = MathImpl::Pow(x, y); + m_vRPN.pop_back(); + break; + + default: + break; + } // switch opcode + } + + + /** \brief Add an operator identifier to bytecode. + + Operator entries in byte code consist of: +
    +
  • value array position of the result
  • +
  • the operator code according to ParserToken::ECmdCode
  • +
+ + \sa ParserToken::ECmdCode + */ + void ParserByteCode::AddOp(ECmdCode a_Oprt) + { + bool bOptimized = false; + + if (m_bEnableOptimizer) + { + std::size_t sz = m_vRPN.size(); + + // Check for foldable constants like: + // cmVAL cmVAL cmADD + // where cmADD can stand fopr any binary operator applied to + // two constant values. + if (sz >= 2 && m_vRPN[sz - 2].Cmd == cmVAL && m_vRPN[sz - 1].Cmd == cmVAL) + { + ConstantFolding(a_Oprt); + bOptimized = true; + } + else + { + switch (a_Oprt) + { + case cmPOW: + // Optimization for polynomials of low order + if (m_vRPN[sz - 2].Cmd == cmVAR && m_vRPN[sz - 1].Cmd == cmVAL) + { + if (m_vRPN[sz - 1].Val.data2 == 0) + { + m_vRPN[sz - 2].Cmd = cmVAL; + m_vRPN[sz - 2].Val.ptr = nullptr; + m_vRPN[sz - 2].Val.data = 0; + m_vRPN[sz - 2].Val.data2 = 1; + } + else if (m_vRPN[sz - 1].Val.data2 == 1) + m_vRPN[sz - 2].Cmd = cmVAR; + else if (m_vRPN[sz - 1].Val.data2 == 2) + m_vRPN[sz - 2].Cmd = cmVARPOW2; + else if (m_vRPN[sz - 1].Val.data2 == 3) + m_vRPN[sz - 2].Cmd = cmVARPOW3; + else if (m_vRPN[sz - 1].Val.data2 == 4) + m_vRPN[sz - 2].Cmd = cmVARPOW4; + else + break; + + m_vRPN.pop_back(); + bOptimized = true; + } + break; + + case cmSUB: + case cmADD: + // Simple optimization based on pattern recognition for a shitload of different + // bytecode combinations of addition/subtraction + if ((m_vRPN[sz - 1].Cmd == cmVAR && m_vRPN[sz - 2].Cmd == cmVAL) || + (m_vRPN[sz - 1].Cmd == cmVAL && m_vRPN[sz - 2].Cmd == cmVAR) || + (m_vRPN[sz - 1].Cmd == cmVAL && m_vRPN[sz - 2].Cmd == cmVARMUL) || + (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd == cmVAL) || + (m_vRPN[sz - 1].Cmd == cmVAR && m_vRPN[sz - 2].Cmd == cmVAR && m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr) || + (m_vRPN[sz - 1].Cmd == cmVAR && m_vRPN[sz - 2].Cmd == cmVARMUL && m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr) || + (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd == cmVAR && m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr) || + (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd == cmVARMUL && m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr)) + { + MUP_ASSERT( + (m_vRPN[sz - 2].Val.ptr == nullptr && m_vRPN[sz - 1].Val.ptr != nullptr) || + (m_vRPN[sz - 2].Val.ptr != nullptr && m_vRPN[sz - 1].Val.ptr == nullptr) || + (m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr)); + + m_vRPN[sz - 2].Cmd = cmVARMUL; + m_vRPN[sz - 2].Val.ptr = (value_type*)((long long)(m_vRPN[sz - 2].Val.ptr) | (long long)(m_vRPN[sz - 1].Val.ptr)); // variable + m_vRPN[sz - 2].Val.data2 += ((a_Oprt == cmSUB) ? -1 : 1) * m_vRPN[sz - 1].Val.data2; // offset + m_vRPN[sz - 2].Val.data += ((a_Oprt == cmSUB) ? -1 : 1) * m_vRPN[sz - 1].Val.data; // multiplicand + m_vRPN.pop_back(); + bOptimized = true; + } + break; + + case cmMUL: + if ((m_vRPN[sz - 1].Cmd == cmVAR && m_vRPN[sz - 2].Cmd == cmVAL) || + (m_vRPN[sz - 1].Cmd == cmVAL && m_vRPN[sz - 2].Cmd == cmVAR)) + { + m_vRPN[sz - 2].Cmd = cmVARMUL; + m_vRPN[sz - 2].Val.ptr = (value_type*)((long long)(m_vRPN[sz - 2].Val.ptr) | (long long)(m_vRPN[sz - 1].Val.ptr)); + m_vRPN[sz - 2].Val.data = m_vRPN[sz - 2].Val.data2 + m_vRPN[sz - 1].Val.data2; + m_vRPN[sz - 2].Val.data2 = 0; + m_vRPN.pop_back(); + bOptimized = true; + } + else if ( + (m_vRPN[sz - 1].Cmd == cmVAL && m_vRPN[sz - 2].Cmd == cmVARMUL) || + (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd == cmVAL)) + { + // Optimization: 2*(3*b+1) or (3*b+1)*2 -> 6*b+2 + m_vRPN[sz - 2].Cmd = cmVARMUL; + m_vRPN[sz - 2].Val.ptr = (value_type*)((long long)(m_vRPN[sz - 2].Val.ptr) | (long long)(m_vRPN[sz - 1].Val.ptr)); + if (m_vRPN[sz - 1].Cmd == cmVAL) + { + m_vRPN[sz - 2].Val.data *= m_vRPN[sz - 1].Val.data2; + m_vRPN[sz - 2].Val.data2 *= m_vRPN[sz - 1].Val.data2; + } + else + { + m_vRPN[sz - 2].Val.data = m_vRPN[sz - 1].Val.data * m_vRPN[sz - 2].Val.data2; + m_vRPN[sz - 2].Val.data2 = m_vRPN[sz - 1].Val.data2 * m_vRPN[sz - 2].Val.data2; + } + m_vRPN.pop_back(); + bOptimized = true; + } + else if ( + m_vRPN[sz - 1].Cmd == cmVAR && m_vRPN[sz - 2].Cmd == cmVAR && + m_vRPN[sz - 1].Val.ptr == m_vRPN[sz - 2].Val.ptr) + { + // Optimization: a*a -> a^2 + m_vRPN[sz - 2].Cmd = cmVARPOW2; + m_vRPN.pop_back(); + bOptimized = true; + } + break; + + case cmDIV: + if (m_vRPN[sz - 1].Cmd == cmVAL && m_vRPN[sz - 2].Cmd == cmVARMUL && m_vRPN[sz - 1].Val.data2 != 0) + { + // Optimization: 4*a/2 -> 2*a + m_vRPN[sz - 2].Val.data /= m_vRPN[sz - 1].Val.data2; + m_vRPN[sz - 2].Val.data2 /= m_vRPN[sz - 1].Val.data2; + m_vRPN.pop_back(); + bOptimized = true; + } + break; + + // no optimization for other opcodes + default: + break; + } // switch a_Oprt + } + } + + // If optimization can't be applied just write the value + if (!bOptimized) + { + --m_iStackPos; + SToken tok; + tok.Cmd = a_Oprt; + m_vRPN.push_back(tok); + } + } + + + void ParserByteCode::AddIfElse(ECmdCode a_Oprt) + { + SToken tok; + tok.Cmd = a_Oprt; + m_vRPN.push_back(tok); + } + + + /** \brief Add an assignment operator + + Operator entries in byte code consist of: +
    +
  • cmASSIGN code
  • +
  • the pointer of the destination variable
  • +
+ + \sa ParserToken::ECmdCode + */ + void ParserByteCode::AddAssignOp(value_type* a_pVar) + { + --m_iStackPos; + + SToken tok; + tok.Cmd = cmASSIGN; + tok.Oprt.ptr = a_pVar; + m_vRPN.push_back(tok); + } + + + /** \brief Add function to bytecode. + + \param a_iArgc Number of arguments, negative numbers indicate multiarg functions. + \param a_pFun Pointer to function callback. + */ + void ParserByteCode::AddFun(generic_callable_type a_pFun, int a_iArgc, bool isFunctionOptimizable) + { + std::size_t sz = m_vRPN.size(); + bool optimize = false; + + // only optimize functions with fixed number of more than a single arguments + if (isFunctionOptimizable && m_bEnableOptimizer && a_iArgc > 0) + { + // Unary Plus is a no-op + if (a_pFun == generic_callable_type{(erased_fun_type)&MathImpl::UnaryPlus, nullptr}) + return; + + optimize = true; + + for (int i = 0; i < std::abs(a_iArgc); ++i) + { + if (m_vRPN[sz - i - 1].Cmd != cmVAL) + { + optimize = false; + break; + } + } + } + + if (optimize) + { + value_type val = 0; + switch (a_iArgc) + { + case 1: val = a_pFun.call_fun<1>(m_vRPN[sz - 1].Val.data2); break; + case 2: val = a_pFun.call_fun<2>(m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2); break; + case 3: val = a_pFun.call_fun<3>(m_vRPN[sz - 3].Val.data2, m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2); break; + case 4: val = a_pFun.call_fun<4>(m_vRPN[sz - 4].Val.data2, m_vRPN[sz - 3].Val.data2, m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2); break; + case 5: val = a_pFun.call_fun<5>(m_vRPN[sz - 5].Val.data2, m_vRPN[sz - 4].Val.data2, m_vRPN[sz - 3].Val.data2, m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2); break; + case 6: val = a_pFun.call_fun<6>(m_vRPN[sz - 6].Val.data2, m_vRPN[sz - 5].Val.data2, m_vRPN[sz - 4].Val.data2, m_vRPN[sz - 3].Val.data2, m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2); break; + case 7: val = a_pFun.call_fun<7>(m_vRPN[sz - 7].Val.data2, m_vRPN[sz - 6].Val.data2, m_vRPN[sz - 5].Val.data2, m_vRPN[sz - 4].Val.data2, m_vRPN[sz - 3].Val.data2, m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2); break; + case 8: val = a_pFun.call_fun<8>(m_vRPN[sz - 8].Val.data2, m_vRPN[sz - 7].Val.data2, m_vRPN[sz - 6].Val.data2, m_vRPN[sz - 5].Val.data2, m_vRPN[sz - 4].Val.data2, m_vRPN[sz - 3].Val.data2, m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2); break; + case 9: val = a_pFun.call_fun<9>(m_vRPN[sz - 9].Val.data2, m_vRPN[sz - 8].Val.data2, m_vRPN[sz - 7].Val.data2, m_vRPN[sz - 6].Val.data2, m_vRPN[sz - 5].Val.data2, m_vRPN[sz - 4].Val.data2, m_vRPN[sz - 3].Val.data2, m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2); break; + case 10: val = a_pFun.call_fun<10>(m_vRPN[sz - 10].Val.data2, m_vRPN[sz - 9].Val.data2, m_vRPN[sz - 8].Val.data2, m_vRPN[sz - 7].Val.data2, m_vRPN[sz - 6].Val.data2, m_vRPN[sz - 5].Val.data2, m_vRPN[sz - 4].Val.data2, m_vRPN[sz - 3].Val.data2, m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2); break; + default: + // For now functions with unlimited number of arguments are not optimized + throw ParserError(ecINTERNAL_ERROR); + } + + // remove the folded values + m_vRPN.erase(m_vRPN.end() - a_iArgc, m_vRPN.end()); + + SToken tok; + tok.Cmd = cmVAL; + tok.Val.data = 0; + tok.Val.data2 = val; + tok.Val.ptr = nullptr; + m_vRPN.push_back(tok); + } + else + { + SToken tok; + tok.Cmd = cmFUNC; + tok.Fun.argc = a_iArgc; + tok.Fun.cb = a_pFun; + m_vRPN.push_back(tok); + } + + m_iStackPos = m_iStackPos - std::abs(a_iArgc) + 1; + m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); + + } + + + /** \brief Add a bulk function to bytecode. + + \param a_iArgc Number of arguments, negative numbers indicate multiarg functions. + \param a_pFun Pointer to function callback. + */ + void ParserByteCode::AddBulkFun(generic_callable_type a_pFun, int a_iArgc) + { + m_iStackPos = m_iStackPos - a_iArgc + 1; + m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); + + SToken tok; + tok.Cmd = cmFUNC_BULK; + tok.Fun.argc = a_iArgc; + tok.Fun.cb = a_pFun; + m_vRPN.push_back(tok); + } + + + /** \brief Add Strung function entry to the parser bytecode. + \throw nothrow + + A string function entry consists of the stack position of the return value, + followed by a cmSTRFUNC code, the function pointer and an index into the + string buffer maintained by the parser. + */ + void ParserByteCode::AddStrFun(generic_callable_type a_pFun, int a_iArgc, int a_iIdx) + { + m_iStackPos = m_iStackPos - a_iArgc + 1; + + SToken tok; + tok.Cmd = cmFUNC_STR; + tok.Fun.argc = a_iArgc; + tok.Fun.idx = a_iIdx; + tok.Fun.cb = a_pFun; + m_vRPN.push_back(tok); + + m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); + } + + + /** \brief Add end marker to bytecode. + + \throw nothrow + */ + void ParserByteCode::Finalize() + { + SToken tok; + tok.Cmd = cmEND; + m_vRPN.push_back(tok); + rpn_type(m_vRPN).swap(m_vRPN); // shrink bytecode vector to fit + + // Determine the if-then-else jump offsets + std::stack stIf, stElse; + int idx; + for (int i = 0; i < (int)m_vRPN.size(); ++i) + { + switch (m_vRPN[i].Cmd) + { + case cmIF: + stIf.push(i); + break; + + case cmELSE: + stElse.push(i); + idx = stIf.top(); + stIf.pop(); + m_vRPN[idx].Oprt.offset = i - idx; + break; + + case cmENDIF: + idx = stElse.top(); + stElse.pop(); + m_vRPN[idx].Oprt.offset = i - idx; + break; + + default: + break; + } + } + } + + + std::size_t ParserByteCode::GetMaxStackSize() const + { + return m_iMaxStackSize + 1; + } + + + /** \brief Delete the bytecode. + + \throw nothrow + + The name of this function is a violation of my own coding guidelines + but this way it's more in line with the STL functions thus more + intuitive. + */ + void ParserByteCode::clear() + { + m_vRPN.clear(); + m_iStackPos = 0; + m_iMaxStackSize = 0; + } + + + /** \brief Dump bytecode (for debugging only!). */ + void ParserByteCode::AsciiDump() const + { + if (!m_vRPN.size()) + { + mu::console() << _T("No bytecode available\n"); + return; + } + + mu::console() << _T("Number of RPN tokens:") << (int)m_vRPN.size() << _T("\n"); + for (std::size_t i = 0; i < m_vRPN.size() && m_vRPN[i].Cmd != cmEND; ++i) + { + mu::console() << std::dec << i << _T(" : \t"); + switch (m_vRPN[i].Cmd) + { + case cmVAL: mu::console() << _T("VAL \t"); + mu::console() << _T("[") << m_vRPN[i].Val.data2 << _T("]\n"); + break; + + case cmVAR: mu::console() << _T("VAR \t"); + mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n"); + break; + + case cmVARPOW2: mu::console() << _T("VARPOW2 \t"); + mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n"); + break; + + case cmVARPOW3: mu::console() << _T("VARPOW3 \t"); + mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n"); + break; + + case cmVARPOW4: mu::console() << _T("VARPOW4 \t"); + mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n"); + break; + + case cmVARMUL: mu::console() << _T("VARMUL \t"); + mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]"); + mu::console() << _T(" * [") << m_vRPN[i].Val.data << _T("]"); + mu::console() << _T(" + [") << m_vRPN[i].Val.data2 << _T("]\n"); + break; + + case cmFUNC: mu::console() << _T("CALL\t"); + mu::console() << _T("[ARG:") << std::dec << m_vRPN[i].Fun.argc << _T("]"); + mu::console() << _T("[ADDR: 0x") << std::hex << reinterpret_cast(m_vRPN[i].Fun.cb._pRawFun) << _T("]"); + mu::console() << _T("[USERDATA: 0x") << std::hex << reinterpret_cast(m_vRPN[i].Fun.cb._pUserData) << _T("]"); + mu::console() << _T("\n"); + break; + + case cmFUNC_STR: + mu::console() << _T("CALL STRFUNC\t"); + mu::console() << _T("[ARG:") << std::dec << m_vRPN[i].Fun.argc << _T("]"); + mu::console() << _T("[IDX:") << std::dec << m_vRPN[i].Fun.idx << _T("=\"") << m_stringBuffer[m_vRPN[i].Fun.idx] << ("\"]"); + mu::console() << _T("[ADDR: 0x") << std::hex << reinterpret_cast(m_vRPN[i].Fun.cb._pRawFun) << _T("]"); + mu::console() << _T("[USERDATA: 0x") << std::hex << reinterpret_cast(m_vRPN[i].Fun.cb._pUserData) << _T("]"); + mu::console() << _T("\n"); + break; + + case cmLT: mu::console() << _T("LT\n"); break; + case cmGT: mu::console() << _T("GT\n"); break; + case cmLE: mu::console() << _T("LE\n"); break; + case cmGE: mu::console() << _T("GE\n"); break; + case cmEQ: mu::console() << _T("EQ\n"); break; + case cmNEQ: mu::console() << _T("NEQ\n"); break; + case cmADD: mu::console() << _T("ADD\n"); break; + case cmLAND: mu::console() << _T("&&\n"); break; + case cmLOR: mu::console() << _T("||\n"); break; + case cmSUB: mu::console() << _T("SUB\n"); break; + case cmMUL: mu::console() << _T("MUL\n"); break; + case cmDIV: mu::console() << _T("DIV\n"); break; + case cmPOW: mu::console() << _T("POW\n"); break; + + case cmIF: mu::console() << _T("IF\t"); + mu::console() << _T("[OFFSET:") << std::dec << m_vRPN[i].Oprt.offset << _T("]\n"); + break; + + case cmELSE: mu::console() << _T("ELSE\t"); + mu::console() << _T("[OFFSET:") << std::dec << m_vRPN[i].Oprt.offset << _T("]\n"); + break; + + case cmENDIF: mu::console() << _T("ENDIF\n"); break; + + case cmASSIGN: + mu::console() << _T("ASSIGN\t"); + mu::console() << _T("[ADDR: 0x") << m_vRPN[i].Oprt.ptr << _T("]\n"); + break; + + default: mu::console() << _T("(unknown code: ") << m_vRPN[i].Cmd << _T(")\n"); + break; + } // switch cmdCode + } // while bytecode + + mu::console() << _T("END") << std::endl; + } +} // namespace mu + +#if defined(_MSC_VER) + #pragma warning(pop) +#endif diff --git a/3rdparty/muparser/muParserBytecode.h b/3rdparty/muparser/muParserBytecode.h index 39ab39d5..3196aac2 100644 --- a/3rdparty/muparser/muParserBytecode.h +++ b/3rdparty/muparser/muParserBytecode.h @@ -1,141 +1,172 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2004-2013 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -#ifndef MU_PARSER_BYTECODE_H -#define MU_PARSER_BYTECODE_H - -#include -#include -#include -#include - -#include "muParserDef.h" -#include "muParserError.h" -#include "muParserToken.h" - -/** \file - \brief Definition of the parser bytecode class. -*/ - - -namespace mu -{ - struct SToken - { - ECmdCode Cmd; - int StackPos; - - union - { - struct //SValData - { - value_type *ptr; - value_type data; - value_type data2; - } Val; - - struct //SFunData - { - // Note: generic_fun_type is merely a placeholder. The real type could be - // anything between gun_type1 and fun_type9. I can't use a void - // pointer due to constraints in the ANSI standard which allows - // data pointers and function pointers to differ in size. - generic_fun_type ptr; - int argc; - int idx; - } Fun; - - struct //SOprtData - { - value_type *ptr; - int offset; - } Oprt; - }; - }; - - - /** \brief Bytecode implementation of the Math Parser. - - The bytecode contains the formula converted to revers polish notation stored in a continious - memory area. Associated with this data are operator codes, variable pointers, constant - values and function pointers. Those are necessary in order to calculate the result. - All those data items will be casted to the underlying datatype of the bytecode. - - \author (C) 2004-2013 Ingo Berg -*/ -class ParserByteCode -{ -private: - - /** \brief Token type for internal use only. */ - typedef ParserToken token_type; - - /** \brief Token vector for storing the RPN. */ - typedef std::vector rpn_type; - - /** \brief Position in the Calculation array. */ - unsigned m_iStackPos; - - /** \brief Maximum size needed for the stack. */ - std::size_t m_iMaxStackSize; - - /** \brief The actual rpn storage. */ - rpn_type m_vRPN; - - bool m_bEnableOptimizer; - - void ConstantFolding(ECmdCode a_Oprt); - -public: - - ParserByteCode(); - ParserByteCode(const ParserByteCode &a_ByteCode); - ParserByteCode& operator=(const ParserByteCode &a_ByteCode); - void Assign(const ParserByteCode &a_ByteCode); - - void AddVar(value_type *a_pVar); - void AddVal(value_type a_fVal); - void AddOp(ECmdCode a_Oprt); - void AddIfElse(ECmdCode a_Oprt); - void AddAssignOp(value_type *a_pVar); - void AddFun(generic_fun_type a_pFun, int a_iArgc); - void AddBulkFun(generic_fun_type a_pFun, int a_iArgc); - void AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx); - - void EnableOptimizer(bool bStat); - - void Finalize(); - void clear(); - std::size_t GetMaxStackSize() const; - std::size_t GetSize() const; - - const SToken* GetBase() const; - void AsciiDump(); -}; - -} // namespace mu - -#endif - - +/* + + _____ __ _____________ _______ ______ ___________ + / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ + | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ + |__|_| /____/| __(____ /__| /____ >\___ >__| + \/ |__| \/ \/ \/ + Copyright (C) 2004 - 2022 Ingo Berg + + Redistribution and use in source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef MU_PARSER_BYTECODE_H +#define MU_PARSER_BYTECODE_H + +#include +#include +#include + +#include "muParserDef.h" +#include "muParserError.h" +#include "muParserToken.h" + +/** \file + \brief Definition of the parser bytecode class. +*/ + + +namespace mu +{ + struct SToken + { + ECmdCode Cmd; + + union + { + struct // SValData + { + value_type* ptr; + value_type data; + value_type data2; + } Val; + + struct // SFunData + { + // Note: the type is erased in generic_callable_type and the signature of the + // function to call is tracked elsewhere in regard with the number of + // parameters (args) and the general kind of function (Cmd: cmFUNC, + // cmFUNC_STR, or cmFUNC_BULK) + generic_callable_type cb; + int argc; + int idx; + } Fun; + + struct // SOprtData + { + value_type* ptr; + int offset; + } Oprt; + }; + }; + + + /** \brief Bytecode implementation of the Math Parser. + + The bytecode contains the formula converted to revers polish notation stored in a continious + memory area. Associated with this data are operator codes, variable pointers, constant + values and function pointers. Those are necessary in order to calculate the result. + All those data items will be casted to the underlying datatype of the bytecode. + */ + class API_EXPORT_CXX ParserByteCode final + { + private: + + /** \brief Token type for internal use only. */ + typedef ParserToken token_type; + + /** \brief Token vector for storing the RPN. */ + typedef std::vector rpn_type; + + /** \brief Type for a vector of strings. */ + typedef std::vector stringbuf_type; + + /** \brief Position in the Calculation array. */ + unsigned m_iStackPos; + + /** \brief String variable storage. */ + stringbuf_type m_stringBuffer; + + /** \brief The expression associated with this bytecode. */ + string_type m_expr; + + /** \brief Maximum size needed for the stack. */ + std::size_t m_iMaxStackSize; + + /** \brief The actual rpn storage. */ + rpn_type m_vRPN; + + bool m_bEnableOptimizer; + + void ConstantFolding(ECmdCode a_Oprt); + + public: + + ParserByteCode(); + ParserByteCode(const ParserByteCode& a_ByteCode); + ParserByteCode& operator=(const ParserByteCode& a_ByteCode); + void Assign(const ParserByteCode& a_ByteCode); + + void AddVar(value_type* a_pVar); + void AddVal(value_type a_fVal); + void AddOp(ECmdCode a_Oprt); + void AddIfElse(ECmdCode a_Oprt); + void AddAssignOp(value_type* a_pVar); + void AddFun(generic_callable_type a_pFun, int a_iArgc, bool isOptimizable); + void AddBulkFun(generic_callable_type a_pFun, int a_iArgc); + void AddStrFun(generic_callable_type a_pFun, int a_iArgc, int a_iIdx); + + void EnableOptimizer(bool bStat); + + void Finalize(); + void clear(); + std::size_t GetMaxStackSize() const; + + std::size_t GetSize() const + { + return m_vRPN.size(); + } + + inline const SToken* GetBase() const + { + if (m_vRPN.size() == 0) + throw ParserError(ecINTERNAL_ERROR); + else + return &m_vRPN[0]; + } + + void StoreEnvironment(string_type expr, stringbuf_type const& strBuf) + { + m_stringBuffer = strBuf; + m_expr = expr; + } + + std::tuple RestoreEnvironment() const + { + return std::make_tuple(m_expr, m_stringBuffer); + } + + void AsciiDump() const; + }; + +} // namespace mu + +#endif + + diff --git a/3rdparty/muparser/muParserCallback.cpp b/3rdparty/muparser/muParserCallback.cpp index 2044fe1c..8f2265b2 100644 --- a/3rdparty/muparser/muParserCallback.cpp +++ b/3rdparty/muparser/muParserCallback.cpp @@ -1,463 +1,894 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2004-2011 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "muParserCallback.h" - -/** \file - \brief Implementation of the parser callback class. -*/ - - -namespace mu -{ - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type0 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(0) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec, ECmdCode a_iCode) - :m_pFun((void*)a_pFun) - ,m_iArgc(1) - ,m_iPri(a_iPrec) - ,m_eOprtAsct(oaNONE) - ,m_iCode(a_iCode) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - /** \brief Constructor for constructing function callbacks taking two arguments. - \throw nothrow - */ - ParserCallback::ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(2) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - /** \brief Constructor for constructing binary operator callbacks. - \param a_pFun Pointer to a static function taking two arguments - \param a_bAllowOpti A flag indicating this function can be optimized - \param a_iPrec The operator precedence - \param a_eOprtAsct The operators associativity - \throw nothrow - */ - ParserCallback::ParserCallback(fun_type2 a_pFun, - bool a_bAllowOpti, - int a_iPrec, - EOprtAssociativity a_eOprtAsct) - :m_pFun((void*)a_pFun) - ,m_iArgc(2) - ,m_iPri(a_iPrec) - ,m_eOprtAsct(a_eOprtAsct) - ,m_iCode(cmOPRT_BIN) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type3 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(3) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type4 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(4) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type5 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(5) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type6 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(6) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type7 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(7) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type8 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(8) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type9 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(9) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(10) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type0 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(0) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type1 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(1) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - /** \brief Constructor for constructing function callbacks taking two arguments. - \throw nothrow - */ - ParserCallback::ParserCallback(bulkfun_type2 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(2) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type3 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(3) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type4 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(4) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type5 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(5) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type6 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(6) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type7 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(7) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type8 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(8) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type9 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(9) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(10) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(multfun_type a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(-1) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(0) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_STR) - ,m_iType(tpSTR) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(1) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_STR) - ,m_iType(tpSTR) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(2) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_STR) - ,m_iType(tpSTR) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - /** \brief Default constructor. - \throw nothrow - */ - ParserCallback::ParserCallback() - :m_pFun(0) - ,m_iArgc(0) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmUNKNOWN) - ,m_iType(tpVOID) - ,m_bAllowOpti(0) - {} - - - //--------------------------------------------------------------------------- - /** \brief Copy constructor. - \throw nothrow - */ - ParserCallback::ParserCallback(const ParserCallback &ref) - { - m_pFun = ref.m_pFun; - m_iArgc = ref.m_iArgc; - m_bAllowOpti = ref.m_bAllowOpti; - m_iCode = ref.m_iCode; - m_iType = ref.m_iType; - m_iPri = ref.m_iPri; - m_eOprtAsct = ref.m_eOprtAsct; - } - - //--------------------------------------------------------------------------- - /** \brief Clone this instance and return a pointer to the new instance. */ - ParserCallback* ParserCallback::Clone() const - { - return new ParserCallback(*this); - } - - //--------------------------------------------------------------------------- - /** \brief Return tru if the function is conservative. - - Conservative functions return always the same result for the same argument. - \throw nothrow - */ - bool ParserCallback::IsOptimizable() const - { - return m_bAllowOpti; - } - - //--------------------------------------------------------------------------- - /** \brief Get the callback address for the parser function. - - The type of the address is void. It needs to be recasted according to the - argument number to the right type. - - \throw nothrow - \return #pFun - */ - void* ParserCallback::GetAddr() const - { - return m_pFun; - } - - //--------------------------------------------------------------------------- - /** \brief Return the callback code. */ - ECmdCode ParserCallback::GetCode() const - { - return m_iCode; - } - - //--------------------------------------------------------------------------- - ETypeCode ParserCallback::GetType() const - { - return m_iType; - } - - - //--------------------------------------------------------------------------- - /** \brief Return the operator precedence. - \throw nothrown - - Only valid if the callback token is an operator token (binary or infix). - */ - int ParserCallback::GetPri() const - { - return m_iPri; - } - - //--------------------------------------------------------------------------- - /** \brief Return the operators associativity. - \throw nothrown - - Only valid if the callback token is a binary operator token. - */ - EOprtAssociativity ParserCallback::GetAssociativity() const - { - return m_eOprtAsct; - } - - //--------------------------------------------------------------------------- - /** \brief Returns the number of function Arguments. */ - int ParserCallback::GetArgc() const - { - return m_iArgc; - } -} // namespace mu +/* + + _____ __ _____________ _______ ______ ___________ + / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ + | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ + |__|_| /____/| __(____ /__| /____ >\___ >__| + \/ |__| \/ \/ \/ + Copyright (C) 2022 Ingo Berg + + Redistribution and use in source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "muParserCallback.h" + +#if defined(_MSC_VER) + #pragma warning(push) + #pragma warning(disable : 26812) +#endif + +/** \file + \brief Implementation of the parser callback class. +*/ + + +namespace mu +{ + static constexpr int CALLBACK_INTERNAL_VAR_ARGS = 1 << 14; + static constexpr int CALLBACK_INTERNAL_FIXED_ARGS_MASK = 0xf; + static constexpr int CALLBACK_INTERNAL_WITH_USER_DATA = 1 << 13; + + struct CbWithUserData + { + void* pFun; + void* pUserData; + }; + + + ParserCallback::ParserCallback(fun_type0 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(0) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec, ECmdCode a_iCode) + :m_pFun((void*)a_pFun) + , m_iArgc(1) + , m_iPri(a_iPrec) + , m_eOprtAsct(oaNONE) + , m_iCode(a_iCode) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti) + : ParserCallback(a_pFun, a_bAllowOpti, -1, cmFUNC) + {} + + + /** \brief Constructor for constructing function callbacks taking two arguments. + \throw nothrow + */ + ParserCallback::ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(2) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + /** \brief Constructor for constructing binary operator callbacks. + \param a_pFun Pointer to a static function taking two arguments + \param a_bAllowOpti A flag indicating this function can be optimized + \param a_iPrec The operator precedence + \param a_eOprtAsct The operators associativity + \throw nothrow + */ + ParserCallback::ParserCallback(fun_type2 a_pFun, + bool a_bAllowOpti, + int a_iPrec, + EOprtAssociativity a_eOprtAsct) + :m_pFun((void*)a_pFun) + , m_iArgc(2) + , m_iPri(a_iPrec) + , m_eOprtAsct(a_eOprtAsct) + , m_iCode(cmOPRT_BIN) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(fun_type3 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(3) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(fun_type4 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(4) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(fun_type5 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(5) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(fun_type6 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(6) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(fun_type7 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(7) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(fun_type8 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(8) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(fun_type9 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(9) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(10) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(fun_userdata_type0 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(0 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(fun_userdata_type1 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(1 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(fun_userdata_type2 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(2 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(fun_userdata_type3 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(3 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(fun_userdata_type4 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(4 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(fun_userdata_type5 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(5 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(fun_userdata_type6 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(6 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(fun_userdata_type7 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(7 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(fun_userdata_type8 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(8 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(fun_userdata_type9 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(9 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(fun_userdata_type10 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(10 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(bulkfun_type0 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(0) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_BULK) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(bulkfun_type1 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(1) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_BULK) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + /** \brief Constructor for constructing function callbacks taking two arguments. + \throw nothrow + */ + ParserCallback::ParserCallback(bulkfun_type2 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(2) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_BULK) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(bulkfun_type3 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(3) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_BULK) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(bulkfun_type4 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(4) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_BULK) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(bulkfun_type5 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(5) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_BULK) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(bulkfun_type6 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(6) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_BULK) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(bulkfun_type7 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(7) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_BULK) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(bulkfun_type8 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(8) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_BULK) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(bulkfun_type9 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(9) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_BULK) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(10) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_BULK) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(bulkfun_userdata_type0 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(0 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_BULK) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(bulkfun_userdata_type1 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(1 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_BULK) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(bulkfun_userdata_type2 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(2 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_BULK) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(bulkfun_userdata_type3 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(3 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_BULK) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(bulkfun_userdata_type4 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(4 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_BULK) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(bulkfun_userdata_type5 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(5 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_BULK) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(bulkfun_userdata_type6 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(6 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_BULK) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(bulkfun_userdata_type7 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(7 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_BULK) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(bulkfun_userdata_type8 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(8 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_BULK) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(bulkfun_userdata_type9 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(9 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_BULK) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(bulkfun_userdata_type10 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(10 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_BULK) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(multfun_type a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(CALLBACK_INTERNAL_VAR_ARGS) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(multfun_userdata_type a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(CALLBACK_INTERNAL_VAR_ARGS | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC) + , m_iType(tpDBL) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(0) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_STR) + , m_iType(tpSTR) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(1) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_STR) + , m_iType(tpSTR) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(2) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_STR) + , m_iType(tpSTR) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(strfun_type4 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(3) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_STR) + , m_iType(tpSTR) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(strfun_type5 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(4) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_STR) + , m_iType(tpSTR) + , m_bAllowOpti(a_bAllowOpti) + {} + + ParserCallback::ParserCallback(strfun_type6 a_pFun, bool a_bAllowOpti) + :m_pFun((void*)a_pFun) + , m_iArgc(5) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_STR) + , m_iType(tpSTR) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(strfun_userdata_type1 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(0 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_STR) + , m_iType(tpSTR) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(strfun_userdata_type2 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(1 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_STR) + , m_iType(tpSTR) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(strfun_userdata_type3 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(2 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_STR) + , m_iType(tpSTR) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(strfun_userdata_type4 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(3 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_STR) + , m_iType(tpSTR) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(strfun_userdata_type5 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{reinterpret_cast(a_pFun), a_pUserData}) + , m_iArgc(4 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_STR) + , m_iType(tpSTR) + , m_bAllowOpti(a_bAllowOpti) + {} + + + ParserCallback::ParserCallback(strfun_userdata_type6 a_pFun, void* a_pUserData, bool a_bAllowOpti) + :m_pFun(new CbWithUserData{ reinterpret_cast(a_pFun), a_pUserData }) + , m_iArgc(5 | CALLBACK_INTERNAL_WITH_USER_DATA) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmFUNC_STR) + , m_iType(tpSTR) + , m_bAllowOpti(a_bAllowOpti) + {} + + /** \brief Default constructor. + \throw nothrow + */ + ParserCallback::ParserCallback() + :m_pFun(0) + , m_iArgc(0) + , m_iPri(-1) + , m_eOprtAsct(oaNONE) + , m_iCode(cmUNKNOWN) + , m_iType(tpVOID) + , m_bAllowOpti(0) + {} + + + /** \brief Copy constructor. + \throw nothrow + */ + ParserCallback::ParserCallback(const ParserCallback& ref) + :ParserCallback() + { + Assign(ref); + } + + ParserCallback & ParserCallback::operator=(const ParserCallback & ref) + { + Assign(ref); + return *this; + } + + + ParserCallback::~ParserCallback() + { + if (m_iArgc & CALLBACK_INTERNAL_WITH_USER_DATA) + delete reinterpret_cast(m_pFun); + } + + + /** \brief Copy callback from argument. + + \throw nothrow + */ + void ParserCallback::Assign(const ParserCallback& ref) + { + if (this == &ref) + return; + + if (m_iArgc & CALLBACK_INTERNAL_WITH_USER_DATA) { + delete reinterpret_cast(m_pFun); + m_pFun = nullptr; + } + + if (ref.m_iArgc & CALLBACK_INTERNAL_WITH_USER_DATA) + m_pFun = new CbWithUserData(*reinterpret_cast(ref.m_pFun)); + else + m_pFun = ref.m_pFun; + m_iArgc = ref.m_iArgc; + m_bAllowOpti = ref.m_bAllowOpti; + m_iCode = ref.m_iCode; + m_iType = ref.m_iType; + m_iPri = ref.m_iPri; + m_eOprtAsct = ref.m_eOprtAsct; + } + + + /** \brief Clone this instance and return a pointer to the new instance. */ + ParserCallback* ParserCallback::Clone() const + { + return new ParserCallback(*this); + } + + + /** \brief Return tru if the function is conservative. + + Conservative functions return always the same result for the same argument. + \throw nothrow + */ + bool ParserCallback::IsOptimizable() const + { + return m_bAllowOpti; + } + + + /** \brief Get the callback address for the parser function. + + The type of the address is void. It needs to be recasted according to the + argument number to the right type. + + \throw nothrow + */ + void* ParserCallback::GetAddr() const + { + if (m_iArgc & CALLBACK_INTERNAL_WITH_USER_DATA) + return reinterpret_cast(m_pFun)->pFun; + else + return m_pFun; + } + + + /** \brief Get the user data if present, else nullptr + + \throw nothrow + */ + void* ParserCallback::GetUserData() const + { + if (m_iArgc & CALLBACK_INTERNAL_WITH_USER_DATA) + return reinterpret_cast(m_pFun)->pUserData; + else + return nullptr; + } + + + /** \brief Check that the callback looks valid + \throw nothrow + + Check that the function pointer is not null, + and if there are user data that they are not null. + */ + bool ParserCallback::IsValid() const + { + return GetAddr() != nullptr + && !((m_iArgc & CALLBACK_INTERNAL_WITH_USER_DATA) + && GetUserData() == nullptr); + } + + + /** \brief Return the callback code. */ + ECmdCode ParserCallback::GetCode() const + { + return m_iCode; + } + + + ETypeCode ParserCallback::GetType() const + { + return m_iType; + } + + + /** \brief Return the operator precedence. + \throw nothrown + + Only valid if the callback token is an operator token (binary or infix). + */ + int ParserCallback::GetPri() const + { + return m_iPri; + } + + + /** \brief Return the operators associativity. + \throw nothrown + + Only valid if the callback token is a binary operator token. + */ + EOprtAssociativity ParserCallback::GetAssociativity() const + { + return m_eOprtAsct; + } + + + /** \brief Returns the number of numeric function Arguments. + + This number is negative for functions with variable number of arguments. + */ + int ParserCallback::GetArgc() const + { + return (m_iArgc & CALLBACK_INTERNAL_VAR_ARGS) ? -1 : (m_iArgc & CALLBACK_INTERNAL_FIXED_ARGS_MASK); + } +} // namespace mu + +#if defined(_MSC_VER) + #pragma warning(pop) +#endif diff --git a/3rdparty/muparser/muParserCallback.h b/3rdparty/muparser/muParserCallback.h index ef32b498..1e53f14c 100644 --- a/3rdparty/muparser/muParserCallback.h +++ b/3rdparty/muparser/muParserCallback.h @@ -1,118 +1,161 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2004-2011 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef MU_PARSER_CALLBACK_H -#define MU_PARSER_CALLBACK_H - -#include "muParserDef.h" - -/** \file - \brief Definition of the parser callback class. -*/ - -namespace mu -{ - -/** \brief Encapsulation of prototypes for a numerical parser function. - - Encapsulates the prototyp for numerical parser functions. The class - stores the number of arguments for parser functions as well - as additional flags indication the function is non optimizeable. - The pointer to the callback function pointer is stored as void* - and needs to be casted according to the argument count. - Negative argument counts indicate a parser function with a variable number - of arguments. - - \author (C) 2004-2011 Ingo Berg -*/ -class ParserCallback -{ -public: - ParserCallback(fun_type0 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec = -1, ECmdCode a_iCode=cmFUNC); - ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti, int a_iPrec, EOprtAssociativity a_eAssociativity); - ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type3 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type4 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type5 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type6 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type7 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type8 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type9 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti); - - ParserCallback(bulkfun_type0 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type1 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type2 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type3 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type4 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type5 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type6 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type7 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type8 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type9 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti); - - ParserCallback(multfun_type a_pFun, bool a_bAllowOpti); - ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti); - ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti); - ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti); - ParserCallback(); - ParserCallback(const ParserCallback &a_Fun); - - ParserCallback* Clone() const; - - bool IsOptimizable() const; - void* GetAddr() const; - ECmdCode GetCode() const; - ETypeCode GetType() const; - int GetPri() const; - EOprtAssociativity GetAssociativity() const; - int GetArgc() const; - -private: - void *m_pFun; ///< Pointer to the callback function, casted to void - - /** \brief Number of numeric function arguments - - This number is negative for functions with variable number of arguments. in this cases - they represent the actual number of arguments found. - */ - int m_iArgc; - int m_iPri; ///< Valid only for binary and infix operators; Operator precedence. - EOprtAssociativity m_eOprtAsct; ///< Operator associativity; Valid only for binary operators - ECmdCode m_iCode; - ETypeCode m_iType; - bool m_bAllowOpti; ///< Flag indication optimizeability -}; - -//------------------------------------------------------------------------------ -/** \brief Container for Callback objects. */ -typedef std::map funmap_type; - -} // namespace mu - -#endif - +/* + + _____ __ _____________ _______ ______ ___________ + / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ + | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ + |__|_| /____/| __(____ /__| /____ >\___ >__| + \/ |__| \/ \/ \/ + Copyright (C) 2022 Ingo Berg + + Redistribution and use in source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef MU_PARSER_CALLBACK_H +#define MU_PARSER_CALLBACK_H + +#include "muParserDef.h" + +/** \file + \brief Definition of the parser callback class. +*/ + +namespace mu +{ + + /** \brief Encapsulation of prototypes for a numerical parser function. + + Encapsulates the prototyp for numerical parser functions. The class + stores the number of arguments for parser functions as well + as additional flags indication the function is non optimizeable. + The pointer to the callback function pointer is stored as void* + and needs to be casted according to the argument count. + Negative argument counts indicate a parser function with a variable number + of arguments. + */ + class API_EXPORT_CXX ParserCallback final + { + public: + ParserCallback(fun_type0 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec, ECmdCode a_iCode); + ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti, int a_iPrec, EOprtAssociativity a_eAssociativity); + ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type3 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type4 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type5 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type6 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type7 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type8 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type9 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti); + + ParserCallback(bulkfun_type0 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type1 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type2 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type3 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type4 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type5 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type6 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type7 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type8 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type9 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti); + + ParserCallback(multfun_type a_pFun, bool a_bAllowOpti); + + ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti); + ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti); + ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti); + ParserCallback(strfun_type4 a_pFun, bool a_bAllowOpti); + ParserCallback(strfun_type5 a_pFun, bool a_bAllowOpti); + ParserCallback(strfun_type6 a_pFun, bool a_bAllowOpti); + + // note: a_pUserData shall not be nullptr + ParserCallback(fun_userdata_type0 a_pFun, void* a_pUserData, bool a_bAllowOpti); + ParserCallback(fun_userdata_type1 a_pFun, void* a_pUserData, bool a_bAllowOpti); + ParserCallback(fun_userdata_type2 a_pFun, void* a_pUserData, bool a_bAllowOpti); + ParserCallback(fun_userdata_type3 a_pFun, void* a_pUserData, bool a_bAllowOpti); + ParserCallback(fun_userdata_type4 a_pFun, void* a_pUserData, bool a_bAllowOpti); + ParserCallback(fun_userdata_type5 a_pFun, void* a_pUserData, bool a_bAllowOpti); + ParserCallback(fun_userdata_type6 a_pFun, void* a_pUserData, bool a_bAllowOpti); + ParserCallback(fun_userdata_type7 a_pFun, void* a_pUserData, bool a_bAllowOpti); + ParserCallback(fun_userdata_type8 a_pFun, void* a_pUserData, bool a_bAllowOpti); + ParserCallback(fun_userdata_type9 a_pFun, void* a_pUserData, bool a_bAllowOpti); + ParserCallback(fun_userdata_type10 a_pFun, void* a_pUserData, bool a_bAllowOpti); + + ParserCallback(bulkfun_userdata_type0 a_pFun, void* a_pUserData, bool a_bAllowOpti); + ParserCallback(bulkfun_userdata_type1 a_pFun, void* a_pUserData, bool a_bAllowOpti); + ParserCallback(bulkfun_userdata_type2 a_pFun, void* a_pUserData, bool a_bAllowOpti); + ParserCallback(bulkfun_userdata_type3 a_pFun, void* a_pUserData, bool a_bAllowOpti); + ParserCallback(bulkfun_userdata_type4 a_pFun, void* a_pUserData, bool a_bAllowOpti); + ParserCallback(bulkfun_userdata_type5 a_pFun, void* a_pUserData, bool a_bAllowOpti); + ParserCallback(bulkfun_userdata_type6 a_pFun, void* a_pUserData, bool a_bAllowOpti); + ParserCallback(bulkfun_userdata_type7 a_pFun, void* a_pUserData, bool a_bAllowOpti); + ParserCallback(bulkfun_userdata_type8 a_pFun, void* a_pUserData, bool a_bAllowOpti); + ParserCallback(bulkfun_userdata_type9 a_pFun, void* a_pUserData, bool a_bAllowOpti); + ParserCallback(bulkfun_userdata_type10 a_pFun, void* a_pUserData, bool a_bAllowOpti); + + ParserCallback(multfun_userdata_type a_pFun, void* a_pUserData, bool a_bAllowOpti); + + ParserCallback(strfun_userdata_type1 a_pFun, void* a_pUserData, bool a_bAllowOpti); + ParserCallback(strfun_userdata_type2 a_pFun, void* a_pUserData, bool a_bAllowOpti); + ParserCallback(strfun_userdata_type3 a_pFun, void* a_pUserData, bool a_bAllowOpti); + ParserCallback(strfun_userdata_type4 a_pFun, void* a_pUserData, bool a_bAllowOpti); + ParserCallback(strfun_userdata_type5 a_pFun, void* a_pUserData, bool a_bAllowOpti); + ParserCallback(strfun_userdata_type6 a_pFun, void* a_pUserData, bool a_bAllowOpti); + + ParserCallback(); + ParserCallback(const ParserCallback& a_Fun); + ParserCallback & operator=(const ParserCallback& a_Fun); + ~ParserCallback(); + + ParserCallback* Clone() const; + + bool IsOptimizable() const; + bool IsValid() const; + void* GetAddr() const; + void* GetUserData() const; + ECmdCode GetCode() const; + ETypeCode GetType() const; + int GetPri() const; + EOprtAssociativity GetAssociativity() const; + int GetArgc() const; + + private: + void Assign(const ParserCallback& ref); + + void* m_pFun; ///< Pointer to the callback function or internal data, casted to void + + int m_iArgc; ///< Internal representation of number of numeric function arguments + int m_iPri; ///< Valid only for binary and infix operators; Operator precedence. + EOprtAssociativity m_eOprtAsct; ///< Operator associativity; Valid only for binary operators + ECmdCode m_iCode; + ETypeCode m_iType; + bool m_bAllowOpti; ///< Flag indication optimizeability + }; + + + /** \brief Container for Callback objects. */ + typedef std::map funmap_type; + +} // namespace mu + +#endif + diff --git a/3rdparty/muparser/muParserDLL.cpp b/3rdparty/muparser/muParserDLL.cpp new file mode 100644 index 00000000..5730f715 --- /dev/null +++ b/3rdparty/muparser/muParserDLL.cpp @@ -0,0 +1,1272 @@ +/* + + _____ __ _____________ _______ ______ ___________ + / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ + | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ + |__|_| /____/| __(____ /__| /____ >\___ >__| + \/ |__| \/ \/ \/ + Copyright (C) 2004 - 2022 Ingo Berg + + Redistribution and use in source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#if defined(MUPARSER_DLL) + +#if defined(_WIN32) + #define WIN32_LEAN_AND_MEAN + #define _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_DEPRECATE + + #include +#endif + +#include + +#include "muParserDLL.h" +#include "muParser.h" +#include "muParserInt.h" +#include "muParserError.h" + +#if _UNICODE + #include +#endif + +#if defined(_MSC_VER) + #pragma warning(push) + #pragma warning(disable : 26812) +#endif + +#define MU_TRY \ + try \ + { + +#define MU_CATCH \ + } \ + catch (muError_t &e) \ + { \ + ParserTag *pTag = static_cast(a_hParser); \ + pTag->exc = e; \ + pTag->bError = true; \ + if (pTag->errHandler) \ + (pTag->errHandler)(a_hParser); \ + } \ + catch (...) \ + { \ + ParserTag *pTag = static_cast(a_hParser); \ + pTag->exc = muError_t(mu::ecINTERNAL_ERROR); \ + pTag->bError = true; \ + if (pTag->errHandler) \ + (pTag->errHandler)(a_hParser); \ + } + +/** \file + \brief This file contains the implementation of the DLL interface of muparser. +*/ + +typedef mu::ParserBase::exception_type muError_t; +typedef mu::ParserBase muParser_t; +int g_nBulkSize; + + +class ParserTag +{ +public: + ParserTag(int nType) + : pParser((nType == muBASETYPE_FLOAT) + ? (mu::ParserBase*)new mu::Parser() + : (nType == muBASETYPE_INT) ? (mu::ParserBase*)new mu::ParserInt() : nullptr) + , exc() + , errHandler(nullptr) + , bError(false) + , m_nParserType(nType) + {} + + ~ParserTag() + { + delete pParser; + } + + mu::ParserBase* pParser; + mu::ParserBase::exception_type exc; + muErrorHandler_t errHandler; + bool bError; + +private: + ParserTag(const ParserTag& ref); + ParserTag& operator=(const ParserTag& ref); + + int m_nParserType; +}; + +static muChar_t s_tmpOutBuf[2048]; + +template +constexpr std::size_t count_of(const T& array) +{ + return (sizeof(array) / sizeof(array[0])); +} + +//--------------------------------------------------------------------------- +// +// +// unexported functions +// +// +//--------------------------------------------------------------------------- + + +inline muParser_t* AsParser(muParserHandle_t a_hParser) +{ + return static_cast(a_hParser)->pParser; +} + + +inline ParserTag* AsParserTag(muParserHandle_t a_hParser) +{ + return static_cast(a_hParser); +} + + +#if defined(_WIN32) + +BOOL APIENTRY DllMain(HANDLE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*lpReserved*/) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + break; + + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + + return TRUE; +} + +#endif + +//--------------------------------------------------------------------------- +// +// +// exported functions +// +// +//--------------------------------------------------------------------------- + +API_EXPORT(void) mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void* pUserData) +{ + MU_TRY + muParser_t* p(AsParser(a_hParser)); + p->SetVarFactory(a_pFactory, pUserData); + MU_CATCH +} + + +/** \brief Create a new Parser instance and return its handle. */ +API_EXPORT(muParserHandle_t) mupCreate(int nBaseType) +{ + switch (nBaseType) + { + case muBASETYPE_FLOAT: return (void*)(new ParserTag(muBASETYPE_FLOAT)); + case muBASETYPE_INT: return (void*)(new ParserTag(muBASETYPE_INT)); + default: return nullptr; + } +} + + +/** \brief Release the parser instance related with a parser handle. */ +API_EXPORT(void) mupRelease(muParserHandle_t a_hParser) +{ + MU_TRY + ParserTag* p = static_cast(a_hParser); + delete p; + MU_CATCH +} + + +API_EXPORT(const muChar_t*) mupGetVersion(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + +#ifndef _UNICODE + snprintf(s_tmpOutBuf, count_of(s_tmpOutBuf), "%s", p->GetVersion().c_str()); +#else + swprintf(s_tmpOutBuf, count_of(s_tmpOutBuf), _T("%s"), p->GetVersion().c_str()); +#endif + + return s_tmpOutBuf; + MU_CATCH + return _T(""); +} + + +/** \brief Evaluate the expression. */ +API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + return p->Eval(); + MU_CATCH + return 0; +} + + +API_EXPORT(muFloat_t*) mupEvalMulti(muParserHandle_t a_hParser, int* nNum) +{ + MU_TRY + if (nNum == nullptr) + throw std::runtime_error("Argument is null!"); + + muParser_t* const p(AsParser(a_hParser)); + return p->Eval(*nNum); + MU_CATCH + return 0; +} + + +API_EXPORT(void) mupEvalBulk(muParserHandle_t a_hParser, muFloat_t* a_res, int nSize) +{ + MU_TRY + muParser_t* p(AsParser(a_hParser)); + p->Eval(a_res, nSize); + MU_CATCH +} + + +API_EXPORT(void) mupSetExpr(muParserHandle_t a_hParser, const muChar_t* a_szExpr) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->SetExpr(a_szExpr); + MU_CATCH +} + + +API_EXPORT(void) mupRemoveVar(muParserHandle_t a_hParser, const muChar_t* a_szName) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->RemoveVar(a_szName); + MU_CATCH +} + + +/** \brief Release all parser variables. + \param a_hParser Handle to the parser instance. +*/ +API_EXPORT(void) mupClearVar(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->ClearVar(); + MU_CATCH +} + + +/** \brief Release all parser variables. + \param a_hParser Handle to the parser instance. +*/ +API_EXPORT(void) mupClearConst(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->ClearConst(); + MU_CATCH +} + + +/** \brief Clear all user defined operators. + \param a_hParser Handle to the parser instance. +*/ +API_EXPORT(void) mupClearOprt(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->ClearOprt(); + MU_CATCH +} + + +API_EXPORT(void) mupClearFun(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->ClearFun(); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFun0(muParserHandle_t a_hParser, + const muChar_t* a_szName, + muFun0_t a_pFun, + muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFun1(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun1_t a_pFun, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFun2(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun2_t a_pFun, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFun3(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun3_t a_pFun, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFun4(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun4_t a_pFun, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFun5(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun5_t a_pFun, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFun6(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun6_t a_pFun, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFun7(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun7_t a_pFun, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFun8(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun8_t a_pFun, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFun9(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun9_t a_pFun, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFun10(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun10_t a_pFun, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFunUserData0(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData0_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFunUserData1(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData1_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFunUserData2(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData2_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFunUserData3(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData3_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFunUserData4(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData4_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFunUserData5(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData5_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFunUserData6(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData6_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFunUserData7(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData7_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFunUserData8(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData8_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFunUserData9(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData9_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineFunUserData10(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData10_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFun0(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun0_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFun1(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun1_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFun2(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun2_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFun3(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun3_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFun4(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun4_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFun5(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun5_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFun6(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun6_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFun7(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun7_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFun8(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun8_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFun9(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun9_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFun10(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun10_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFunUserData0(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData0_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFunUserData1(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData1_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFunUserData2(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData2_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFunUserData3(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData3_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFunUserData4(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData4_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFunUserData5(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData5_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFunUserData6(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData6_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFunUserData7(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData7_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFunUserData8(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData8_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFunUserData9(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData9_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkFunUserData10(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData10_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineStrFun1(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun1_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineStrFun2(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun2_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineStrFun3(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun3_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineStrFun4(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun4_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineStrFun5(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun5_t a_pFun) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineStrFunUserData1(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFunUserData1_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineStrFunUserData2(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFunUserData2_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineStrFunUserData3(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFunUserData3_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineStrFunUserData4(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFunUserData4_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineStrFunUserData5(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFunUserData5_t a_pFun, void* a_pUserData) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, false); + MU_CATCH +} + + +API_EXPORT(void) mupDefineMultFun(muParserHandle_t a_hParser, const muChar_t* a_szName, muMultFun_t a_pFun, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineMultFunUserData(muParserHandle_t a_hParser, const muChar_t* a_szName, muMultFunUserData_t a_pFun, void* a_pUserData, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineFunUserData(a_szName, a_pFun, a_pUserData, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineOprt(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun2_t a_pFun, muInt_t a_nPrec, muInt_t a_nOprtAsct, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineOprt(a_szName, a_pFun, a_nPrec, (mu::EOprtAssociativity)a_nOprtAsct, a_bAllowOpt != 0); + MU_CATCH +} + + +API_EXPORT(void) mupDefineVar(muParserHandle_t a_hParser, const muChar_t* a_szName, muFloat_t* a_pVar) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineVar(a_szName, a_pVar); + MU_CATCH +} + + +API_EXPORT(void) mupDefineBulkVar(muParserHandle_t a_hParser, const muChar_t* a_szName, muFloat_t* a_pVar) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineVar(a_szName, a_pVar); + MU_CATCH +} + + +API_EXPORT(void) mupDefineConst(muParserHandle_t a_hParser, const muChar_t* a_szName, muFloat_t a_fVal) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineConst(a_szName, a_fVal); + MU_CATCH +} + + +API_EXPORT(void) mupDefineStrConst(muParserHandle_t a_hParser, const muChar_t* a_szName, const muChar_t* a_szVal) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineStrConst(a_szName, a_szVal); + MU_CATCH +} + + +API_EXPORT(const muChar_t*) mupGetExpr(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + + // C# explodes when pMsg is returned directly. For some reason it can't access + // the memory where the message lies directly. +#ifndef _UNICODE + snprintf(s_tmpOutBuf, count_of(s_tmpOutBuf), "%s", p->GetExpr().c_str()); +#else + swprintf(s_tmpOutBuf, count_of(s_tmpOutBuf), _T("%s"), p->GetExpr().c_str()); +#endif + + return s_tmpOutBuf; + MU_CATCH + + return _T(""); +} + + +API_EXPORT(void) mupDefinePostfixOprt(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun1_t a_pOprt, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefinePostfixOprt(a_szName, a_pOprt, a_bAllowOpt != 0); + MU_CATCH +} + +// Signature changed to fix #125 (https://github.com/beltoforion/muparser/issues/125) +API_EXPORT(void) mupDefineInfixOprt(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun1_t a_pOprt, int a_iPrec, muBool_t a_bAllowOpt) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->DefineInfixOprt(a_szName, a_pOprt, a_iPrec, a_bAllowOpt != 0); + MU_CATCH +} + +// Define character sets for identifiers +API_EXPORT(void) mupDefineNameChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset) +{ + muParser_t* const p(AsParser(a_hParser)); + p->DefineNameChars(a_szCharset); +} + + +API_EXPORT(void) mupDefineOprtChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset) +{ + muParser_t* const p(AsParser(a_hParser)); + p->DefineOprtChars(a_szCharset); +} + + +API_EXPORT(void) mupDefineInfixOprtChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset) +{ + muParser_t* const p(AsParser(a_hParser)); + p->DefineInfixOprtChars(a_szCharset); +} + + +/** \brief Get the number of variables defined in the parser. + \param a_hParser [in] Must be a valid parser handle. + \return The number of used variables. + \sa mupGetExprVar +*/ +API_EXPORT(int) mupGetVarNum(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + const mu::varmap_type VarMap = p->GetVar(); + return (int)VarMap.size(); + MU_CATCH + + return 0; // never reached +} + + +/** \brief Return a variable that is used in an expression. + \param a_hParser [in] A valid parser handle. + \param a_iVar [in] The index of the variable to return. + \param a_szName [out] Pointer to the variable name. + \param a_pVar [out] Pointer to the variable. + \throw nothrow + + Prior to calling this function call mupGetExprVarNum in order to get the + number of variables in the expression. If the parameter a_iVar is greater + than the number of variables both a_szName and a_pVar will be set to zero. + As a side effect this function will trigger an internal calculation of the + expression undefined variables will be set to zero during this calculation. + During the calculation user defined callback functions present in the expression + will be called, this is unavoidable. +*/ +API_EXPORT(void) mupGetVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_szName, muFloat_t** a_pVar) +{ + // A static buffer is needed for the name since i can't return the + // pointer from the map. + static muChar_t szName[1024]; + + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + const mu::varmap_type VarMap = p->GetVar(); + + if (a_iVar >= VarMap.size()) + { + *a_szName = 0; + *a_pVar = 0; + return; + } + mu::varmap_type::const_iterator item; + + item = VarMap.begin(); + for (unsigned i = 0; i < a_iVar; ++i) + ++item; + +#ifndef _UNICODE + strncpy(szName, item->first.c_str(), count_of(szName)); +#else + wcsncpy(szName, item->first.c_str(), count_of(szName)); +#endif + + szName[count_of(szName) - 1] = 0; + + *a_szName = &szName[0]; + *a_pVar = item->second; + return; + MU_CATCH + + * a_szName = 0; + *a_pVar = 0; +} + + +/** \brief Get the number of variables used in the expression currently set in the parser. + \param a_hParser [in] Must be a valid parser handle. + \return The number of used variables. + \sa mupGetExprVar + */ +API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + const mu::varmap_type VarMap = p->GetUsedVar(); + return (int)VarMap.size(); + MU_CATCH + + return 0; // never reached +} + + +/** \brief Return a variable that is used in an expression. + + Prior to calling this function call mupGetExprVarNum in order to get the + number of variables in the expression. If the parameter a_iVar is greater + than the number of variables both a_szName and a_pVar will be set to zero. + As a side effect this function will trigger an internal calculation of the + expression undefined variables will be set to zero during this calculation. + During the calculation user defined callback functions present in the expression + will be called, this is unavoidable. + + \param a_hParser [in] A valid parser handle. + \param a_iVar [in] The index of the variable to return. + \param a_szName [out] Pointer to the variable name. + \param a_pVar [out] Pointer to the variable. + \throw nothrow +*/ +API_EXPORT(void) mupGetExprVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_szName, muFloat_t** a_pVar) +{ + // A static buffer is needed for the name since i can't return the + // pointer from the map. + static muChar_t szName[1024]; + + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + const mu::varmap_type VarMap = p->GetUsedVar(); + + if (a_iVar >= VarMap.size()) + { + *a_szName = 0; + *a_pVar = 0; + return; + } + mu::varmap_type::const_iterator item; + + item = VarMap.begin(); + for (unsigned i = 0; i < a_iVar; ++i) + ++item; + +#ifndef _UNICODE + strncpy(szName, item->first.c_str(), count_of(szName)); +#else + wcsncpy(szName, item->first.c_str(), count_of(szName)); +#endif + + szName[count_of(szName) - 1] = 0; + + *a_szName = &szName[0]; + *a_pVar = item->second; + return; + MU_CATCH + + * a_szName = 0; + *a_pVar = 0; +} + + +/** \brief Return the number of constants defined in a parser. */ +API_EXPORT(int) mupGetConstNum(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + const mu::valmap_type ValMap = p->GetConst(); + return (int)ValMap.size(); + MU_CATCH + + return 0; // never reached +} + + +API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->SetArgSep(cArgSep); + MU_CATCH +} + + +API_EXPORT(void) mupResetLocale(muParserHandle_t a_hParser) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->ResetLocale(); + MU_CATCH +} + + +API_EXPORT(void) mupSetDecSep(muParserHandle_t a_hParser, const muChar_t cDecSep) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->SetDecSep(cDecSep); + MU_CATCH +} + + +API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t cThousandsSep) +{ + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + p->SetThousandsSep(cThousandsSep); + MU_CATCH +} + +//--------------------------------------------------------------------------- +/** \brief Retrieve name and value of a single parser constant. + \param a_hParser [in] a valid parser handle + \param a_iVar [in] Index of the constant to query + \param a_pszName [out] pointer to a null terminated string with the constant name + \param [out] The constant value + */ +API_EXPORT(void) mupGetConst(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t* a_fVal) +{ + // A static buffer is needed for the name since i can't return the + // pointer from the map. + static muChar_t szName[1024]; + + MU_TRY + muParser_t* const p(AsParser(a_hParser)); + const mu::valmap_type ValMap = p->GetConst(); + + if (a_iVar >= ValMap.size()) + { + *a_pszName = 0; + *a_fVal = 0; + return; + } + + mu::valmap_type::const_iterator item; + item = ValMap.begin(); + for (unsigned i = 0; i < a_iVar; ++i) + ++item; + +#ifndef _UNICODE + strncpy(szName, item->first.c_str(), count_of(szName)); +#else + wcsncpy(szName, item->first.c_str(), count_of(szName)); +#endif + + szName[count_of(szName) - 1] = 0; + + *a_pszName = &szName[0]; + *a_fVal = item->second; + return; + + MU_CATCH + + * a_pszName = 0; + *a_fVal = 0; +} + + +/** \brief Add a custom value recognition function. */ +API_EXPORT(void) mupAddValIdent(muParserHandle_t a_hParser, muIdentFun_t a_pFun) +{ + MU_TRY + muParser_t* p(AsParser(a_hParser)); + p->AddValIdent(a_pFun); + MU_CATCH +} + + +/** \brief Query if an error occurred. + + After querying the internal error bit will be reset. So a consecutive call + will return false. +*/ +API_EXPORT(muBool_t) mupError(muParserHandle_t a_hParser) +{ + bool bError(AsParserTag(a_hParser)->bError); + AsParserTag(a_hParser)->bError = false; + return bError; +} + + +/** \brief Reset the internal error flag. */ +API_EXPORT(void) mupErrorReset(muParserHandle_t a_hParser) +{ + AsParserTag(a_hParser)->bError = false; +} + + +API_EXPORT(void) mupSetErrorHandler(muParserHandle_t a_hParser, muErrorHandler_t a_pHandler) +{ + AsParserTag(a_hParser)->errHandler = a_pHandler; +} + + +/** \brief Return the message associated with the last error. */ +API_EXPORT(const muChar_t*) mupGetErrorMsg(muParserHandle_t a_hParser) +{ + ParserTag* const p(AsParserTag(a_hParser)); + const muChar_t* pMsg = p->exc.GetMsg().c_str(); + + // C# explodes when pMsg is returned directly. For some reason it can't access + // the memory where the message lies directly. +#ifndef _UNICODE + snprintf(s_tmpOutBuf, count_of(s_tmpOutBuf), "%s", pMsg); +#else + swprintf(s_tmpOutBuf, count_of(s_tmpOutBuf), _T("%s"), pMsg); +#endif + + return s_tmpOutBuf; +} + + +/** \brief Return the message associated with the last error. */ +API_EXPORT(const muChar_t*) mupGetErrorToken(muParserHandle_t a_hParser) +{ + ParserTag* const p(AsParserTag(a_hParser)); + const muChar_t* pToken = p->exc.GetToken().c_str(); + + // C# explodes when pMsg is returned directly. For some reason it can't access + // the memory where the message lies directly. +#ifndef _UNICODE + snprintf(s_tmpOutBuf, count_of(s_tmpOutBuf), "%s", pToken); +#else + swprintf(s_tmpOutBuf, count_of(s_tmpOutBuf), _T("%s"), pToken); +#endif + + return s_tmpOutBuf; +} + + +/** \brief Return the code associated with the last error. +*/ +API_EXPORT(int) mupGetErrorCode(muParserHandle_t a_hParser) +{ + return AsParserTag(a_hParser)->exc.GetCode(); +} + + +/** \brief Return the position associated with the last error. */ +API_EXPORT(int) mupGetErrorPos(muParserHandle_t a_hParser) +{ + return (int)AsParserTag(a_hParser)->exc.GetPos(); +} + + +API_EXPORT(muFloat_t*) mupCreateVar() +{ + return new muFloat_t(0); +} + + +API_EXPORT(void) mupReleaseVar(muFloat_t* ptr) +{ + delete ptr; +} + +#if defined(_MSC_VER) + #pragma warning(pop) +#endif + +#endif // MUPARSER_DLL diff --git a/3rdparty/muparser/muParserDLL.h b/3rdparty/muparser/muParserDLL.h new file mode 100644 index 00000000..14d08cdb --- /dev/null +++ b/3rdparty/muparser/muParserDLL.h @@ -0,0 +1,310 @@ +/* + + _____ __ _____________ _______ ______ ___________ + / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ + | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ + |__|_| /____/| __(____ /__| /____ >\___ >__| + \/ |__| \/ \/ \/ + Copyright (C) 2004 - 2023 Ingo Berg + + Redistribution and use in source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef MU_PARSER_DLL_H +#define MU_PARSER_DLL_H + +#include "muParserFixes.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** \file + \brief This file contains the DLL interface of muparser. + */ + + // Basic types + typedef void* muParserHandle_t; // parser handle + +#ifndef _UNICODE + typedef char muChar_t; // character type +#else + typedef wchar_t muChar_t; // character type +#endif + + typedef int muBool_t; // boolean type + typedef int muInt_t; // integer type + typedef double muFloat_t; // floating point type + + // function types for calculation + typedef muFloat_t(*muFun0_t)(void); + typedef muFloat_t(*muFun1_t)(muFloat_t); + typedef muFloat_t(*muFun2_t)(muFloat_t, muFloat_t); + typedef muFloat_t(*muFun3_t)(muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muFun4_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muFun5_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muFun6_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muFun7_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muFun8_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muFun9_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muFun10_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + // with user data (not null) + typedef muFloat_t(*muFunUserData0_t)(void*); + typedef muFloat_t(*muFunUserData1_t)(void*, muFloat_t); + typedef muFloat_t(*muFunUserData2_t)(void*, muFloat_t, muFloat_t); + typedef muFloat_t(*muFunUserData3_t)(void*, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muFunUserData4_t)(void*, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muFunUserData5_t)(void*, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muFunUserData6_t)(void*, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muFunUserData7_t)(void*, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muFunUserData8_t)(void*, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muFunUserData9_t)(void*, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muFunUserData10_t)(void*, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + + // Function prototypes for bulkmode functions + typedef muFloat_t(*muBulkFun0_t)(int, int); + typedef muFloat_t(*muBulkFun1_t)(int, int, muFloat_t); + typedef muFloat_t(*muBulkFun2_t)(int, int, muFloat_t, muFloat_t); + typedef muFloat_t(*muBulkFun3_t)(int, int, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muBulkFun4_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muBulkFun5_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muBulkFun6_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muBulkFun7_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muBulkFun8_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muBulkFun9_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muBulkFun10_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + // with user data (not null) + typedef muFloat_t(*muBulkFunUserData0_t)(void*, int, int); + typedef muFloat_t(*muBulkFunUserData1_t)(void*, int, int, muFloat_t); + typedef muFloat_t(*muBulkFunUserData2_t)(void*, int, int, muFloat_t, muFloat_t); + typedef muFloat_t(*muBulkFunUserData3_t)(void*, int, int, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muBulkFunUserData4_t)(void*, int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muBulkFunUserData5_t)(void*, int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muBulkFunUserData6_t)(void*, int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muBulkFunUserData7_t)(void*, int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muBulkFunUserData8_t)(void*, int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muBulkFunUserData9_t)(void*, int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muBulkFunUserData10_t)(void*, int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + + typedef muFloat_t(*muMultFun_t)(const muFloat_t*, muInt_t); + typedef muFloat_t(*muMultFunUserData_t)(void*, const muFloat_t*, muInt_t); // with user data (not null) + + typedef muFloat_t(*muStrFun1_t)(const muChar_t*); + typedef muFloat_t(*muStrFun2_t)(const muChar_t*, muFloat_t); + typedef muFloat_t(*muStrFun3_t)(const muChar_t*, muFloat_t, muFloat_t); + typedef muFloat_t(*muStrFun4_t)(const muChar_t*, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muStrFun5_t)(const muChar_t*, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + // with user data (not null) + typedef muFloat_t(*muStrFunUserData1_t)(void*, const muChar_t*); + typedef muFloat_t(*muStrFunUserData2_t)(void*, const muChar_t*, muFloat_t); + typedef muFloat_t(*muStrFunUserData3_t)(void*, const muChar_t*, muFloat_t, muFloat_t); + typedef muFloat_t(*muStrFunUserData4_t)(void*, const muChar_t*, muFloat_t, muFloat_t, muFloat_t); + typedef muFloat_t(*muStrFunUserData5_t)(void*, const muChar_t*, muFloat_t, muFloat_t, muFloat_t, muFloat_t); + + // Functions for parser management + typedef void (*muErrorHandler_t)(muParserHandle_t a_hParser); // [optional] callback to an error handler + typedef muFloat_t* (*muFacFun_t)(const muChar_t*, void*); // [optional] callback for creating new variables + typedef muInt_t(*muIdentFun_t)(const muChar_t*, muInt_t*, muFloat_t*); // [optional] value identification callbacks + + //----------------------------------------------------------------------------------------------------- + // Constants + static const int muOPRT_ASCT_LEFT = 0; + static const int muOPRT_ASCT_RIGHT = 1; + + static const int muBASETYPE_FLOAT = 0; + static const int muBASETYPE_INT = 1; + + //----------------------------------------------------------------------------------------------------- + // + // + // muParser C compatible bindings + // + // + //----------------------------------------------------------------------------------------------------- + + + // Basic operations / initialization + API_EXPORT(muParserHandle_t) mupCreate(int nBaseType); + API_EXPORT(void) mupRelease(muParserHandle_t a_hParser); + API_EXPORT(const muChar_t*) mupGetExpr(muParserHandle_t a_hParser); + API_EXPORT(void) mupSetExpr(muParserHandle_t a_hParser, const muChar_t* a_szExpr); + API_EXPORT(void) mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void* pUserData); + API_EXPORT(const muChar_t*) mupGetVersion(muParserHandle_t a_hParser); + API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser); + API_EXPORT(muFloat_t*) mupEvalMulti(muParserHandle_t a_hParser, int* nNum); + API_EXPORT(void) mupEvalBulk(muParserHandle_t a_hParser, muFloat_t* a_fResult, int nSize); + + // Defining callbacks / variables / constants + API_EXPORT(void) mupDefineFun0(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun0_t a_pFun, muBool_t a_bOptimize); + API_EXPORT(void) mupDefineFun1(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun1_t a_pFun, muBool_t a_bOptimize); + API_EXPORT(void) mupDefineFun2(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun2_t a_pFun, muBool_t a_bOptimize); + API_EXPORT(void) mupDefineFun3(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun3_t a_pFun, muBool_t a_bOptimize); + API_EXPORT(void) mupDefineFun4(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun4_t a_pFun, muBool_t a_bOptimize); + API_EXPORT(void) mupDefineFun5(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun5_t a_pFun, muBool_t a_bOptimize); + API_EXPORT(void) mupDefineFun6(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun6_t a_pFun, muBool_t a_bOptimize); + API_EXPORT(void) mupDefineFun7(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun7_t a_pFun, muBool_t a_bOptimize); + API_EXPORT(void) mupDefineFun8(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun8_t a_pFun, muBool_t a_bOptimize); + API_EXPORT(void) mupDefineFun9(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun9_t a_pFun, muBool_t a_bOptimize); + API_EXPORT(void) mupDefineFun10(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun10_t a_pFun, muBool_t a_bOptimize); + // with user data (not null) + API_EXPORT(void) mupDefineFunUserData0(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData0_t a_pFun, void* a_pUserData, muBool_t a_bOptimize); + API_EXPORT(void) mupDefineFunUserData1(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData1_t a_pFun, void* a_pUserData, muBool_t a_bOptimize); + API_EXPORT(void) mupDefineFunUserData2(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData2_t a_pFun, void* a_pUserData, muBool_t a_bOptimize); + API_EXPORT(void) mupDefineFunUserData3(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData3_t a_pFun, void* a_pUserData, muBool_t a_bOptimize); + API_EXPORT(void) mupDefineFunUserData4(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData4_t a_pFun, void* a_pUserData, muBool_t a_bOptimize); + API_EXPORT(void) mupDefineFunUserData5(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData5_t a_pFun, void* a_pUserData, muBool_t a_bOptimize); + API_EXPORT(void) mupDefineFunUserData6(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData6_t a_pFun, void* a_pUserData, muBool_t a_bOptimize); + API_EXPORT(void) mupDefineFunUserData7(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData7_t a_pFun, void* a_pUserData, muBool_t a_bOptimize); + API_EXPORT(void) mupDefineFunUserData8(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData8_t a_pFun, void* a_pUserData, muBool_t a_bOptimize); + API_EXPORT(void) mupDefineFunUserData9(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData9_t a_pFun, void* a_pUserData, muBool_t a_bOptimize); + API_EXPORT(void) mupDefineFunUserData10(muParserHandle_t a_hParser, const muChar_t* a_szName, muFunUserData10_t a_pFun, void* a_pUserData, muBool_t a_bOptimize); + + // Defining bulkmode functions + API_EXPORT(void) mupDefineBulkFun0(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun0_t a_pFun); + API_EXPORT(void) mupDefineBulkFun1(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun1_t a_pFun); + API_EXPORT(void) mupDefineBulkFun2(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun2_t a_pFun); + API_EXPORT(void) mupDefineBulkFun3(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun3_t a_pFun); + API_EXPORT(void) mupDefineBulkFun4(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun4_t a_pFun); + API_EXPORT(void) mupDefineBulkFun5(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun5_t a_pFun); + API_EXPORT(void) mupDefineBulkFun6(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun6_t a_pFun); + API_EXPORT(void) mupDefineBulkFun7(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun7_t a_pFun); + API_EXPORT(void) mupDefineBulkFun8(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun8_t a_pFun); + API_EXPORT(void) mupDefineBulkFun9(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun9_t a_pFun); + API_EXPORT(void) mupDefineBulkFun10(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun10_t a_pFun); + // with user data (not null) + API_EXPORT(void) mupDefineBulkFunUserData0(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData0_t a_pFun, void* a_pUserData); + API_EXPORT(void) mupDefineBulkFunUserData1(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData1_t a_pFun, void* a_pUserData); + API_EXPORT(void) mupDefineBulkFunUserData2(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData2_t a_pFun, void* a_pUserData); + API_EXPORT(void) mupDefineBulkFunUserData3(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData3_t a_pFun, void* a_pUserData); + API_EXPORT(void) mupDefineBulkFunUserData4(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData4_t a_pFun, void* a_pUserData); + API_EXPORT(void) mupDefineBulkFunUserData5(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData5_t a_pFun, void* a_pUserData); + API_EXPORT(void) mupDefineBulkFunUserData6(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData6_t a_pFun, void* a_pUserData); + API_EXPORT(void) mupDefineBulkFunUserData7(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData7_t a_pFun, void* a_pUserData); + API_EXPORT(void) mupDefineBulkFunUserData8(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData8_t a_pFun, void* a_pUserData); + API_EXPORT(void) mupDefineBulkFunUserData9(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData9_t a_pFun, void* a_pUserData); + API_EXPORT(void) mupDefineBulkFunUserData10(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFunUserData10_t a_pFun, void* a_pUserData); + + // string functions + API_EXPORT(void) mupDefineStrFun1(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun1_t a_pFun); + API_EXPORT(void) mupDefineStrFun2(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun2_t a_pFun); + API_EXPORT(void) mupDefineStrFun3(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun3_t a_pFun); + API_EXPORT(void) mupDefineStrFun4(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun4_t a_pFun); + API_EXPORT(void) mupDefineStrFun5(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun5_t a_pFun); + // with user data (not null) + API_EXPORT(void) mupDefineStrFunUserData1(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFunUserData1_t a_pFun, void* a_pUserData); + API_EXPORT(void) mupDefineStrFunUserData2(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFunUserData2_t a_pFun, void* a_pUserData); + API_EXPORT(void) mupDefineStrFunUserData3(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFunUserData3_t a_pFun, void* a_pUserData); + API_EXPORT(void) mupDefineStrFunUserData4(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFunUserData4_t a_pFun, void* a_pUserData); + API_EXPORT(void) mupDefineStrFunUserData5(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFunUserData5_t a_pFun, void* a_pUserData); + + API_EXPORT(void) mupDefineMultFun(muParserHandle_t a_hParser, + const muChar_t* a_szName, + muMultFun_t a_pFun, + muBool_t a_bOptimize); + // with user data (not null) + API_EXPORT(void) mupDefineMultFunUserData(muParserHandle_t a_hParser, + const muChar_t* a_szName, + muMultFunUserData_t a_pFun, + void* a_pUserData, + muBool_t a_bOptimize); + + API_EXPORT(void) mupDefineOprt(muParserHandle_t a_hParser, + const muChar_t* a_szName, + muFun2_t a_pFun, + muInt_t a_nPrec, + muInt_t a_nOprtAsct, + muBool_t a_bOptimize); + + API_EXPORT(void) mupDefineConst(muParserHandle_t a_hParser, + const muChar_t* a_szName, + muFloat_t a_fVal); + + API_EXPORT(void) mupDefineStrConst(muParserHandle_t a_hParser, + const muChar_t* a_szName, + const muChar_t* a_sVal); + + API_EXPORT(void) mupDefineVar(muParserHandle_t a_hParser, + const muChar_t* a_szName, + muFloat_t* a_fVar); + + API_EXPORT(void) mupDefineBulkVar(muParserHandle_t a_hParser, + const muChar_t* a_szName, + muFloat_t* a_fVar); + + API_EXPORT(void) mupDefinePostfixOprt(muParserHandle_t a_hParser, + const muChar_t* a_szName, + muFun1_t a_pOprt, + muBool_t a_bOptimize); + + // signature changed to fix #125 (https://github.com/beltoforion/muparser/issues/125) + API_EXPORT(void) mupDefineInfixOprt( + muParserHandle_t a_hParser, + const muChar_t* a_szName, + muFun1_t a_pOprt, + int a_iPrec, + muBool_t a_bAllowOpt); + + // Define character sets for identifiers + API_EXPORT(void) mupDefineNameChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset); + API_EXPORT(void) mupDefineOprtChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset); + API_EXPORT(void) mupDefineInfixOprtChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset); + + // Remove all / single variables + API_EXPORT(void) mupRemoveVar(muParserHandle_t a_hParser, const muChar_t* a_szName); + API_EXPORT(void) mupClearVar(muParserHandle_t a_hParser); + API_EXPORT(void) mupClearConst(muParserHandle_t a_hParser); + API_EXPORT(void) mupClearOprt(muParserHandle_t a_hParser); + API_EXPORT(void) mupClearFun(muParserHandle_t a_hParser); + + // Querying variables / expression variables / constants + API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser); + API_EXPORT(int) mupGetVarNum(muParserHandle_t a_hParser); + API_EXPORT(int) mupGetConstNum(muParserHandle_t a_hParser); + API_EXPORT(void) mupGetExprVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t** a_pVar); + API_EXPORT(void) mupGetVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t** a_pVar); + API_EXPORT(void) mupGetConst(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t* a_pVar); + API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep); + API_EXPORT(void) mupSetDecSep(muParserHandle_t a_hParser, const muChar_t cArgSep); + API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t cArgSep); + API_EXPORT(void) mupResetLocale(muParserHandle_t a_hParser); + + // Add value recognition callbacks + API_EXPORT(void) mupAddValIdent(muParserHandle_t a_hParser, muIdentFun_t); + + // Error handling + API_EXPORT(muBool_t) mupError(muParserHandle_t a_hParser); + API_EXPORT(void) mupErrorReset(muParserHandle_t a_hParser); + API_EXPORT(void) mupSetErrorHandler(muParserHandle_t a_hParser, muErrorHandler_t a_pErrHandler); + API_EXPORT(const muChar_t*) mupGetErrorMsg(muParserHandle_t a_hParser); + API_EXPORT(muInt_t) mupGetErrorCode(muParserHandle_t a_hParser); + API_EXPORT(muInt_t) mupGetErrorPos(muParserHandle_t a_hParser); + API_EXPORT(const muChar_t*) mupGetErrorToken(muParserHandle_t a_hParser); + //API_EXPORT(const muChar_t*) mupGetErrorExpr(muParserHandle_t a_hParser); + + // This is used for .NET only. It creates a new variable allowing the dll to + // manage the variable rather than the .NET garbage collector. + API_EXPORT(muFloat_t*) mupCreateVar(void); + API_EXPORT(void) mupReleaseVar(muFloat_t*); + +#ifdef __cplusplus +} +#endif + +#endif // include guard diff --git a/3rdparty/muparser/muParserDef.h b/3rdparty/muparser/muParserDef.h index 33c838b8..6a154862 100644 --- a/3rdparty/muparser/muParserDef.h +++ b/3rdparty/muparser/muParserDef.h @@ -1,374 +1,520 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2014 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -#ifndef MUP_DEF_H -#define MUP_DEF_H - -#include -#include -#include -#include - -#include "muParserFixes.h" - -/** \file - \brief This file contains standard definitions used by the parser. -*/ - -#define MUP_VERSION _T("2.2.5") -#define MUP_VERSION_DATE _T("20150427; GC") - -#define MUP_CHARS _T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") - -/** \brief If this macro is defined mathematical exceptions (div by zero) will be thrown as exceptions. */ -//#define MUP_MATH_EXCEPTIONS - -/** \brief Define the base datatype for values. - - This datatype must be a built in value type. You can not use custom classes. - It should be working with all types except "int"! -*/ -#define MUP_BASETYPE double - -/** \brief Activate this option in order to compile with OpenMP support. - - OpenMP is used only in the bulk mode it may increase the performance a bit. -*/ -//#define MUP_USE_OPENMP - -#if defined(_UNICODE) -#ifndef _T -#define _T(x) x -#endif - -/** \brief Definition of the basic parser string type. */ -#define MUP_STRING_TYPE std::string -#else - #ifndef _T - #define _T(x) x - #endif - - /** \brief Definition of the basic parser string type. */ - #define MUP_STRING_TYPE std::string -#endif - -#if defined(_DEBUG) - /** \brief Debug macro to force an abortion of the programm with a certain message. - */ - #define MUP_FAIL(MSG) \ - { \ - bool MSG=false; \ - assert(MSG); \ - } - - /** \brief An assertion that does not kill the program. - - This macro is neutralised in UNICODE builds. It's - too difficult to translate. - */ - #define MUP_ASSERT(COND) \ - if (!(COND)) \ - { \ - stringstream_type ss; \ - ss << _T("Assertion \"") _T(#COND) _T("\" failed: ") \ - << __FILE__ << _T(" line ") \ - << __LINE__ << _T("."); \ - throw ParserError( ss.str() ); \ - } -#else - #define MUP_FAIL(MSG) - #define MUP_ASSERT(COND) -#endif - - -namespace mu -{ -#if defined(_UNICODE) - - //------------------------------------------------------------------------------ - /** \brief Encapsulate cout. - - Used for supporting UNICODE more easily. - */ - inline std::ostream& console() - { - return std::cout; - } - - /** \brief Encapsulate cin. - - Used for supporting UNICODE more easily. - */ - inline std::istream& console_in() - { - return std::cin; - } - -#else - - /** \brief Encapsulate cout. - - Used for supporting UNICODE more easily. - */ - inline std::ostream& console() - { - return std::cout; - } - - /** \brief Encapsulate cin. - - Used for supporting UNICODE more easily. - */ - inline std::istream& console_in() - { - return std::cin; - } - -#endif - - //------------------------------------------------------------------------------ - /** \brief Bytecode values. - - \attention The order of the operator entries must match the order in ParserBase::c_DefaultOprt! - */ - enum ECmdCode - { - // The following are codes for built in binary operators - // apart from built in operators the user has the opportunity to - // add user defined operators. - cmLE = 0, ///< Operator item: less or equal - cmGE = 1, ///< Operator item: greater or equal - cmNEQ = 2, ///< Operator item: not equal - cmEQ = 3, ///< Operator item: equals - cmLT = 4, ///< Operator item: less than - cmGT = 5, ///< Operator item: greater than - cmADD = 6, ///< Operator item: add - cmSUB = 7, ///< Operator item: subtract - cmMUL = 8, ///< Operator item: multiply - cmDIV = 9, ///< Operator item: division - cmPOW = 10, ///< Operator item: y to the power of ... - cmLAND = 11, - cmLOR = 12, - cmASSIGN = 13, ///< Operator item: Assignment operator - cmBO = 14, ///< Operator item: opening bracket - cmBC = 15, ///< Operator item: closing bracket - cmIF = 16, ///< For use in the ternary if-then-else operator - cmELSE = 17, ///< For use in the ternary if-then-else operator - cmENDIF = 18, ///< For use in the ternary if-then-else operator - cmARG_SEP = 19, ///< function argument separator - cmVAR = 20, ///< variable item - cmVAL = 21, ///< value item - - // For optimization purposes - cmVARPOW2, - cmVARPOW3, - cmVARPOW4, - cmVARMUL, - cmPOW2, - - // operators and functions - cmFUNC, ///< Code for a generic function item - cmFUNC_STR, ///< Code for a function with a string parameter - cmFUNC_BULK, ///< Special callbacks for Bulk mode with an additional parameter for the bulk index - cmSTRING, ///< Code for a string token - cmOPRT_BIN, ///< user defined binary operator - cmOPRT_POSTFIX, ///< code for postfix operators - cmOPRT_INFIX, ///< code for infix operators - cmEND, ///< end of formula - cmUNKNOWN ///< uninitialized item - }; - - //------------------------------------------------------------------------------ - /** \brief Types internally used by the parser. - */ - enum ETypeCode - { - tpSTR = 0, ///< String type (Function arguments and constants only, no string variables) - tpDBL = 1, ///< Floating point variables - tpVOID = 2 ///< Undefined type. - }; - - //------------------------------------------------------------------------------ - enum EParserVersionInfo - { - pviBRIEF, - pviFULL - }; - - //------------------------------------------------------------------------------ - /** \brief Parser operator precedence values. */ - enum EOprtAssociativity - { - oaLEFT = 0, - oaRIGHT = 1, - oaNONE = 2 - }; - - //------------------------------------------------------------------------------ - /** \brief Parser operator precedence values. */ - enum EOprtPrecedence - { - // binary operators - prLOR = 1, - prLAND = 2, - prLOGIC = 3, ///< logic operators - prCMP = 4, ///< comparsion operators - prADD_SUB = 5, ///< addition - prMUL_DIV = 6, ///< multiplication/division - prPOW = 7, ///< power operator priority (highest) - - // infix operators - prINFIX = 6, ///< Signs have a higher priority than ADD_SUB, but lower than power operator - prPOSTFIX = 6 ///< Postfix operator priority (currently unused) - }; - - //------------------------------------------------------------------------------ - // basic types - - /** \brief The numeric datatype used by the parser. - - Normally this is a floating point type either single or double precision. - */ - typedef MUP_BASETYPE value_type; - - /** \brief The stringtype used by the parser. - - Depends on wether UNICODE is used or not. - */ - typedef MUP_STRING_TYPE string_type; - - /** \brief The character type used by the parser. - - Depends on wether UNICODE is used or not. - */ - typedef string_type::value_type char_type; - - /** \brief Typedef for easily using stringstream that respect the parser stringtype. */ - typedef std::basic_stringstream, - std::allocator > stringstream_type; - - // Data container types - - /** \brief Type used for storing variables. */ - typedef std::map varmap_type; - - /** \brief Type used for storing constants. */ - typedef std::map valmap_type; - - /** \brief Type for assigning a string name to an index in the internal string table. */ - typedef std::map strmap_type; - - // Parser callbacks - - /** \brief Callback type used for functions without arguments. */ - typedef value_type (*generic_fun_type)(); - - /** \brief Callback type used for functions without arguments. */ - typedef value_type (*fun_type0)(); - - /** \brief Callback type used for functions with a single arguments. */ - typedef value_type (*fun_type1)(value_type); - - /** \brief Callback type used for functions with two arguments. */ - typedef value_type (*fun_type2)(value_type, value_type); - - /** \brief Callback type used for functions with three arguments. */ - typedef value_type (*fun_type3)(value_type, value_type, value_type); - - /** \brief Callback type used for functions with four arguments. */ - typedef value_type (*fun_type4)(value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*fun_type5)(value_type, value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*fun_type6)(value_type, value_type, value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*fun_type7)(value_type, value_type, value_type, value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*fun_type8)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*fun_type9)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*fun_type10)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions without arguments. */ - typedef value_type (*bulkfun_type0)(int, int); - - /** \brief Callback type used for functions with a single arguments. */ - typedef value_type (*bulkfun_type1)(int, int, value_type); - - /** \brief Callback type used for functions with two arguments. */ - typedef value_type (*bulkfun_type2)(int, int, value_type, value_type); - - /** \brief Callback type used for functions with three arguments. */ - typedef value_type (*bulkfun_type3)(int, int, value_type, value_type, value_type); - - /** \brief Callback type used for functions with four arguments. */ - typedef value_type (*bulkfun_type4)(int, int, value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*bulkfun_type5)(int, int, value_type, value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*bulkfun_type6)(int, int, value_type, value_type, value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*bulkfun_type7)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*bulkfun_type8)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*bulkfun_type9)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*bulkfun_type10)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions with a variable argument list. */ - typedef value_type (*multfun_type)(const value_type*, int); - - /** \brief Callback type used for functions taking a string as an argument. */ - typedef value_type (*strfun_type1)(const char_type*); - - /** \brief Callback type used for functions taking a string and a value as arguments. */ - typedef value_type (*strfun_type2)(const char_type*, value_type); - - /** \brief Callback type used for functions taking a string and two values as arguments. */ - typedef value_type (*strfun_type3)(const char_type*, value_type, value_type); - - /** \brief Callback used for functions that identify values in a string. */ - typedef int (*identfun_type)(const char_type *sExpr, int *nPos, value_type *fVal); - - /** \brief Callback used for variable creation factory functions. */ - typedef value_type* (*facfun_type)(const char_type*, void*); -} // end of namespace - -#endif - +/* + + _____ __ _____________ _______ ______ ___________ + / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ + | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ + |__|_| /____/| __(____ /__| /____ >\___ >__| + \/ |__| \/ \/ \/ + Copyright (C) 2004 - 2022 Ingo Berg + + Redistribution and use in source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef MUP_DEF_H +#define MUP_DEF_H + +#include +#include +#include +#include + +#include "muParserFixes.h" + +/** \file + \brief This file contains standard definitions used by the parser. +*/ + +/** \brief Define the base datatype for values. + + This datatype must be a built in value type. You can not use custom classes. + It should be working with all types except "int"! +*/ +#define MUP_BASETYPE double + +/** \brief Activate this option in order to compile with OpenMP support. + + OpenMP is used only in the bulk mode it may increase the performance a bit. + + !!! DO NOT ACTIVATE THIS MACRO HERE IF YOU USE CMAKE FOR BUILDING !!! + + use the cmake option instead! +*/ +//#define MUP_USE_OPENMP + +#if defined(_UNICODE) && defined(MUP_USE_UNICODE) + /** \brief Definition of the basic parser string type. */ + #define MUP_STRING_TYPE std::wstring + + #if !defined(_T) + #define _T(x) L##x + #endif // not defined _T +#else + #ifndef _T + #define _T(x) x + #endif + + /** \brief Definition of the basic parser string type. */ + #define MUP_STRING_TYPE std::string +#endif + +/** \brief An assertion that does not kill the program. */ +#define MUP_ASSERT(COND) \ + if (!(COND)) \ + { \ + stringstream_type ss; \ + ss << _T("Assertion \"") _T(#COND) _T("\" failed: ") \ + << __FILE__ << _T(" line ") \ + << __LINE__ << _T("."); \ + throw ParserError( ecINTERNAL_ERROR, -1, ss.str()); \ + } + +#if defined(_MSC_VER) + #pragma warning(push) + #pragma warning(disable : 26812) +#endif + + +namespace mu +{ +#if defined(_UNICODE) && defined(MUP_USE_UNICODE) + + /** \brief Encapsulate wcout. */ + inline std::wostream& console() + { + return std::wcout; + } + + /** \brief Encapsulate cin. */ + inline std::wistream& console_in() + { + return std::wcin; + } + +#else + + /** \brief Encapsulate cout. + + Used for supporting UNICODE more easily. + */ + inline std::ostream& console() + { + return std::cout; + } + + /** \brief Encapsulate cin. + + Used for supporting UNICODE more easily. + */ + inline std::istream& console_in() + { + return std::cin; + } + +#endif + + /** \brief Bytecode values. + + \attention The order of the operator entries must match the order in ParserBase::c_DefaultOprt! + */ + enum ECmdCode + { + // The following are codes for built in binary operators + // apart from built in operators the user has the opportunity to + // add user defined operators. + cmLE = 0, ///< Operator item: less or equal + cmGE = 1, ///< Operator item: greater or equal + cmNEQ = 2, ///< Operator item: not equal + cmEQ = 3, ///< Operator item: equals + cmLT = 4, ///< Operator item: less than + cmGT = 5, ///< Operator item: greater than + cmADD = 6, ///< Operator item: add + cmSUB = 7, ///< Operator item: subtract + cmMUL = 8, ///< Operator item: multiply + cmDIV = 9, ///< Operator item: division + cmPOW = 10, ///< Operator item: y to the power of ... + cmLAND = 11, + cmLOR = 12, + cmASSIGN = 13, ///< Operator item: Assignment operator + cmBO = 14, ///< Operator item: opening bracket + cmBC = 15, ///< Operator item: closing bracket + cmIF = 16, ///< For use in the ternary if-then-else operator + cmELSE = 17, ///< For use in the ternary if-then-else operator + cmENDIF = 18, ///< For use in the ternary if-then-else operator + cmARG_SEP = 19, ///< function argument separator + cmVAR = 20, ///< variable item + cmVAL = 21, ///< value item + + // For optimization purposes + cmVARPOW2 = 22, + cmVARPOW3 = 23, + cmVARPOW4 = 24, + cmVARMUL = 25, + + // operators and functions + cmFUNC = 26, ///< Code for a generic function item + cmFUNC_STR, ///< Code for a function with a string parameter + cmFUNC_BULK, ///< Special callbacks for Bulk mode with an additional parameter for the bulk index + cmSTRING, ///< Code for a string token + cmOPRT_BIN, ///< user defined binary operator + cmOPRT_POSTFIX, ///< code for postfix operators + cmOPRT_INFIX, ///< code for infix operators + cmEND, ///< end of formula + cmUNKNOWN ///< uninitialized item + }; + + /** \brief Types internally used by the parser. + */ + enum ETypeCode + { + tpSTR = 0, ///< String type (Function arguments and constants only, no string variables) + tpDBL = 1, ///< Floating point variables + tpVOID = 2 ///< Undefined type. + }; + + + enum EParserVersionInfo + { + pviBRIEF, + pviFULL + }; + + + /** \brief Parser operator precedence values. */ + enum EOprtAssociativity + { + oaLEFT = 0, + oaRIGHT = 1, + oaNONE = 2 + }; + + + /** \brief Parser operator precedence values. */ + enum EOprtPrecedence + { + prLOR = 1, ///< logic or + prLAND = 2, ///< logic and + prBOR = 3, ///< bitwise or + prBAND = 4, ///< bitwise and + prCMP = 5, ///< comparsion operators + prADD_SUB = 6, ///< addition + prMUL_DIV = 7, ///< multiplication/division + prPOW = 8, ///< power operator priority (highest) + + // infix operators + prINFIX = 7, ///< Signs have a higher priority than ADD_SUB, but lower than power operator + prPOSTFIX = 7 ///< Postfix operator priority (currently unused) + }; + + + /** \brief Error codes. */ + enum EErrorCodes + { + // Formula syntax errors + ecUNEXPECTED_OPERATOR = 0, ///< Unexpected binary operator found + ecUNASSIGNABLE_TOKEN = 1, ///< Token can't be identified. + ecUNEXPECTED_EOF = 2, ///< Unexpected end of formula. (Example: "2+sin(") + ecUNEXPECTED_ARG_SEP = 3, ///< An unexpected comma has been found. (Example: "1,23") + ecUNEXPECTED_ARG = 4, ///< An unexpected argument has been found + ecUNEXPECTED_VAL = 5, ///< An unexpected value token has been found + ecUNEXPECTED_VAR = 6, ///< An unexpected variable token has been found + ecUNEXPECTED_PARENS = 7, ///< Unexpected Parenthesis, opening or closing + ecUNEXPECTED_STR = 8, ///< A string has been found at an inapropriate position + ecSTRING_EXPECTED = 9, ///< A string function has been called with a different type of argument + ecVAL_EXPECTED = 10, ///< A numerical function has been called with a non value type of argument + ecMISSING_PARENS = 11, ///< Missing parens. (Example: "3*sin(3") + ecUNEXPECTED_FUN = 12, ///< Unexpected function found. (Example: "sin(8)cos(9)") + ecUNTERMINATED_STRING = 13, ///< unterminated string constant. (Example: "3*valueof("hello)") + ecTOO_MANY_PARAMS = 14, ///< Too many function parameters + ecTOO_FEW_PARAMS = 15, ///< Too few function parameters. (Example: "ite(1<2,2)") + ecOPRT_TYPE_CONFLICT = 16, ///< binary operators may only be applied to value items of the same type + ecSTR_RESULT = 17, ///< result is a string + + // Invalid Parser input Parameters + ecINVALID_NAME = 18, ///< Invalid function, variable or constant name. + ecINVALID_BINOP_IDENT = 19, ///< Invalid binary operator identifier + ecINVALID_INFIX_IDENT = 20, ///< Invalid function, variable or constant name. + ecINVALID_POSTFIX_IDENT = 21, ///< Invalid function, variable or constant name. + + ecBUILTIN_OVERLOAD = 22, ///< Trying to overload builtin operator + ecINVALID_FUN_PTR = 23, ///< Invalid callback function pointer + ecINVALID_VAR_PTR = 24, ///< Invalid variable pointer + ecEMPTY_EXPRESSION = 25, ///< The Expression is empty + ecNAME_CONFLICT = 26, ///< Name conflict + ecOPT_PRI = 27, ///< Invalid operator priority + // + ecDOMAIN_ERROR = 28, ///< catch division by zero, sqrt(-1), log(0) (currently unused) + ecDIV_BY_ZERO = 29, ///< Division by zero (currently unused) + ecGENERIC = 30, ///< Generic error + ecLOCALE = 31, ///< Conflict with current locale + + ecUNEXPECTED_CONDITIONAL = 32, + ecMISSING_ELSE_CLAUSE = 33, + ecMISPLACED_COLON = 34, + + ecUNREASONABLE_NUMBER_OF_COMPUTATIONS = 35, + + ecIDENTIFIER_TOO_LONG = 36, ///< Thrown when an identifier with more then 255 characters is used. + + ecEXPRESSION_TOO_LONG = 37, ///< Throw an exception if the expression has more than 10000 characters. (an arbitrary limit) + + ecINVALID_CHARACTERS_FOUND = 38,///< The expression or identifier contains invalid non printable characters + + // internal errors + ecINTERNAL_ERROR = 39, ///< Internal error of any kind. + + ecBYTECODE_IMPORT_EXPORT_DISABLED = 40, ///< Bytecode cannot be exported. + + // The last two are special entries + ecCOUNT, ///< This is no error code, It just stores just the total number of error codes + ecUNDEFINED = -1 ///< Undefined message, placeholder to detect unassigned error messages + }; + + //------------------------------------------------------------------------------ + // Basic Types + //------------------------------------------------------------------------------ + + /** \brief The numeric datatype used by the parser. + + Normally this is a floating point type either single or double precision. + */ + typedef MUP_BASETYPE value_type; + + /** \brief The stringtype used by the parser. + + Depends on whether UNICODE is used or not. + */ + typedef MUP_STRING_TYPE string_type; + + /** \brief The character type used by the parser. + + Depends on whether UNICODE is used or not. + */ + typedef string_type::value_type char_type; + + /** \brief Typedef for easily using stringstream that respect the parser stringtype. */ + typedef std::basic_stringstream, std::allocator > stringstream_type; + + // Data container types + + /** \brief Type used for storing variables. */ + typedef std::map varmap_type; + + /** \brief Type used for storing constants. */ + typedef std::map valmap_type; + + /** \brief Type for assigning a string name to an index in the internal string table. */ + typedef std::map strmap_type; + + // Parser callbacks + + /** \brief Function type used to erase type. Voluntarily needs explicit cast with all other *fun_type*. */ + typedef void(*erased_fun_type)(); + + /** \brief Callback type used for functions without arguments. */ + typedef value_type(*fun_type0)(); + + /** \brief Callback type used for functions with a single arguments. */ + typedef value_type(*fun_type1)(value_type); + + /** \brief Callback type used for functions with two arguments. */ + typedef value_type(*fun_type2)(value_type, value_type); + + /** \brief Callback type used for functions with three arguments. */ + typedef value_type(*fun_type3)(value_type, value_type, value_type); + + /** \brief Callback type used for functions with four arguments. */ + typedef value_type(*fun_type4)(value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions with five arguments. */ + typedef value_type(*fun_type5)(value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions with six arguments. */ + typedef value_type(*fun_type6)(value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions with seven arguments. */ + typedef value_type(*fun_type7)(value_type, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions with eight arguments. */ + typedef value_type(*fun_type8)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions with nine arguments. */ + typedef value_type(*fun_type9)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions with ten arguments. */ + typedef value_type(*fun_type10)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type with user data (not null) used for functions without arguments. */ + typedef value_type(*fun_userdata_type0)(void*); + + /** \brief Callback type with user data (not null) used for functions with a single arguments. */ + typedef value_type(*fun_userdata_type1)(void*, value_type); + + /** \brief Callback type with user data (not null) used for functions with two arguments. */ + typedef value_type(*fun_userdata_type2)(void*, value_type, value_type); + + /** \brief Callback type with user data (not null) used for functions with three arguments. */ + typedef value_type(*fun_userdata_type3)(void*, value_type, value_type, value_type); + + /** \brief Callback type with user data (not null) used for functions with four arguments. */ + typedef value_type(*fun_userdata_type4)(void*, value_type, value_type, value_type, value_type); + + /** \brief Callback type with user data (not null) used for functions with five arguments. */ + typedef value_type(*fun_userdata_type5)(void*, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type with user data (not null) used for functions with six arguments. */ + typedef value_type(*fun_userdata_type6)(void*, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type with user data (not null) used for functions with seven arguments. */ + typedef value_type(*fun_userdata_type7)(void*, value_type, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type with user data (not null) used for functions with eight arguments. */ + typedef value_type(*fun_userdata_type8)(void*, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type with user data (not null) used for functions with nine arguments. */ + typedef value_type(*fun_userdata_type9)(void*, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type with user data (not null) used for functions with ten arguments. */ + typedef value_type(*fun_userdata_type10)(void*, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions without arguments. */ + typedef value_type(*bulkfun_type0)(int, int); + + /** \brief Callback type used for functions with a single arguments. */ + typedef value_type(*bulkfun_type1)(int, int, value_type); + + /** \brief Callback type used for functions with two arguments. */ + typedef value_type(*bulkfun_type2)(int, int, value_type, value_type); + + /** \brief Callback type used for functions with three arguments. */ + typedef value_type(*bulkfun_type3)(int, int, value_type, value_type, value_type); + + /** \brief Callback type used for functions with four arguments. */ + typedef value_type(*bulkfun_type4)(int, int, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions with five arguments. */ + typedef value_type(*bulkfun_type5)(int, int, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions with six arguments. */ + typedef value_type(*bulkfun_type6)(int, int, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions with seven arguments. */ + typedef value_type(*bulkfun_type7)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions with eight arguments. */ + typedef value_type(*bulkfun_type8)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions with nine arguments. */ + typedef value_type(*bulkfun_type9)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions with ten arguments. */ + typedef value_type(*bulkfun_type10)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type with user data (not null) used for functions without arguments. */ + typedef value_type(*bulkfun_userdata_type0)(void*, int, int); + + /** \brief Callback type with user data (not null) used for functions with a single arguments. */ + typedef value_type(*bulkfun_userdata_type1)(void*, int, int, value_type); + + /** \brief Callback type with user data (not null) used for functions with two arguments. */ + typedef value_type(*bulkfun_userdata_type2)(void*, int, int, value_type, value_type); + + /** \brief Callback type with user data (not null) used for functions with three arguments. */ + typedef value_type(*bulkfun_userdata_type3)(void*, int, int, value_type, value_type, value_type); + + /** \brief Callback type with user data (not null) used for functions with four arguments. */ + typedef value_type(*bulkfun_userdata_type4)(void*, int, int, value_type, value_type, value_type, value_type); + + /** \brief Callback type with user data (not null) used for functions with five arguments. */ + typedef value_type(*bulkfun_userdata_type5)(void*, int, int, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type with user data (not null) used for functions with six arguments. */ + typedef value_type(*bulkfun_userdata_type6)(void*, int, int, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type with user data (not null) used for functions with seven arguments. */ + typedef value_type(*bulkfun_userdata_type7)(void*, int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type with user data (not null) used for functions with eight arguments. */ + typedef value_type(*bulkfun_userdata_type8)(void*, int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type with user data (not null) used for functions with nine arguments. */ + typedef value_type(*bulkfun_userdata_type9)(void*, int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type with user data (not null) used for functions with ten arguments. */ + typedef value_type(*bulkfun_userdata_type10)(void*, int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions with a variable argument list. */ + typedef value_type(*multfun_type)(const value_type*, int); + + /** \brief Callback type with user data (not null) used for functions and a variable argument list. */ + typedef value_type(*multfun_userdata_type)(void*, const value_type*, int); + + /** \brief Callback type used for functions taking a string as an argument. */ + typedef value_type(*strfun_type1)(const char_type*); + + /** \brief Callback type used for functions taking a string and a value as arguments. */ + typedef value_type(*strfun_type2)(const char_type*, value_type); + + /** \brief Callback type used for functions taking a string and two values as arguments. */ + typedef value_type(*strfun_type3)(const char_type*, value_type, value_type); + + /** \brief Callback type used for functions taking a string and three values as arguments. */ + typedef value_type(*strfun_type4)(const char_type*, value_type, value_type, value_type); + + /** \brief Callback type used for functions taking a string and four values as arguments. */ + typedef value_type(*strfun_type5)(const char_type*, value_type, value_type, value_type, value_type); + + /** \brief Callback type used for functions taking a string and five values as arguments. */ + typedef value_type(*strfun_type6)(const char_type*, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback type with user data (not null) used for functions taking a string as an argument. */ + typedef value_type(*strfun_userdata_type1)(void*, const char_type*); + + /** \brief Callback type with user data (not null) used for functions taking a string and a value as arguments. */ + typedef value_type(*strfun_userdata_type2)(void*, const char_type*, value_type); + + /** \brief Callback type with user data (not null) used for functions taking a string and two values as arguments. */ + typedef value_type(*strfun_userdata_type3)(void*, const char_type*, value_type, value_type); + + /** \brief Callback type with user data (not null) used for functions taking a string and a value as arguments. */ + typedef value_type(*strfun_userdata_type4)(void*, const char_type*, value_type, value_type, value_type); + + /** \brief Callback type with user data (not null) used for functions taking a string and two values as arguments. */ + typedef value_type(*strfun_userdata_type5)(void*, const char_type*, value_type, value_type, value_type, value_type); + + /** \brief Callback type with user data (not null) used for functions taking a string and five values as arguments. */ + typedef value_type(*strfun_userdata_type6)(void*, const char_type*, value_type, value_type, value_type, value_type, value_type); + + /** \brief Callback used for functions that identify values in a string. */ + typedef int (*identfun_type)(const char_type* sExpr, int* nPos, value_type* fVal); + + /** \brief Callback used for variable creation factory functions. */ + typedef value_type* (*facfun_type)(const char_type*, void*); + + static const int MaxLenExpression = 20000; + static const int MaxLenIdentifier = 100; + static const string_type ParserVersion = string_type(_T("2.3.5 (Release)")); + static const string_type ParserVersionDate = string_type(_T("20241213")); +} // end of namespace + +#if defined(_MSC_VER) + #pragma warning(pop) +#endif + +#endif + diff --git a/3rdparty/muparser/muParserError.cpp b/3rdparty/muparser/muParserError.cpp index 6fe4e1d2..4312dc6d 100644 --- a/3rdparty/muparser/muParserError.cpp +++ b/3rdparty/muparser/muParserError.cpp @@ -1,337 +1,336 @@ /* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2011 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + _____ __ _____________ _______ ______ ___________ + / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ + | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ + |__|_| /____/| __(____ /__| /____ >\___ >__| + \/ |__| \/ \/ \/ + Copyright (C) 2004 - 2022 Ingo Berg + + Redistribution and use in source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + #include "muParserError.h" +#include +#if defined(_MSC_VER) + #pragma warning(push) + #pragma warning(disable : 26812) // MSVC wants to force me te use enum classes or bother me with pointless warnings +#endif namespace mu { - const ParserErrorMsg ParserErrorMsg::m_Instance; - - //------------------------------------------------------------------------------ - const ParserErrorMsg& ParserErrorMsg::Instance() - { - return m_Instance; - } - - //------------------------------------------------------------------------------ - string_type ParserErrorMsg::operator[](unsigned a_iIdx) const - { - return (a_iIdx \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2004-2011 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef MU_PARSER_ERROR_H -#define MU_PARSER_ERROR_H - -#include -#include -#include -#include -#include -#include - -#include "muParserDef.h" - -/** \file - \brief This file defines the error class used by the parser. -*/ - -namespace mu -{ - -/** \brief Error codes. */ -enum EErrorCodes -{ - // Formula syntax errors - ecUNEXPECTED_OPERATOR = 0, ///< Unexpected binary operator found - ecUNASSIGNABLE_TOKEN = 1, ///< Token cant be identified. - ecUNEXPECTED_EOF = 2, ///< Unexpected end of formula. (Example: "2+sin(") - ecUNEXPECTED_ARG_SEP = 3, ///< An unexpected comma has been found. (Example: "1,23") - ecUNEXPECTED_ARG = 4, ///< An unexpected argument has been found - ecUNEXPECTED_VAL = 5, ///< An unexpected value token has been found - ecUNEXPECTED_VAR = 6, ///< An unexpected variable token has been found - ecUNEXPECTED_PARENS = 7, ///< Unexpected Parenthesis, opening or closing - ecUNEXPECTED_STR = 8, ///< A string has been found at an inapropriate position - ecSTRING_EXPECTED = 9, ///< A string function has been called with a different type of argument - ecVAL_EXPECTED = 10, ///< A numerical function has been called with a non value type of argument - ecMISSING_PARENS = 11, ///< Missing parens. (Example: "3*sin(3") - ecUNEXPECTED_FUN = 12, ///< Unexpected function found. (Example: "sin(8)cos(9)") - ecUNTERMINATED_STRING = 13, ///< unterminated string constant. (Example: "3*valueof("hello)") - ecTOO_MANY_PARAMS = 14, ///< Too many function parameters - ecTOO_FEW_PARAMS = 15, ///< Too few function parameters. (Example: "ite(1<2,2)") - ecOPRT_TYPE_CONFLICT = 16, ///< binary operators may only be applied to value items of the same type - ecSTR_RESULT = 17, ///< result is a string - - // Invalid Parser input Parameters - ecINVALID_NAME = 18, ///< Invalid function, variable or constant name. - ecINVALID_BINOP_IDENT = 19, ///< Invalid binary operator identifier - ecINVALID_INFIX_IDENT = 20, ///< Invalid function, variable or constant name. - ecINVALID_POSTFIX_IDENT = 21, ///< Invalid function, variable or constant name. - - ecBUILTIN_OVERLOAD = 22, ///< Trying to overload builtin operator - ecINVALID_FUN_PTR = 23, ///< Invalid callback function pointer - ecINVALID_VAR_PTR = 24, ///< Invalid variable pointer - ecEMPTY_EXPRESSION = 25, ///< The Expression is empty - ecNAME_CONFLICT = 26, ///< Name conflict - ecOPT_PRI = 27, ///< Invalid operator priority - // - ecDOMAIN_ERROR = 28, ///< catch division by zero, sqrt(-1), log(0) (currently unused) - ecDIV_BY_ZERO = 29, ///< Division by zero (currently unused) - ecGENERIC = 30, ///< Generic error - ecLOCALE = 31, ///< Conflict with current locale - - ecUNEXPECTED_CONDITIONAL = 32, - ecMISSING_ELSE_CLAUSE = 33, - ecMISPLACED_COLON = 34, - - ecUNREASONABLE_NUMBER_OF_COMPUTATIONS = 35, - - // internal errors - ecINTERNAL_ERROR = 36, ///< Internal error of any kind. - - // The last two are special entries - ecCOUNT, ///< This is no error code, It just stores just the total number of error codes - ecUNDEFINED = -1 ///< Undefined message, placeholder to detect unassigned error messages -}; - -//--------------------------------------------------------------------------- -/** \brief A class that handles the error messages. -*/ -class ParserErrorMsg -{ -public: - typedef ParserErrorMsg self_type; - - ParserErrorMsg& operator=(const ParserErrorMsg &); - ParserErrorMsg(const ParserErrorMsg&); - ParserErrorMsg(); - - ~ParserErrorMsg(); - - static const ParserErrorMsg& Instance(); - string_type operator[](unsigned a_iIdx) const; - -private: - std::vector m_vErrMsg; ///< A vector with the predefined error messages - static const self_type m_Instance; ///< The instance pointer -}; - -//--------------------------------------------------------------------------- -/** \brief Error class of the parser. - \author Ingo Berg - - Part of the math parser package. -*/ -class ParserError -{ -private: - - /** \brief Replace all ocuurences of a substring with another string. */ - void ReplaceSubString( string_type &strSource, - const string_type &strFind, - const string_type &strReplaceWith); - void Reset(); - -public: - - ParserError(); - explicit ParserError(EErrorCodes a_iErrc); - explicit ParserError(const string_type &sMsg); - ParserError( EErrorCodes a_iErrc, - const string_type &sTok, - const string_type &sFormula = string_type(), - int a_iPos = -1); - ParserError( EErrorCodes a_iErrc, - int a_iPos, - const string_type &sTok); - ParserError( const char_type *a_szMsg, - int a_iPos = -1, - const string_type &sTok = string_type()); - ParserError(const ParserError &a_Obj); - ParserError& operator=(const ParserError &a_Obj); - ~ParserError(); - - void SetFormula(const string_type &a_strFormula); - const string_type& GetExpr() const; - const string_type& GetMsg() const; - int GetPos() const; - const string_type& GetToken() const; - EErrorCodes GetCode() const; - -private: - string_type m_strMsg; ///< The message string - string_type m_strFormula; ///< Formula string - string_type m_strTok; ///< Token related with the error - int m_iPos; ///< Formula position related to the error - EErrorCodes m_iErrc; ///< Error code - const ParserErrorMsg &m_ErrMsg; -}; - -} // namespace mu - -#endif - +/* + + _____ __ _____________ _______ ______ ___________ + / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ + | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ + |__|_| /____/| __(____ /__| /____ >\___ >__| + \/ |__| \/ \/ \/ + Copyright (C) 2004 - 2022 Ingo Berg + + Redistribution and use in source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef MU_PARSER_ERROR_H +#define MU_PARSER_ERROR_H + +#include +#include +#include +#include +#include + +#include "muParserDef.h" + +#if defined(_MSC_VER) + #pragma warning(push) + #pragma warning(disable : 4251) // ...needs to have dll-interface to be used by clients of class ... +#endif + + +/** \file + \brief This file defines the error class used by the parser. +*/ + +namespace mu +{ + /** \brief A class that handles the error messages. */ + class ParserErrorMsg final + { + public: + static const ParserErrorMsg& Instance(); + string_type operator[](unsigned a_iIdx) const; + + private: + ParserErrorMsg& operator=(const ParserErrorMsg&) = delete; + ParserErrorMsg(const ParserErrorMsg&) = delete; + ParserErrorMsg(); + + ~ParserErrorMsg() = default; + + std::vector m_vErrMsg; ///< A vector with the predefined error messages + }; + + + /** \brief Error class of the parser. + + Part of the math parser package. + */ + class API_EXPORT_CXX ParserError + { + private: + + /** \brief Replace all ocuurences of a substring with another string. */ + void ReplaceSubString(string_type& strSource, const string_type& strFind, const string_type& strReplaceWith); + void Reset(); + + public: + + ParserError(); + explicit ParserError(EErrorCodes a_iErrc); + explicit ParserError(const string_type& sMsg); + ParserError(EErrorCodes a_iErrc, const string_type& sTok, const string_type& sFormula = string_type(), int a_iPos = -1); + ParserError(EErrorCodes a_iErrc, int a_iPos, const string_type& sTok); + ParserError(const char_type* a_szMsg, int a_iPos = -1, const string_type& sTok = string_type()); + ParserError(const ParserError& a_Obj); + + ParserError& operator=(const ParserError& a_Obj); + ~ParserError(); + + void SetFormula(const string_type& a_strFormula); + const string_type& GetExpr() const; + const string_type& GetMsg() const; + int GetPos() const; + const string_type& GetToken() const; + EErrorCodes GetCode() const; + + private: + string_type m_strMsg; ///< The message string + string_type m_strFormula; ///< Formula string + string_type m_strTok; ///< Token related with the error + int m_iPos; ///< Formula position related to the error + EErrorCodes m_iErrc; ///< Error code + const ParserErrorMsg& m_ErrMsg; + }; +} // namespace mu + +#if defined(_MSC_VER) + #pragma warning(pop) +#endif + +#endif + diff --git a/3rdparty/muparser/muParserFixes.h b/3rdparty/muparser/muParserFixes.h index 1cd15e02..afcd6bdf 100644 --- a/3rdparty/muparser/muParserFixes.h +++ b/3rdparty/muparser/muParserFixes.h @@ -1,62 +1,90 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2013 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef MU_PARSER_FIXES_H -#define MU_PARSER_FIXES_H - -/** \file - \brief This file contains compatibility fixes for some platforms. -*/ - -// -// Compatibility fixes -// - -//--------------------------------------------------------------------------- -// -// Intel Compiler -// -//--------------------------------------------------------------------------- - -#ifdef __INTEL_COMPILER - -// remark #981: operands are evaluated in unspecified order -// disabled -> completely pointless if the functions do not have side effects -// -#pragma warning(disable:981) - -// remark #383: value copied to temporary, reference to temporary used -#pragma warning(disable:383) - -// remark #1572: floating-point equality and inequality comparisons are unreliable -// disabled -> everyone knows it, the parser passes this problem -// deliberately to the user -#pragma warning(disable:1572) - -#endif - -#endif // include guard - - +/* + + _____ __ _____________ _______ ______ ___________ + / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ + | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ + |__|_| /____/| __(____ /__| /____ >\___ >__| + \/ |__| \/ \/ \/ + Copyright (C) 2004 - 2022 Ingo Berg + + Redistribution and use in source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef MU_PARSER_FIXES_H +#define MU_PARSER_FIXES_H + +/** \file + \brief This file contains compatibility fixes for some platforms. +*/ + +// +// Compatibility fixes +// + +/* From http://gcc.gnu.org/wiki/Visibility */ +/* Generic helper definitions for shared library support */ +#if defined _WIN32 || defined __CYGWIN__ + #define MUPARSER_HELPER_DLL_IMPORT __declspec(dllimport) + #define MUPARSER_HELPER_DLL_EXPORT __declspec(dllexport) + #define MUPARSER_HELPER_DLL_LOCAL +#else + #if __GNUC__ >= 4 + #define MUPARSER_HELPER_DLL_IMPORT __attribute__ ((visibility ("default"))) + #define MUPARSER_HELPER_DLL_EXPORT __attribute__ ((visibility ("default"))) + #define MUPARSER_HELPER_DLL_LOCAL __attribute__ ((visibility ("hidden"))) + #else + #define MUPARSER_HELPER_DLL_IMPORT + #define MUPARSER_HELPER_DLL_EXPORT + #define MUPARSER_HELPER_DLL_LOCAL + #endif +#endif + +/* + Now we use the generic helper definitions above to define API_EXPORT_CXX and MUPARSER_LOCAL. + API_EXPORT_CXX is used for the public API symbols. It either DLL imports or DLL exports (or does nothing for static build) + MUPARSER_LOCAL is used for non-api symbols. +*/ + +#ifndef MUPARSER_STATIC /* defined if muParser is compiled as a DLL */ + + #ifdef MUPARSERLIB_EXPORTS /* defined if we are building the muParser DLL (instead of using it) */ + #define API_EXPORT_CXX MUPARSER_HELPER_DLL_EXPORT + #else + #define API_EXPORT_CXX MUPARSER_HELPER_DLL_IMPORT + #endif /* MUPARSER_DLL_EXPORTS */ + #define MUPARSER_LOCAL MUPARSER_HELPER_DLL_LOCAL + +#else /* MUPARSER_STATIC is defined: this means muParser is a static lib. */ + + #define API_EXPORT_CXX + #define MUPARSER_LOCAL + +#endif /* !MUPARSER_STATIC */ + + +#ifdef _WIN32 + #define API_EXPORT(TYPE) API_EXPORT_CXX TYPE __cdecl +#else + #define API_EXPORT(TYPE) TYPE +#endif + + +#endif // include guard + + diff --git a/3rdparty/muparser/muParserInt.cpp b/3rdparty/muparser/muParserInt.cpp index 8b5aae60..33a1db80 100644 --- a/3rdparty/muparser/muParserInt.cpp +++ b/3rdparty/muparser/muParserInt.cpp @@ -1,280 +1,280 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2011 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "muParserInt.h" - -#include -#include -#include - -using namespace std; - -/** \file - \brief Implementation of a parser using integer value. -*/ - -/** \brief Namespace for mathematical applications. */ -namespace mu -{ -value_type ParserInt::Abs(value_type v) { return (value_type)Round(fabs((double)v)); } -value_type ParserInt::Sign(value_type v) { return (Round(v)<0) ? -1 : (Round(v)>0) ? 1 : 0; } -value_type ParserInt::Ite(value_type v1, - value_type v2, - value_type v3) { return (Round(v1)==1) ? Round(v2) : Round(v3); } -value_type ParserInt::Add(value_type v1, value_type v2) { return Round(v1) + Round(v2); } -value_type ParserInt::Sub(value_type v1, value_type v2) { return Round(v1) - Round(v2); } -value_type ParserInt::Mul(value_type v1, value_type v2) { return Round(v1) * Round(v2); } -value_type ParserInt::Div(value_type v1, value_type v2) { return Round(v1) / Round(v2); } -value_type ParserInt::Mod(value_type v1, value_type v2) { return Round(v1) % Round(v2); } -value_type ParserInt::Shr(value_type v1, value_type v2) { return Round(v1) >> Round(v2); } -value_type ParserInt::Shl(value_type v1, value_type v2) { return Round(v1) << Round(v2); } -value_type ParserInt::LogAnd(value_type v1, value_type v2) { return Round(v1) & Round(v2); } -value_type ParserInt::LogOr(value_type v1, value_type v2) { return Round(v1) | Round(v2); } -value_type ParserInt::And(value_type v1, value_type v2) { return Round(v1) && Round(v2); } -value_type ParserInt::Or(value_type v1, value_type v2) { return Round(v1) || Round(v2); } -value_type ParserInt::Less(value_type v1, value_type v2) { return Round(v1) < Round(v2); } -value_type ParserInt::Greater(value_type v1, value_type v2) { return Round(v1) > Round(v2); } -value_type ParserInt::LessEq(value_type v1, value_type v2) { return Round(v1) <= Round(v2); } -value_type ParserInt::GreaterEq(value_type v1, value_type v2) { return Round(v1) >= Round(v2); } -value_type ParserInt::Equal(value_type v1, value_type v2) { return Round(v1) == Round(v2); } -value_type ParserInt::NotEqual(value_type v1, value_type v2) { return Round(v1) != Round(v2); } -value_type ParserInt::Not(value_type v) { return !Round(v); } - -value_type ParserInt::Pow(value_type v1, value_type v2) -{ - return std::pow((double)Round(v1), (double)Round(v2)); -} - -//--------------------------------------------------------------------------- -// Unary operator Callbacks: Infix operators -value_type ParserInt::UnaryMinus(value_type v) -{ - return -Round(v); -} - -//--------------------------------------------------------------------------- -value_type ParserInt::Sum(const value_type* a_afArg, int a_iArgc) -{ - if (!a_iArgc) - throw ParserError(_T("too few arguments for function sum.")); - - value_type fRes=0; - for (int i=0; i> iVal; - if (stream.fail()) - return 0; - - stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading - if (stream.fail()) - iEnd = stream.str().length(); - - if (iEnd==(stringstream_type::pos_type)-1) - return 0; - - *a_iPos += (int)iEnd; - *a_fVal = (value_type)iVal; - return 1; -} - -//--------------------------------------------------------------------------- -/** \brief Check a given position in the expression for the presence of - a hex value. - \param a_szExpr Pointer to the expression string - \param [in/out] a_iPos Pointer to an integer value holding the current parsing - position in the expression. - \param [out] a_fVal Pointer to the position where the detected value shall be stored. - - Hey values must be prefixed with "0x" in order to be detected properly. -*/ -int ParserInt::IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal) -{ - if (a_szExpr[1]==0 || (a_szExpr[0]!='0' || a_szExpr[1]!='x') ) - return 0; - - unsigned iVal(0); - - // New code based on streams for UNICODE compliance: - stringstream_type::pos_type nPos(0); - stringstream_type ss(a_szExpr + 2); - ss >> std::hex >> iVal; - nPos = ss.tellg(); - - if (nPos==(stringstream_type::pos_type)0) - return 1; - - *a_iPos += (int)(2 + nPos); - *a_fVal = (value_type)iVal; - return 1; -} - -//--------------------------------------------------------------------------- -int ParserInt::IsBinVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal) -{ - if (a_szExpr[0]!='#') - return 0; - - unsigned iVal(0), - iBits(sizeof(iVal)*8), - i(0); - - for (i=0; (a_szExpr[i+1]=='0' || a_szExpr[i+1]=='1') && i> (iBits-i) ); - *a_iPos += i+1; - - return 1; -} - -//--------------------------------------------------------------------------- -/** \brief Constructor. - - Call ParserBase class constructor and trigger Function, Operator and Constant initialization. -*/ -ParserInt::ParserInt() - :ParserBase() -{ - AddValIdent(IsVal); // lowest priority - AddValIdent(IsBinVal); - AddValIdent(IsHexVal); // highest priority - - InitCharSets(); - InitFun(); - InitOprt(); -} - -//--------------------------------------------------------------------------- -void ParserInt::InitConst() -{ -} - -//--------------------------------------------------------------------------- -void ParserInt::InitCharSets() -{ - DefineNameChars( _T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") ); - DefineOprtChars( _T("+-*^/?<>=!%&|~'_") ); - DefineInfixOprtChars( _T("/+-*^?<>=!%&|~'_") ); -} - -//--------------------------------------------------------------------------- -/** \brief Initialize the default functions. */ -void ParserInt::InitFun() -{ - DefineFun( _T("sign"), Sign); - DefineFun( _T("abs"), Abs); - DefineFun( _T("if"), Ite); - DefineFun( _T("sum"), Sum); - DefineFun( _T("min"), Min); - DefineFun( _T("max"), Max); -} - -//--------------------------------------------------------------------------- -/** \brief Initialize operators. */ -void ParserInt::InitOprt() -{ - // disable all built in operators, not all of them useful for integer numbers - // (they don't do rounding of values) - EnableBuiltInOprt(false); - - // Disable all built in operators, they wont work with integer numbers - // since they are designed for floating point numbers - DefineInfixOprt( _T("-"), UnaryMinus); - DefineInfixOprt( _T("!"), Not); - - DefineOprt( _T("&"), LogAnd, prLOGIC); - DefineOprt( _T("|"), LogOr, prLOGIC); - DefineOprt( _T("&&"), And, prLOGIC); - DefineOprt( _T("||"), Or, prLOGIC); - - DefineOprt( _T("<"), Less, prCMP); - DefineOprt( _T(">"), Greater, prCMP); - DefineOprt( _T("<="), LessEq, prCMP); - DefineOprt( _T(">="), GreaterEq, prCMP); - DefineOprt( _T("=="), Equal, prCMP); - DefineOprt( _T("!="), NotEqual, prCMP); - - DefineOprt( _T("+"), Add, prADD_SUB); - DefineOprt( _T("-"), Sub, prADD_SUB); - - DefineOprt( _T("*"), Mul, prMUL_DIV); - DefineOprt( _T("/"), Div, prMUL_DIV); - DefineOprt( _T("%"), Mod, prMUL_DIV); - - DefineOprt( _T("^"), Pow, prPOW, oaRIGHT); - DefineOprt( _T(">>"), Shr, prMUL_DIV+1); - DefineOprt( _T("<<"), Shl, prMUL_DIV+1); -} - -} // namespace mu +/* + + _____ __ _____________ _______ ______ ___________ + / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ + | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ + |__|_| /____/| __(____ /__| /____ >\___ >__| + \/ |__| \/ \/ \/ + Copyright (C) 2004 - 2022 Ingo Berg + + Redistribution and use in source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "muParserInt.h" + +#include +#include +#include + +using namespace std; + +/** \file + \brief Implementation of a parser using integer value. +*/ + +/** \brief Namespace for mathematical applications. */ +namespace mu +{ + value_type ParserInt::Abs(value_type v) { return (value_type)Round(fabs((double)v)); } + value_type ParserInt::Sign(value_type v) { return (Round(v) < 0) ? -1 : (Round(v) > 0) ? 1 : 0; } + value_type ParserInt::Ite(value_type v1, value_type v2, value_type v3) { return (Round(v1) == 1) ? Round(v2) : Round(v3); } + value_type ParserInt::Add(value_type v1, value_type v2) { return Round(v1) + Round(v2); } + value_type ParserInt::Sub(value_type v1, value_type v2) { return Round(v1) - Round(v2); } + value_type ParserInt::Mul(value_type v1, value_type v2) { return Round(v1) * Round(v2); } + value_type ParserInt::Div(value_type v1, value_type v2) { return Round(v1) / Round(v2); } + value_type ParserInt::Mod(value_type v1, value_type v2) { return Round(v1) % Round(v2); } + value_type ParserInt::Shr(value_type v1, value_type v2) { return Round(v1) >> Round(v2); } + value_type ParserInt::Shl(value_type v1, value_type v2) { return Round(v1) << Round(v2); } + value_type ParserInt::BitAnd(value_type v1, value_type v2) { return Round(v1) & Round(v2); } + value_type ParserInt::BitOr(value_type v1, value_type v2) { return Round(v1) | Round(v2); } + value_type ParserInt::And(value_type v1, value_type v2) { return Round(v1) && Round(v2); } + value_type ParserInt::Or(value_type v1, value_type v2) { return Round(v1) || Round(v2); } + value_type ParserInt::Less(value_type v1, value_type v2) { return Round(v1) < Round(v2); } + value_type ParserInt::Greater(value_type v1, value_type v2) { return Round(v1) > Round(v2); } + value_type ParserInt::LessEq(value_type v1, value_type v2) { return Round(v1) <= Round(v2); } + value_type ParserInt::GreaterEq(value_type v1, value_type v2) { return Round(v1) >= Round(v2); } + value_type ParserInt::Equal(value_type v1, value_type v2) { return Round(v1) == Round(v2); } + value_type ParserInt::NotEqual(value_type v1, value_type v2) { return Round(v1) != Round(v2); } + value_type ParserInt::Not(value_type v) { return !Round(v); } + + value_type ParserInt::Pow(value_type v1, value_type v2) + { + return std::pow((double)Round(v1), (double)Round(v2)); + } + + + value_type ParserInt::UnaryMinus(value_type v) + { + return -Round(v); + } + + + value_type ParserInt::Sum(const value_type* a_afArg, int a_iArgc) + { + if (!a_iArgc) + throw ParserError(_T("too few arguments for function sum.")); + + value_type fRes = 0; + for (int i = 0; i < a_iArgc; ++i) + fRes += a_afArg[i]; + + return fRes; + } + + + value_type ParserInt::Min(const value_type* a_afArg, int a_iArgc) + { + if (!a_iArgc) + throw ParserError(_T("too few arguments for function min.")); + + value_type fRes = a_afArg[0]; + for (int i = 0; i < a_iArgc; ++i) + fRes = std::min(fRes, a_afArg[i]); + + return fRes; + } + + + value_type ParserInt::Max(const value_type* a_afArg, int a_iArgc) + { + if (!a_iArgc) + throw ParserError(_T("too few arguments for function min.")); + + value_type fRes = a_afArg[0]; + for (int i = 0; i < a_iArgc; ++i) + fRes = std::max(fRes, a_afArg[i]); + + return fRes; + } + + + int ParserInt::IsVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal) + { + string_type buf(a_szExpr); + std::size_t pos = buf.find_first_not_of(_T("0123456789")); + + if (pos == std::string::npos) + return 0; + + stringstream_type stream(buf.substr(0, pos)); + int iVal(0); + + stream >> iVal; + if (stream.fail()) + return 0; + + stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading + if (stream.fail()) + iEnd = stream.str().length(); + + if (iEnd == (stringstream_type::pos_type) - 1) + return 0; + + *a_iPos += (int)iEnd; + *a_fVal = (value_type)iVal; + return 1; + } + + + /** \brief Check a given position in the expression for the presence of + a hex value. + \param a_szExpr Pointer to the expression string + \param [in/out] a_iPos Pointer to an integer value holding the current parsing + position in the expression. + \param [out] a_fVal Pointer to the position where the detected value shall be stored. + + Hey values must be prefixed with "0x" in order to be detected properly. + */ + int ParserInt::IsHexVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal) + { + if (a_szExpr[1] == 0 || (a_szExpr[0] != '0' || a_szExpr[1] != 'x')) + return 0; + + unsigned iVal(0); + + // New code based on streams for UNICODE compliance: + stringstream_type::pos_type nPos(0); + stringstream_type ss(a_szExpr + 2); + ss >> std::hex >> iVal; + nPos = ss.tellg(); + + if (nPos == (stringstream_type::pos_type)0) + return 1; + + *a_iPos += (int)(2 + nPos); + *a_fVal = (value_type)iVal; + return 1; + } + + + int ParserInt::IsBinVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal) + { + if (a_szExpr[0] != '#') + return 0; + + unsigned iVal(0), + iBits(sizeof(iVal) * 8), + i(0); + + for (i = 0; (a_szExpr[i + 1] == '0' || a_szExpr[i + 1] == '1') && i < iBits; ++i) + iVal |= (int)(a_szExpr[i + 1] == '1') << ((iBits - 1) - i); + + if (i == 0) + return 0; + + if (i == iBits) + throw exception_type(_T("Binary to integer conversion error (overflow).")); + + *a_fVal = (unsigned)(iVal >> (iBits - i)); + *a_iPos += i + 1; + + return 1; + } + + + /** \brief Constructor. + + Call ParserBase class constructor and trigger Function, Operator and Constant initialization. + */ + ParserInt::ParserInt() + :ParserBase() + { + AddValIdent(IsVal); // lowest priority + AddValIdent(IsBinVal); + AddValIdent(IsHexVal); // highest priority + + InitCharSets(); + InitFun(); + InitOprt(); + } + + + void ParserInt::InitConst() + { + } + + + void ParserInt::InitCharSets() + { + DefineNameChars(_T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")); + DefineOprtChars(_T("+-*^/?<>=!%&|~'_")); + DefineInfixOprtChars(_T("/+-*^?<>=!%&|~'_")); + } + + + /** \brief Initialize the default functions. */ + void ParserInt::InitFun() + { + DefineFun(_T("sign"), Sign); + DefineFun(_T("abs"), Abs); + DefineFun(_T("if"), Ite); + DefineFun(_T("sum"), Sum); + DefineFun(_T("min"), Min); + DefineFun(_T("max"), Max); + } + + + /** \brief Initialize operators. */ + void ParserInt::InitOprt() + { + // disable all built in operators, not all of them useful for integer numbers + // (they don't do rounding of values) + EnableBuiltInOprt(false); + + // Disable all built in operators, they won't work with integer numbers + // since they are designed for floating point numbers + DefineInfixOprt(_T("-"), UnaryMinus); + DefineInfixOprt(_T("!"), Not); + + DefineOprt(_T("&"), BitAnd, prBAND); + DefineOprt(_T("|"), BitOr, prBOR); + + DefineOprt(_T("&&"), And, prLAND); + DefineOprt(_T("||"), Or, prLOR); + + DefineOprt(_T("<"), Less, prCMP); + DefineOprt(_T(">"), Greater, prCMP); + DefineOprt(_T("<="), LessEq, prCMP); + DefineOprt(_T(">="), GreaterEq, prCMP); + DefineOprt(_T("=="), Equal, prCMP); + DefineOprt(_T("!="), NotEqual, prCMP); + + DefineOprt(_T("+"), Add, prADD_SUB); + DefineOprt(_T("-"), Sub, prADD_SUB); + + DefineOprt(_T("*"), Mul, prMUL_DIV); + DefineOprt(_T("/"), Div, prMUL_DIV); + DefineOprt(_T("%"), Mod, prMUL_DIV); + + DefineOprt(_T("^"), Pow, prPOW, oaRIGHT); + DefineOprt(_T(">>"), Shr, prMUL_DIV + 1); + DefineOprt(_T("<<"), Shl, prMUL_DIV + 1); + } + +} // namespace mu diff --git a/3rdparty/muparser/muParserInt.h b/3rdparty/muparser/muParserInt.h new file mode 100644 index 00000000..cad708f4 --- /dev/null +++ b/3rdparty/muparser/muParserInt.h @@ -0,0 +1,143 @@ +/* + + _____ __ _____________ _______ ______ ___________ + / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ + | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ + |__|_| /____/| __(____ /__| /____ >\___ >__| + \/ |__| \/ \/ \/ + Copyright (C) 2004 - 2022 Ingo Berg + + Redistribution and use in source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef MU_PARSER_INT_H +#define MU_PARSER_INT_H + +#include "muParserBase.h" +#include + + +/** \file + \brief Definition of a parser using integer value. +*/ + + +namespace mu +{ + + /** \brief Mathematical expressions parser. + + This version of the parser handles only integer numbers. It disables the built in operators thus it is + slower than muParser. Integer values are stored in the double value_type and converted if needed. + */ + class ParserInt : public ParserBase + { + private: + static int Round(value_type v) { return (int)(v + ((v >= 0) ? 0.5 : -0.5)); }; + + static value_type Abs(value_type); + static value_type Sign(value_type); + static value_type Ite(value_type, value_type, value_type); + // !! The unary Minus is a MUST, otherwise you can't use negative signs !! + static value_type UnaryMinus(value_type); + // Functions with variable number of arguments + static value_type Sum(const value_type* a_afArg, int a_iArgc); // sum + static value_type Min(const value_type* a_afArg, int a_iArgc); // minimum + static value_type Max(const value_type* a_afArg, int a_iArgc); // maximum + // binary operator callbacks + static value_type Add(value_type v1, value_type v2); + static value_type Sub(value_type v1, value_type v2); + static value_type Mul(value_type v1, value_type v2); + static value_type Div(value_type v1, value_type v2); + static value_type Mod(value_type v1, value_type v2); + static value_type Pow(value_type v1, value_type v2); + static value_type Shr(value_type v1, value_type v2); + static value_type Shl(value_type v1, value_type v2); + static value_type BitAnd(value_type v1, value_type v2); + static value_type BitOr(value_type v1, value_type v2); + static value_type And(value_type v1, value_type v2); + static value_type Or(value_type v1, value_type v2); + static value_type Xor(value_type v1, value_type v2); + static value_type Less(value_type v1, value_type v2); + static value_type Greater(value_type v1, value_type v2); + static value_type LessEq(value_type v1, value_type v2); + static value_type GreaterEq(value_type v1, value_type v2); + static value_type Equal(value_type v1, value_type v2); + static value_type NotEqual(value_type v1, value_type v2); + static value_type Not(value_type v1); + + static int IsHexVal(const char_type* a_szExpr, int* a_iPos, value_type* a_iVal); + static int IsBinVal(const char_type* a_szExpr, int* a_iPos, value_type* a_iVal); + static int IsVal(const char_type* a_szExpr, int* a_iPos, value_type* a_iVal); + + /** \brief A facet class used to change decimal and thousands separator. */ + template + class change_dec_sep : public std::numpunct + { + public: + + explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3) + :std::numpunct() + , m_cDecPoint(cDecSep) + , m_cThousandsSep(cThousandsSep) + , m_nGroup(nGroup) + {} + + protected: + + virtual char_type do_decimal_point() const + { + return m_cDecPoint; + } + + virtual char_type do_thousands_sep() const + { + return m_cThousandsSep; + } + + virtual std::string do_grouping() const + { + // fix for issue 4: https://code.google.com/p/muparser/issues/detail?id=4 + // courtesy of Jens Bartsch + // original code: + // return std::string(1, (char)m_nGroup); + // new code: + return std::string(1, (char)(m_cThousandsSep > 0 ? m_nGroup : CHAR_MAX)); + } + + private: + + int m_nGroup; + char_type m_cDecPoint; + char_type m_cThousandsSep; + }; + + public: + ParserInt(); + + void InitFun() override; + void InitOprt() override; + void InitConst() override; + void InitCharSets() override; + }; + +} // namespace mu + +#endif + diff --git a/3rdparty/muparser/muParserTemplateMagic.h b/3rdparty/muparser/muParserTemplateMagic.h index 1626caea..63645ea0 100644 --- a/3rdparty/muparser/muParserTemplateMagic.h +++ b/3rdparty/muparser/muParserTemplateMagic.h @@ -1,113 +1,208 @@ -#ifndef MU_PARSER_TEMPLATE_MAGIC_H -#define MU_PARSER_TEMPLATE_MAGIC_H - -#include -#include "muParserError.h" - - -namespace mu -{ - //----------------------------------------------------------------------------------------------- - // - // Compile time type detection - // - //----------------------------------------------------------------------------------------------- - - /** \brief A class singling out integer types at compile time using - template meta programming. - */ - template - struct TypeInfo - { - static bool IsInteger() { return false; } - }; - - template<> - struct TypeInfo - { - static bool IsInteger() { return true; } - }; - - template<> - struct TypeInfo - { - static bool IsInteger() { return true; } - }; - - template<> - struct TypeInfo - { - static bool IsInteger() { return true; } - }; - - template<> - struct TypeInfo - { - static bool IsInteger() { return true; } - }; - - template<> - struct TypeInfo - { - static bool IsInteger() { return true; } - }; - - template<> - struct TypeInfo - { - static bool IsInteger() { return true; } - }; - - template<> - struct TypeInfo - { - static bool IsInteger() { return true; } - }; - - template<> - struct TypeInfo - { - static bool IsInteger() { return true; } - }; - - - //----------------------------------------------------------------------------------------------- - // - // Standard math functions with dummy overload for integer types - // - //----------------------------------------------------------------------------------------------- - - /** \brief A template class for providing wrappers for essential math functions. - - This template is spezialized for several types in order to provide a unified interface - for parser internal math function calls regardless of the data type. - */ - template - struct MathImpl - { - static T Sin(T v) { return sin(v); } - static T Cos(T v) { return cos(v); } - static T Tan(T v) { return tan(v); } - static T ASin(T v) { return asin(v); } - static T ACos(T v) { return acos(v); } - static T ATan(T v) { return atan(v); } - static T ATan2(T v1, T v2) { return atan2(v1, v2); } - static T Sinh(T v) { return sinh(v); } - static T Cosh(T v) { return cosh(v); } - static T Tanh(T v) { return tanh(v); } - static T ASinh(T v) { return log(v + sqrt(v * v + 1)); } - static T ACosh(T v) { return log(v + sqrt(v * v - 1)); } - static T ATanh(T v) { return ((T)0.5 * log((1 + v) / (1 - v))); } - static T Log(T v) { return log(v); } - static T Log2(T v) { return log(v)/log((T)2); } // Logarithm base 2 - static T Log10(T v) { return log10(v); } // Logarithm base 10 - static T Exp(T v) { return exp(v); } - static T Abs(T v) { return (v>=0) ? v : -v; } - static T Sqrt(T v) { return sqrt(v); } - static T Rint(T v) { return floor(v + (T)0.5); } - static T Sign(T v) { return (T)((v<0) ? -1 : (v>0) ? 1 : 0); } - static T Pow(T v1, T v2) { return std::pow(v1, v2); } - }; -} - -#endif +/* + + _____ __ _____________ _______ ______ ___________ + / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ + | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ + |__|_| /____/| __(____ /__| /____ >\___ >__| + \/ |__| \/ \/ \/ + Copyright (C) 2004 - 2022 Ingo Berg + + Redistribution and use in source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef MU_PARSER_TEMPLATE_MAGIC_H +#define MU_PARSER_TEMPLATE_MAGIC_H + +#include +#include +#include +#include "muParserError.h" + + +namespace mu +{ + //----------------------------------------------------------------------------------------------- + // + // Compile time type detection + // + //----------------------------------------------------------------------------------------------- + + /** \brief A class singling out integer types at compile time using + template meta programming. + */ + template + struct TypeInfo + { + static bool IsInteger() { return false; } + }; + + template<> + struct TypeInfo + { + static bool IsInteger() { return true; } + }; + + template<> + struct TypeInfo + { + static bool IsInteger() { return true; } + }; + + template<> + struct TypeInfo + { + static bool IsInteger() { return true; } + }; + + template<> + struct TypeInfo + { + static bool IsInteger() { return true; } + }; + + template<> + struct TypeInfo + { + static bool IsInteger() { return true; } + }; + + template<> + struct TypeInfo + { + static bool IsInteger() { return true; } + }; + + template<> + struct TypeInfo + { + static bool IsInteger() { return true; } + }; + + template<> + struct TypeInfo + { + static bool IsInteger() { return true; } + }; + + + //----------------------------------------------------------------------------------------------- + // + // Standard math functions with dummy overload for integer types + // + //----------------------------------------------------------------------------------------------- + + /** \brief A template class for providing wrappers for essential math functions. + + This template is spezialized for several types in order to provide a unified interface + for parser internal math function calls regardless of the data type. + */ + template + struct MathImpl + { + static T Sin(T v) { return sin(v); } + static T Cos(T v) { return cos(v); } + static T Tan(T v) { return tan(v); } + static T ASin(T v) { return asin(v); } + static T ACos(T v) { return acos(v); } + static T ATan(T v) { return atan(v); } + static T ATan2(T v1, T v2) { return atan2(v1, v2); } + static T Sinh(T v) { return sinh(v); } + static T Cosh(T v) { return cosh(v); } + static T Tanh(T v) { return tanh(v); } + static T ASinh(T v) { return log(v + sqrt(v * v + 1)); } + static T ACosh(T v) { return log(v + sqrt(v * v - 1)); } + static T ATanh(T v) { return ((T)0.5 * log((1 + v) / (1 - v))); } + static T Log(T v) { return log(v); } + static T Log2(T v) { return log(v) / log((T)2); } // Logarithm base 2 + static T Log10(T v) { return log10(v); } // Logarithm base 10 + static T Exp(T v) { return exp(v); } + static T Abs(T v) { return (v >= 0) ? v : -v; } + static T Sqrt(T v) { return sqrt(v); } + static T Rint(T v) { return floor(v + (T)0.5); } + static T Sign(T v) { return (T)((v < 0) ? -1 : (v > 0) ? 1 : 0); } + static T Pow(T v1, T v2) { return std::pow(v1, v2); } + static T Rnd() + { + static std::random_device rd; + static std::mt19937 gen(rd()); + static std::uniform_real_distribution dis(0.0, 1.0); // Range [0, 1) + + return dis(gen); + } + + static T UnaryMinus(T v) { return -v; } + static T UnaryPlus(T v) { return v; } + + static T Sum(const T *a_afArg, int a_iArgc) + { + if (!a_iArgc) + throw ParserError(_T("too few arguments for function sum.")); + + T fRes = 0; + for (int i = 0; i < a_iArgc; ++i) fRes += a_afArg[i]; + return fRes; + } + + static T Avg(const T *a_afArg, int a_iArgc) + { + if (!a_iArgc) + throw ParserError(_T("too few arguments for function avg.")); + + T fRes = 0; + for (int i = 0; i < a_iArgc; ++i) fRes += a_afArg[i]; + return fRes / (T)a_iArgc; + } + + static T Min(const T *a_afArg, int a_iArgc) + { + if (!a_iArgc) + throw ParserError(_T("too few arguments for function min.")); + + T fRes = a_afArg[0]; + for (int i = 0; i < a_iArgc; ++i) + fRes = std::min(fRes, a_afArg[i]); + + return fRes; + } + + static T Max(const T *a_afArg, int a_iArgc) + { + if (!a_iArgc) + throw ParserError(_T("too few arguments for function max.")); + + T fRes = a_afArg[0]; + for (int i = 0; i < a_iArgc; ++i) fRes = std::max(fRes, a_afArg[i]); + + return fRes; + } + + +#if defined (__GNUG__) + // Bei zu genauer definition von pi kann die Berechnung von + // sin(pi*a) mit a=1 10 x langsamer sein! + static constexpr T CONST_PI = (T)3.141592653589; +#else + static constexpr T CONST_PI = (T)3.141592653589793238462643; +#endif + + static constexpr T CONST_E = (T)2.718281828459045235360287; + }; +} + +#endif diff --git a/3rdparty/muparser/muParserTest.cpp b/3rdparty/muparser/muParserTest.cpp new file mode 100644 index 00000000..d7461071 --- /dev/null +++ b/3rdparty/muparser/muParserTest.cpp @@ -0,0 +1,1781 @@ +/* + + _____ __ _____________ _______ ______ ___________ + / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ + | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ + |__|_| /____/| __(____ /__| /____ >\___ >__| + \/ |__| \/ \/ \/ + Copyright (C) 2023 Ingo Berg + + Redistribution and use in source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "muParserTest.h" + +#include +#include +#include +#include + +using namespace std; + +/** \file + \brief This file contains the implementation of parser test cases. +*/ + +namespace mu +{ + namespace Test + { + int ParserTester::c_iCount = 0; + + //--------------------------------------------------------------------------------------------- + ParserTester::ParserTester() + :m_vTestFun() + { + AddTest(&ParserTester::TestNames); + AddTest(&ParserTester::TestSyntax); + AddTest(&ParserTester::TestPostFix); + AddTest(&ParserTester::TestInfixOprt); + AddTest(&ParserTester::TestVarConst); + AddTest(&ParserTester::TestMultiArg); + AddTest(&ParserTester::TestExpression); + AddTest(&ParserTester::TestIfThenElse); + AddTest(&ParserTester::TestInterface); + AddTest(&ParserTester::TestBinOprt); + AddTest(&ParserTester::TestException); + AddTest(&ParserTester::TestStrArg); + AddTest(&ParserTester::TestBulkMode); + AddTest(&ParserTester::TestOptimizer); + AddTest(&ParserTester::TestLocalization); + + ParserTester::c_iCount = 0; + } + + //--------------------------------------------------------------------------------------------- + int ParserTester::IsHexVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal) + { + if (a_szExpr[1] == 0 || (a_szExpr[0] != '0' || a_szExpr[1] != 'x')) + return 0; + + unsigned iVal(0); + + // New code based on streams for UNICODE compliance: + stringstream_type::pos_type nPos(0); + stringstream_type ss(a_szExpr + 2); + ss >> std::hex >> iVal; + nPos = ss.tellg(); + + if (nPos == (stringstream_type::pos_type)0) + return 1; + + *a_iPos += (int)(2 + nPos); + *a_fVal = (value_type)iVal; + return 1; + } + + //--------------------------------------------------------------------------------------------- + int ParserTester::TestInterface() + { + int iStat = 0; + mu::console() << _T("testing member functions..."); + + // Test RemoveVar + value_type afVal[3] = { 1,2,3 }; + Parser p; + + try + { + p.DefineVar(_T("a"), &afVal[0]); + p.DefineVar(_T("b"), &afVal[1]); + p.DefineVar(_T("c"), &afVal[2]); + p.SetExpr(_T("a+b+c")); + p.Eval(); + } + catch (...) + { + iStat += 1; // this is not supposed to happen + } + + try + { + p.RemoveVar(_T("c")); + p.Eval(); + iStat += 1; // not supposed to reach this, nonexisting variable "c" deleted... + } + catch (...) + { + // failure is expected... + } + + if (iStat == 0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + return iStat; + } + + //--------------------------------------------------------------------------------------------- + int ParserTester::TestOptimizer() + { + int iStat = 0; + mu::console() << _T("testing optimizer..."); + + // Test RemoveVar + Parser p; + try + { + // test for #93 (https://github.com/beltoforion/muparser/issues/93) + // expected bytecode is: + // VAL, FUN + { + p.DefineFun(_T("unoptimizable"), f1of1, false); + p.SetExpr(_T("unoptimizable(1)")); + p.Eval(); + + auto& bc = p.GetByteCode(); + const SToken* tok = bc.GetBase(); + if (bc.GetSize() != 2 && tok[1].Cmd != cmFUNC) + { + mu::console() << _T("#93 an unoptimizable expression was optimized!") << endl; + iStat += 1; + } + } + + { + p.ClearFun(); + p.DefineFun(_T("unoptimizable"), f1of1, true); + p.SetExpr(_T("unoptimizable(1)")); + p.Eval(); + + auto& bc = p.GetByteCode(); + const SToken* tok = bc.GetBase(); + if (bc.GetSize() != 1 && tok[0].Cmd != cmVAL) + { + mu::console() << _T("#93 optimizer error") << endl; + iStat += 1; + } + } + } + catch (...) + { + iStat += 1; // this is not supposed to happen + } + + if (iStat == 0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + return iStat; + } + + //--------------------------------------------------------------------------------------------- + int ParserTester::TestStrArg() + { + int iStat = 0; + mu::console() << _T("testing string arguments..."); + + // from oss-fuzz: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=23410 + iStat += ThrowTest(_T(R"(6 - 6 ? 4 : "", ? 4 : "", ? 4 : "")"), ecUNEXPECTED_STR, true); + // variations: + iStat += ThrowTest(_T(R"(avg(0?4:(""),1))"), ecUNEXPECTED_STR); + iStat += ThrowTest(_T(R"(1 ? 4 : "")"), ecUNEXPECTED_STR); + iStat += ThrowTest(_T(R"(1 ? "" : 4)"), ecUNEXPECTED_STR); + iStat += ThrowTest(_T(R"(1 ? "" : "")"), ecUNEXPECTED_STR); + iStat += ThrowTest(_T(R"(0 ? 4 : "")"), ecUNEXPECTED_STR); + iStat += ThrowTest(_T(R"(0 ? 4 : (""))"), ecUNEXPECTED_STR); + iStat += ThrowTest(_T(R"(1 ? 4 : "")"), ecUNEXPECTED_STR); + + // from oss-fuzz: https://oss-fuzz.com/testcase-detail/5106868061208576 + iStat += ThrowTest(_T(R"("","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",8)"), ecSTR_RESULT); + + // derived from oss-fuzz: https://oss-fuzz.com/testcase-detail/5758791700971520 + iStat += ThrowTest(_T("(\"\"), 7"), ecSTR_RESULT); + iStat += ThrowTest(_T("((\"\")), 7"), ecSTR_RESULT); + //iStat += ThrowTest(_T("(\"\"),(\" \"), 7, (3)"), ecSTR_RESULT); + //iStat += ThrowTest(_T("(\"\"),(\"\"), 7, (3)"), ecSTR_RESULT); + //iStat += ThrowTest(_T("(\"\"),(\"\"), (3)"), ecSTR_RESULT); + //iStat += ThrowTest(_T("(\"\"),(\"\"), 7"), ecSTR_RESULT); + + + // variations: + iStat += ThrowTest(_T(R"("","",9)"), ecSTR_RESULT); + + iStat += EqnTest(_T("valueof(\"\")"), 123, true); // empty string arguments caused a crash + iStat += EqnTest(_T("valueof(\"aaa\")+valueof(\"bbb\") "), 246, true); + iStat += EqnTest(_T("2*(valueof(\"aaa\")-23)+valueof(\"bbb\")"), 323, true); + + // use in expressions with variables + iStat += EqnTest(_T("a*(atof(\"10\")-b)"), 8, true); + iStat += EqnTest(_T("a-(atof(\"10\")*b)"), -19, true); + + // string + numeric arguments + iStat += EqnTest(_T("strfun1(\"100\")"), 100, true); + iStat += EqnTest(_T("strfun2(\"100\",1)"), 101, true); + iStat += EqnTest(_T("strfun3(\"99\",1,2)"), 102, true); + iStat += EqnTest(_T("strfun4(\"99\",1,2,3)"), 105, true); + iStat += EqnTest(_T("strfun5(\"99\",1,2,3,4)"), 109, true); + iStat += EqnTest(_T("strfun6(\"99\",1,2,3,4,5)"), 114, true); + + // string constants + iStat += EqnTest(_T("atof(str1)+atof(str2)"), 3.33, true); + + // user data + iStat += EqnTest(_T("strfunud3_10(\"99\",1,2)"), 112, true); + + if (iStat == 0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + return iStat; + } + + //--------------------------------------------------------------------------------------------- + int ParserTester::TestBulkMode() + { + int iStat = 0; + mu::console() << _T("testing bulkmode..."); + +#define EQN_TEST_BULK(EXPR, R1, R2, R3, R4, PASS) \ + { \ + double res[] = { R1, R2, R3, R4 }; \ + iStat += EqnTestBulk(_T(EXPR), res, (PASS)); \ + } + + // Bulk Variables for the test: + // a: 1,2,3,4 + // b: 2,2,2,2 + // c: 3,3,3,3 + // d: 5,4,3,2 + EQN_TEST_BULK("a", 1, 1, 1, 1, false) + EQN_TEST_BULK("a", 1, 2, 3, 4, true) + EQN_TEST_BULK("b=a", 1, 2, 3, 4, true) + EQN_TEST_BULK("b=a, b*10", 10, 20, 30, 40, true) + EQN_TEST_BULK("b=a, b*10, a", 1, 2, 3, 4, true) + EQN_TEST_BULK("a+b", 3, 4, 5, 6, true) + EQN_TEST_BULK("c*(a+b)", 9, 12, 15, 18, true) +#undef EQN_TEST_BULK + + if (iStat == 0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + return iStat; + } + + //--------------------------------------------------------------------------------------------- + int ParserTester::TestBinOprt() + { + int iStat = 0; + mu::console() << _T("testing binary operators..."); + + // built in operators + // xor operator + + iStat += EqnTest(_T("a++b"), 3, true); + iStat += EqnTest(_T("a ++ b"), 3, true); + iStat += EqnTest(_T("1++2"), 3, true); + iStat += EqnTest(_T("1 ++ 2"), 3, true); + iStat += EqnTest(_T("a add b"), 3, true); + iStat += EqnTest(_T("1 add 2"), 3, true); + iStat += EqnTest(_T("aa"), 1, true); + iStat += EqnTest(_T("a>a"), 0, true); + iStat += EqnTest(_T("aa"), 0, true); + iStat += EqnTest(_T("a<=a"), 1, true); + iStat += EqnTest(_T("a<=b"), 1, true); + iStat += EqnTest(_T("b<=a"), 0, true); + iStat += EqnTest(_T("a>=a"), 1, true); + iStat += EqnTest(_T("b>=a"), 1, true); + iStat += EqnTest(_T("a>=b"), 0, true); + + // Test logical operators, especially if user defined "&" and the internal "&&" collide + iStat += EqnTest(_T("1 && 1"), 1, true); + iStat += EqnTest(_T("1 && 0"), 0, true); + iStat += EqnTest(_T("(aa)"), 1, true); + iStat += EqnTest(_T("(ab)"), 0, true); + iStat += EqnTest(_T("12 & 255"), 12, true); + iStat += EqnTest(_T("12 & 0"), 0, true); + iStat += EqnTest(_T("12&255"), 12, true); + iStat += EqnTest(_T("12&0"), 0, true); + // test precedence of logic operators (should be like c++) + iStat += EqnTest(_T("0 && 0 || 1"), 1, true); + iStat += EqnTest(_T("0 && 1 || 0"), 0, true); + iStat += EqnTest(_T("1 && 0 || 0"), 0, true); + iStat += EqnTest(_T("1 && 1 || 0"), 1, true); + iStat += EqnTest(_T("1 && 0 + 1"), 1, true); + iStat += EqnTest(_T("1 && 1 - 1"), 0, true); + + // Assignment operator + iStat += EqnTest(_T("a = b"), 2, true); + iStat += EqnTest(_T("a = sin(b)"), 0.909297, true); + iStat += EqnTest(_T("a = 1+sin(b)"), 1.909297, true); + iStat += EqnTest(_T("(a=b)*2"), 4, true); + iStat += EqnTest(_T("2*(a=b)"), 4, true); + iStat += EqnTest(_T("2*(a=b+1)"), 6, true); + iStat += EqnTest(_T("(a=b+1)*2"), 6, true); + iStat += EqnTest(_T("a=c, a*10"), 30, true); + + iStat += EqnTest(_T("2^2^3"), 256, true); + iStat += EqnTest(_T("1/2/3"), 1.0 / 6.0, true); + + // reference: http://www.wolframalpha.com/input/?i=3%2B4*2%2F%281-5%29^2^3 + iStat += EqnTest(_T("3+4*2/(1-5)^2^3"), 3.0001220703125, true); + + // Test user defined binary operators + iStat += EqnTestInt(_T("1 | 2"), 3, true); + iStat += EqnTestInt(_T("1 || 2"), 1, true); + iStat += EqnTestInt(_T("123 & 456"), 72, true); + iStat += EqnTestInt(_T("(123 & 456) % 10"), 2, true); + iStat += EqnTestInt(_T("1 && 0"), 0, true); + iStat += EqnTestInt(_T("123 && 456"), 1, true); + iStat += EqnTestInt(_T("1 << 3"), 8, true); + iStat += EqnTestInt(_T("8 >> 3"), 1, true); + iStat += EqnTestInt(_T("9 / 4"), 2, true); + iStat += EqnTestInt(_T("9 % 4"), 1, true); + iStat += EqnTestInt(_T("if(5%2,1,0)"), 1, true); + iStat += EqnTestInt(_T("if(4%2,1,0)"), 0, true); + iStat += EqnTestInt(_T("-10+1"), -9, true); + iStat += EqnTestInt(_T("1+2*3"), 7, true); + iStat += EqnTestInt(_T("const1 != const2"), 1, true); + iStat += EqnTestInt(_T("const1 != const2"), 0, false); + iStat += EqnTestInt(_T("const1 == const2"), 0, true); + iStat += EqnTestInt(_T("const1 == 1"), 1, true); + iStat += EqnTestInt(_T("10*(const1 == 1)"), 10, true); + iStat += EqnTestInt(_T("2*(const1 | const2)"), 6, true); + iStat += EqnTestInt(_T("2*(const1 | const2)"), 7, false); + iStat += EqnTestInt(_T("const1 < const2"), 1, true); + iStat += EqnTestInt(_T("const2 > const1"), 1, true); + iStat += EqnTestInt(_T("const1 <= 1"), 1, true); + iStat += EqnTestInt(_T("const2 >= 2"), 1, true); + iStat += EqnTestInt(_T("2*(const1 + const2)"), 6, true); + iStat += EqnTestInt(_T("2*(const1 - const2)"), -2, true); + iStat += EqnTestInt(_T("a != b"), 1, true); + iStat += EqnTestInt(_T("a != b"), 0, false); + iStat += EqnTestInt(_T("a == b"), 0, true); + iStat += EqnTestInt(_T("a == 1"), 1, true); + iStat += EqnTestInt(_T("10*(a == 1)"), 10, true); + iStat += EqnTestInt(_T("2*(a | b)"), 6, true); + iStat += EqnTestInt(_T("2*(a | b)"), 7, false); + iStat += EqnTestInt(_T("a < b"), 1, true); + iStat += EqnTestInt(_T("b > a"), 1, true); + iStat += EqnTestInt(_T("a <= 1"), 1, true); + iStat += EqnTestInt(_T("b >= 2"), 1, true); + iStat += EqnTestInt(_T("2*(a + b)"), 6, true); + iStat += EqnTestInt(_T("2*(a - b)"), -2, true); + iStat += EqnTestInt(_T("a + (a << b)"), 5, true); + iStat += EqnTestInt(_T("-2^2"), -4, true); + iStat += EqnTestInt(_T("3--a"), 4, true); + iStat += EqnTestInt(_T("3+-3^2"), -6, true); + + // Test reading of hex values: + iStat += EqnTestInt(_T("0xff"), 255, true); + iStat += EqnTestInt(_T("10+0xff"), 265, true); + iStat += EqnTestInt(_T("0xff+10"), 265, true); + iStat += EqnTestInt(_T("10*0xff"), 2550, true); + iStat += EqnTestInt(_T("0xff*10"), 2550, true); + iStat += EqnTestInt(_T("10+0xff+1"), 266, true); + iStat += EqnTestInt(_T("1+0xff+10"), 266, true); + + // incorrect: '^' is yor here, not power + // iStat += EqnTestInt("-(1+2)^2", -9, true); + // iStat += EqnTestInt("-1^3", -1, true); + + // Test precedence + // a=1, b=2, c=3 + iStat += EqnTestInt(_T("a + b * c"), 7, true); + iStat += EqnTestInt(_T("a * b + c"), 5, true); + iStat += EqnTestInt(_T("a10"), 0, true); + iStat += EqnTestInt(_T("a"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("?<"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("**"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("xor"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("and"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("or"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("not"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("!"), f1of1) + + // Binary operator + // The following must fail with builtin operators activated + // p.EnableBuiltInOp(true); -> this is the default + p.ClearPostfixOprt(); + PARSER_THROWCHECK(Oprt, false, _T("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), f1of2); + PARSER_THROWCHECK(Oprt, false, _T("+"), f1of2) + PARSER_THROWCHECK(Oprt, false, _T("-"), f1of2) + PARSER_THROWCHECK(Oprt, false, _T("*"), f1of2) + PARSER_THROWCHECK(Oprt, false, _T("/"), f1of2) + PARSER_THROWCHECK(Oprt, false, _T("^"), f1of2) + PARSER_THROWCHECK(Oprt, false, _T("&&"), f1of2) + PARSER_THROWCHECK(Oprt, false, _T("||"), f1of2) + + // without activated built in operators it should work + p.EnableBuiltInOprt(false); + PARSER_THROWCHECK(Oprt, true, _T("+"), f1of2) + PARSER_THROWCHECK(Oprt, true, _T("-"), f1of2) + PARSER_THROWCHECK(Oprt, true, _T("*"), f1of2) + PARSER_THROWCHECK(Oprt, true, _T("/"), f1of2) + PARSER_THROWCHECK(Oprt, true, _T("^"), f1of2) + PARSER_THROWCHECK(Oprt, true, _T("&&"), f1of2) + PARSER_THROWCHECK(Oprt, true, _T("||"), f1of2) +#undef PARSER_THROWCHECK + + if (iStat == 0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + return iStat; + } + + //--------------------------------------------------------------------------- + int ParserTester::TestSyntax() + { + int iStat = 0; + mu::console() << _T("testing syntax engine..."); + + iStat += ThrowTest(_T("1,"), ecUNEXPECTED_EOF); // incomplete hex definition + iStat += ThrowTest(_T("a,"), ecUNEXPECTED_EOF); // incomplete hex definition + iStat += ThrowTest(_T("sin(8),"), ecUNEXPECTED_EOF); // incomplete hex definition + iStat += ThrowTest(_T("(sin(8)),"), ecUNEXPECTED_EOF); // incomplete hex definition + iStat += ThrowTest(_T("a{m},"), ecUNEXPECTED_EOF); // incomplete hex definition + + iStat += EqnTest(_T("(1+ 2*a)"), 3, true); // Spaces within formula + iStat += EqnTest(_T("sqrt((4))"), 2, true); // Multiple brackets + iStat += EqnTest(_T("sqrt((2)+2)"), 2, true);// Multiple brackets + iStat += EqnTest(_T("sqrt(2+(2))"), 2, true);// Multiple brackets + iStat += EqnTest(_T("sqrt(a+(3))"), 2, true);// Multiple brackets + iStat += EqnTest(_T("sqrt((3)+a)"), 2, true);// Multiple brackets + iStat += EqnTest(_T("order(1,2)"), 1, true); // May not cause name collision with operator "or" + iStat += EqnTest(_T("(2+"), 0, false); // missing closing bracket + iStat += EqnTest(_T("2++4"), 0, false); // unexpected operator + iStat += EqnTest(_T("2+-4"), 0, false); // unexpected operator + iStat += EqnTest(_T("(2+)"), 0, false); // unexpected closing bracket + iStat += EqnTest(_T("--2"), 0, false); // double sign + iStat += EqnTest(_T("ksdfj"), 0, false); // unknown token + iStat += EqnTest(_T("()"), 0, false); // empty bracket without a function + iStat += EqnTest(_T("5+()"), 0, false); // empty bracket without a function + iStat += EqnTest(_T("sin(cos)"), 0, false); // unexpected function + iStat += EqnTest(_T("5t6"), 0, false); // unknown token + iStat += EqnTest(_T("5 t 6"), 0, false); // unknown token + iStat += EqnTest(_T("8*"), 0, false); // unexpected end of formula + iStat += EqnTest(_T(",3"), 0, false); // unexpected comma + iStat += EqnTest(_T("3,5"), 0, false); // unexpected comma + iStat += EqnTest(_T("sin(8,8)"), 0, false); // too many function args + iStat += EqnTest(_T("(7,8)"), 0, false); // too many function args + iStat += EqnTest(_T("sin)"), 0, false); // unexpected closing bracket + iStat += EqnTest(_T("a)"), 0, false); // unexpected closing bracket + iStat += EqnTest(_T("pi)"), 0, false); // unexpected closing bracket + iStat += EqnTest(_T("sin(())"), 0, false); // unexpected closing bracket + iStat += EqnTest(_T("sin()"), 0, false); // unexpected closing bracket + + if (iStat == 0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + return iStat; + } + + //--------------------------------------------------------------------------- + int ParserTester::TestVarConst() + { + int iStat = 0; + mu::console() << _T("testing variable/constant detection..."); + + // Test if the result changes when a variable changes + iStat += EqnTestWithVarChange(_T("a"), 1, 1, 2, 2); + iStat += EqnTestWithVarChange(_T("2*a"), 2, 4, 3, 6); + + // distinguish constants with same basename + iStat += EqnTest(_T("const"), 1, true); + iStat += EqnTest(_T("const1"), 2, true); + iStat += EqnTest(_T("const2"), 3, true); + iStat += EqnTest(_T("2*const"), 2, true); + iStat += EqnTest(_T("2*const1"), 4, true); + iStat += EqnTest(_T("2*const2"), 6, true); + iStat += EqnTest(_T("2*const+1"), 3, true); + iStat += EqnTest(_T("2*const1+1"), 5, true); + iStat += EqnTest(_T("2*const2+1"), 7, true); + iStat += EqnTest(_T("const"), 0, false); + iStat += EqnTest(_T("const1"), 0, false); + iStat += EqnTest(_T("const2"), 0, false); + + // distinguish variables with same basename + iStat += EqnTest(_T("a"), 1, true); + iStat += EqnTest(_T("aa"), 2, true); + iStat += EqnTest(_T("2*a"), 2, true); + iStat += EqnTest(_T("2*aa"), 4, true); + iStat += EqnTest(_T("2*a-1"), 1, true); + iStat += EqnTest(_T("2*aa-1"), 3, true); + + // custom value recognition + iStat += EqnTest(_T("0xff"), 255, true); + iStat += EqnTest(_T("0x97 + 0xff"), 406, true); + + // Finally test querying of used variables + try + { + int idx; + mu::Parser p; + mu::value_type vVarVal[] = { 1, 2, 3, 4, 5 }; + p.DefineVar(_T("a"), &vVarVal[0]); + p.DefineVar(_T("b"), &vVarVal[1]); + p.DefineVar(_T("c"), &vVarVal[2]); + p.DefineVar(_T("d"), &vVarVal[3]); + p.DefineVar(_T("e"), &vVarVal[4]); + + // Test lookup of defined variables + // 4 used variables + p.SetExpr(_T("a+b+c+d")); + mu::varmap_type UsedVar = p.GetUsedVar(); + int iCount = (int)UsedVar.size(); + if (iCount != 4) + throw false; + + // the next check will fail if the parser + // erroneously creates new variables internally + if (p.GetVar().size() != 5) + throw false; + + mu::varmap_type::const_iterator item = UsedVar.begin(); + for (idx = 0; item != UsedVar.end(); ++item) + { + if (&vVarVal[idx++] != item->second) + throw false; + } + + // Test lookup of undefined variables + p.SetExpr(_T("undef1+undef2+undef3")); + UsedVar = p.GetUsedVar(); + iCount = (int)UsedVar.size(); + if (iCount != 3) + throw false; + + // the next check will fail if the parser + // erroneously creates new variables internally + if (p.GetVar().size() != 5) + throw false; + + for (item = UsedVar.begin(); item != UsedVar.end(); ++item) + { + if (item->second != 0) + throw false; // all pointers to undefined variables must be null + } + + // 1 used variables + p.SetExpr(_T("a+b")); + UsedVar = p.GetUsedVar(); + iCount = (int)UsedVar.size(); + if (iCount != 2) throw false; + item = UsedVar.begin(); + for (idx = 0; item != UsedVar.end(); ++item) + if (&vVarVal[idx++] != item->second) throw false; + + } + catch (...) + { + iStat += 1; + } + + if (iStat == 0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + return iStat; + } + + //--------------------------------------------------------------------------- + int ParserTester::TestMultiArg() + { + int iStat = 0; + mu::console() << _T("testing multiarg functions..."); + + // from oss-fzz.com: UNKNOWN READ; https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=23330#c1 + iStat += ThrowTest(_T("6, +, +, +, +, +, +, +, +, +, +, +, +, +, +, 1, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +, +"), ecUNEXPECTED_ARG_SEP, true); + + // misplaced string argument + iStat += ThrowTest(_T(R"(sin(0?4:("")))"), ecUNEXPECTED_STR); + iStat += ThrowTest(_T(R"(avg(0?4:(""),1))"), ecUNEXPECTED_STR); + + // Compound expressions + iStat += EqnTest(_T("1,2,3"), 3, true); + iStat += EqnTest(_T("a,b,c"), 3, true); + iStat += EqnTest(_T("a=10,b=20,c=a*b"), 200, true); + iStat += EqnTest(_T("1,\n2,\n3"), 3, true); + iStat += EqnTest(_T("a,\nb,\nc"), 3, true); + iStat += EqnTest(_T("a=10,\nb=20,\nc=a*b"), 200, true); + iStat += EqnTest(_T("1,\r\n2,\r\n3"), 3, true); + iStat += EqnTest(_T("a,\r\nb,\r\nc"), 3, true); + iStat += EqnTest(_T("a=10,\r\nb=20,\r\nc=a*b"), 200, true); + + // picking the right argument + iStat += EqnTest(_T("f1of1(1)"), 1, true); + iStat += EqnTest(_T("f1of2(1, 2)"), 1, true); + iStat += EqnTest(_T("f2of2(1, 2)"), 2, true); + iStat += EqnTest(_T("f1of3(1, 2, 3)"), 1, true); + iStat += EqnTest(_T("f2of3(1, 2, 3)"), 2, true); + iStat += EqnTest(_T("f3of3(1, 2, 3)"), 3, true); + iStat += EqnTest(_T("f1of4(1, 2, 3, 4)"), 1, true); + iStat += EqnTest(_T("f2of4(1, 2, 3, 4)"), 2, true); + iStat += EqnTest(_T("f3of4(1, 2, 3, 4)"), 3, true); + iStat += EqnTest(_T("f4of4(1, 2, 3, 4)"), 4, true); + iStat += EqnTest(_T("f1of5(1, 2, 3, 4, 5)"), 1, true); + iStat += EqnTest(_T("f2of5(1, 2, 3, 4, 5)"), 2, true); + iStat += EqnTest(_T("f3of5(1, 2, 3, 4, 5)"), 3, true); + iStat += EqnTest(_T("f4of5(1, 2, 3, 4, 5)"), 4, true); + iStat += EqnTest(_T("f5of5(1, 2, 3, 4, 5)"), 5, true); + // Too few arguments / Too many arguments + iStat += EqnTest(_T("1+ping()"), 11, true); + iStat += EqnTest(_T("ping()+1"), 11, true); + iStat += EqnTest(_T("2*ping()"), 20, true); + iStat += EqnTest(_T("ping()*2"), 20, true); + iStat += EqnTest(_T("ping(1,2)"), 0, false); + iStat += EqnTest(_T("1+ping(1,2)"), 0, false); + iStat += EqnTest(_T("f1of1(1,2)"), 0, false); + iStat += EqnTest(_T("f1of1()"), 0, false); + iStat += EqnTest(_T("f1of2(1, 2, 3)"), 0, false); + iStat += EqnTest(_T("f1of2(1)"), 0, false); + iStat += EqnTest(_T("f1of3(1, 2, 3, 4)"), 0, false); + iStat += EqnTest(_T("f1of3(1)"), 0, false); + iStat += EqnTest(_T("f1of4(1, 2, 3, 4, 5)"), 0, false); + iStat += EqnTest(_T("f1of4(1)"), 0, false); + iStat += EqnTest(_T("(1,2,3)"), 0, false); + iStat += EqnTest(_T("1,2,3"), 0, false); + iStat += EqnTest(_T("(1*a,2,3)"), 0, false); + iStat += EqnTest(_T("1,2*a,3"), 0, false); + + // correct calculation of arguments + iStat += EqnTest(_T("min(a, 1)"), 1, true); + iStat += EqnTest(_T("min(3*2, 1)"), 1, true); + iStat += EqnTest(_T("min(3*2, 1)"), 6, false); + iStat += EqnTest(_T("firstArg(2,3,4)"), 2, true); + iStat += EqnTest(_T("lastArg(2,3,4)"), 4, true); + iStat += EqnTest(_T("min(3*a+1, 1)"), 1, true); + iStat += EqnTest(_T("max(3*a+1, 1)"), 4, true); + iStat += EqnTest(_T("max(3*a+1, 1)*2"), 8, true); + iStat += EqnTest(_T("2*max(3*a+1, 1)+2"), 10, true); + + // functions with Variable argument count + iStat += EqnTest(_T("sum(a)"), 1, true); + iStat += EqnTest(_T("sum(1,2,3)"), 6, true); + iStat += EqnTest(_T("sum(a,b,c)"), 6, true); + iStat += EqnTest(_T("sum(1,-max(1,2),3)*2"), 4, true); + iStat += EqnTest(_T("2*sum(1,2,3)"), 12, true); + iStat += EqnTest(_T("2*sum(1,2,3)+2"), 14, true); + iStat += EqnTest(_T("2*sum(-1,2,3)+2"), 10, true); + iStat += EqnTest(_T("2*sum(-1,2,-(-a))+2"), 6, true); + iStat += EqnTest(_T("2*sum(-1,10,-a)+2"), 18, true); + iStat += EqnTest(_T("2*sum(1,2,3)*2"), 24, true); + iStat += EqnTest(_T("sum(1,-max(1,2),3)*2"), 4, true); + iStat += EqnTest(_T("sum(1*3, 4, a+2)"), 10, true); + iStat += EqnTest(_T("sum(1*3, 2*sum(1,2,2), a+2)"), 16, true); + iStat += EqnTest(_T("sum(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2)"), 24, true); + + // some failures + iStat += EqnTest(_T("sum()"), 0, false); + iStat += EqnTest(_T("sum(,)"), 0, false); + iStat += EqnTest(_T("sum(1,2,)"), 0, false); + iStat += EqnTest(_T("sum(,1,2)"), 0, false); + + // user data + iStat += EqnTest(_T("funud0_8()"), 8, true); + iStat += EqnTest(_T("funud1_16(10)"), 26, true); + iStat += EqnTest(_T("funud2_24(10, 100)"), 134, true); + iStat += EqnTest(_T("funud10_32(1,2,3,4,5,6,7,8,9,10)"), 87, true); + iStat += EqnTest(_T("funud0_9()"), 9, true); + iStat += EqnTest(_T("funud1_17(10)"), 27, true); + iStat += EqnTest(_T("funud2_25(10, 100)"), 135, true); + iStat += EqnTest(_T("funud10_33(1,2,3,4,5,6,7,8,9,10)"), 88, true); + iStat += EqnTest(_T("sumud_100(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2)"), 124, true); + iStat += EqnTest(_T("sumud_100()"), 0, false); + + if (iStat == 0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + return iStat; + } + + + //--------------------------------------------------------------------------- + int ParserTester::TestInfixOprt() + { + int iStat(0); + mu::console() << "testing infix operators..."; + + iStat += EqnTest(_T("+1"), +1, true); + iStat += EqnTest(_T("-(+1)"), -1, true); + iStat += EqnTest(_T("-(+1)*2"), -2, true); + iStat += EqnTest(_T("-(+2)*sqrt(4)"), -4, true); + iStat += EqnTest(_T("3-+a"), 2, true); + iStat += EqnTest(_T("+1*3"), 3, true); + + iStat += EqnTest(_T("-1"), -1, true); + iStat += EqnTest(_T("-(-1)"), 1, true); + iStat += EqnTest(_T("-(-1)*2"), 2, true); + iStat += EqnTest(_T("-(-2)*sqrt(4)"), 4, true); + iStat += EqnTest(_T("-_pi"), -MathImpl::CONST_PI, true); + iStat += EqnTest(_T("-a"), -1, true); + iStat += EqnTest(_T("-(a)"), -1, true); + iStat += EqnTest(_T("-(-a)"), 1, true); + iStat += EqnTest(_T("-(-a)*2"), 2, true); + iStat += EqnTest(_T("-(8)"), -8, true); + iStat += EqnTest(_T("-8"), -8, true); + iStat += EqnTest(_T("-(2+1)"), -3, true); + iStat += EqnTest(_T("-(f1of1(1+2*3)+1*2)"), -9, true); + iStat += EqnTest(_T("-(-f1of1(1+2*3)+1*2)"), 5, true); + iStat += EqnTest(_T("-sin(8)"), -0.989358, true); + iStat += EqnTest(_T("3-(-a)"), 4, true); + iStat += EqnTest(_T("3--a"), 4, true); + iStat += EqnTest(_T("-1*3"), -3, true); + + // Postfix / infix priorities + iStat += EqnTest(_T("~2#"), 8, true); + iStat += EqnTest(_T("~f1of1(2)#"), 8, true); + iStat += EqnTest(_T("~(b)#"), 8, true); + iStat += EqnTest(_T("(~b)#"), 12, true); + iStat += EqnTest(_T("~(2#)"), 8, true); + iStat += EqnTest(_T("~(f1of1(2)#)"), 8, true); + // + iStat += EqnTest(_T("-2^2"), -4, true); + iStat += EqnTest(_T("-(a+b)^2"), -9, true); + iStat += EqnTest(_T("(-3)^2"), 9, true); + iStat += EqnTest(_T("-(-2^2)"), 4, true); + iStat += EqnTest(_T("3+-3^2"), -6, true); + // The following assumes use of sqr as postfix operator together + // with a sign operator of low priority: + iStat += EqnTest(_T("-2'"), -4, true); + iStat += EqnTest(_T("-(1+1)'"), -4, true); + iStat += EqnTest(_T("2+-(1+1)'"), -2, true); + iStat += EqnTest(_T("2+-2'"), -2, true); + // This is the classic behaviour of the infix sign operator (here: "$") which is + // now deprecated: + iStat += EqnTest(_T("$2^2"), 4, true); + iStat += EqnTest(_T("$(a+b)^2"), 9, true); + iStat += EqnTest(_T("($3)^2"), 9, true); + iStat += EqnTest(_T("$($2^2)"), -4, true); + iStat += EqnTest(_T("3+$3^2"), 12, true); + + // infix operators sharing the first few characters + iStat += EqnTest(_T("~ 123"), (value_type)123.0 + 2, true); + iStat += EqnTest(_T("~~ 123"), (value_type)123.0 + 2, true); + + if (iStat == 0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + return iStat; + } + + + //--------------------------------------------------------------------------- + int ParserTester::TestPostFix() + { + int iStat = 0; + mu::console() << _T("testing postfix operators..."); + + // application + iStat += EqnTest(_T("3{m}+5"), 5.003, true); + iStat += EqnTest(_T("1000{m}"), 1, true); + iStat += EqnTest(_T("1000 {m}"), 1, true); + iStat += EqnTest(_T("(a){m}"), 1e-3, true); + iStat += EqnTest(_T("a{m}"), 1e-3, true); + iStat += EqnTest(_T("a {m}"), 1e-3, true); + iStat += EqnTest(_T("-(a){m}"), -1e-3, true); + iStat += EqnTest(_T("-2{m}"), -2e-3, true); + iStat += EqnTest(_T("-2 {m}"), -2e-3, true); + iStat += EqnTest(_T("f1of1(1000){m}"), 1, true); + iStat += EqnTest(_T("-f1of1(1000){m}"), -1, true); + iStat += EqnTest(_T("-f1of1(-1000){m}"), 1, true); + iStat += EqnTest(_T("f4of4(0,0,0,1000){m}"), 1, true); + iStat += EqnTest(_T("2+(a*1000){m}"), 3, true); + + // I have added a space between the number and the operator so that + // systems using libc++ can pass the test (see #123) + iStat += EqnTest(_T("1 n"), 1e-9, true); + + // can postfix operators "m" und "meg" be told apart properly? + iStat += EqnTest(_T("2*3000meg+2"), 2 * 3e9 + 2, true); + + // some incorrect results + iStat += EqnTest(_T("1000{m}"), 0.1, false); + iStat += EqnTest(_T("(a){m}"), 2, false); + // failure due to syntax checking + iStat += ThrowTest(_T("0x"), ecUNASSIGNABLE_TOKEN); // incomplete hex definition + iStat += ThrowTest(_T("3+"), ecUNEXPECTED_EOF); + iStat += ThrowTest(_T("4 + {m}"), ecUNASSIGNABLE_TOKEN); + iStat += ThrowTest(_T("{m}4"), ecUNASSIGNABLE_TOKEN); + iStat += ThrowTest(_T("sin({m})"), ecUNASSIGNABLE_TOKEN); + iStat += ThrowTest(_T("{m} {m}"), ecUNASSIGNABLE_TOKEN); + iStat += ThrowTest(_T("{m}(8)"), ecUNASSIGNABLE_TOKEN); + iStat += ThrowTest(_T("4,{m}"), ecUNASSIGNABLE_TOKEN); + iStat += ThrowTest(_T("-{m}"), ecUNASSIGNABLE_TOKEN); + iStat += ThrowTest(_T("2(-{m})"), ecUNEXPECTED_PARENS); + iStat += ThrowTest(_T("2({m})"), ecUNEXPECTED_PARENS); + + iStat += ThrowTest(_T("multi*1.0"), ecUNASSIGNABLE_TOKEN); + + if (iStat == 0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + return iStat; + } + + //--------------------------------------------------------------------------- + int ParserTester::TestExpression() + { + int iStat = 0; + mu::console() << _T("testing expression samples..."); + + value_type b = 2; + + iStat += EqnTest(_T("f0()"), 42, true); + iStat += EqnTest(_T("b^2"), 4, true); + iStat += EqnTest(_T("b^1"), 2, true); + iStat += EqnTest(_T("b^0"), 1, true); + iStat += EqnTest(_T("b^-1"), 0.5, true); + + // Optimization + iStat += EqnTest(_T("2*b*5"), 20, true); + iStat += EqnTest(_T("2*b*5 + 4*b"), 28, true); + iStat += EqnTest(_T("2*a/3"), 2.0 / 3.0, true); + + // Addition auf cmVARMUL + iStat += EqnTest(_T("3+b"), b + 3, true); + iStat += EqnTest(_T("b+3"), b + 3, true); + iStat += EqnTest(_T("b*3+2"), b * 3 + 2, true); + iStat += EqnTest(_T("3*b+2"), b * 3 + 2, true); + iStat += EqnTest(_T("2+b*3"), b * 3 + 2, true); + iStat += EqnTest(_T("2+3*b"), b * 3 + 2, true); + iStat += EqnTest(_T("b+3*b"), b + 3 * b, true); + iStat += EqnTest(_T("3*b+b"), b + 3 * b, true); + + iStat += EqnTest(_T("2+b*3+b"), 2 + b * 3 + b, true); + iStat += EqnTest(_T("b+2+b*3"), b + 2 + b * 3, true); + + iStat += EqnTest(_T("(2*b+1)*4"), (2 * b + 1) * 4, true); + iStat += EqnTest(_T("4*(2*b+1)"), (2 * b + 1) * 4, true); + + // operator precedences + iStat += EqnTest(_T("1+2-3*4/5^6"), 2.99923, true); + iStat += EqnTest(_T("1^2/3*4-5+6"), 2.33333333, true); + iStat += EqnTest(_T("1+2*3"), 7, true); + iStat += EqnTest(_T("1+2*3"), 7, true); + iStat += EqnTest(_T("(1+2)*3"), 9, true); + iStat += EqnTest(_T("(1+2)*(-3)"), -9, true); + iStat += EqnTest(_T("2/4"), 0.5, true); + + iStat += EqnTest(_T("exp(ln(7))"), 7, true); + iStat += EqnTest(_T("e^ln(7)"), 7, true); + iStat += EqnTest(_T("e^(ln(7))"), 7, true); + iStat += EqnTest(_T("(e^(ln(7)))"), 7, true); + iStat += EqnTest(_T("1-(e^(ln(7)))"), -6, true); + iStat += EqnTest(_T("2*(e^(ln(7)))"), 14, true); + iStat += EqnTest(_T("10^log(5)"), pow(10.0, log(5.0)), true); + iStat += EqnTest(_T("10^log10(5)"), 5, true); + iStat += EqnTest(_T("2^log2(4)"), 4, true); + iStat += EqnTest(_T("-(sin(0)+1)"), -1, true); + iStat += EqnTest(_T("-(2^1.1)"), -2.14354692, true); + + iStat += EqnTest(_T("(cos(2.41)/b)"), -0.372056, true); + iStat += EqnTest(_T("(1*(2*(3*(4*(5*(6*(a+b)))))))"), 2160, true); + iStat += EqnTest(_T("(1*(2*(3*(4*(5*(6*(7*(a+b))))))))"), 15120, true); + iStat += EqnTest(_T("(a/((((b+(((e*(((((pi*((((3.45*((pi+a)+pi))+b)+b)*a))+0.68)+e)+a)/a))+a)+b))+b)*a)-pi))"), 0.00377999, true); + + // long formula (Reference: Matlab) + iStat += EqnTest( + _T("(((-9))-e/(((((((pi-(((-7)+(-3)/4/e))))/(((-5))-2)-((pi+(-0))*(sqrt((e+e))*(-8))*(((-pi)+(-pi)-(-9)*(6*5))") + _T("/(-e)-e))/2)/((((sqrt(2/(-e)+6)-(4-2))+((5/(-2))/(1*(-pi)+3))/8)*pi*((pi/((-2)/(-6)*1*(-1))*(-6)+(-e)))))/") + _T("((e+(-2)+(-e)*((((-3)*9+(-e)))+(-9)))))))-((((e-7+(((5/pi-(3/1+pi)))))/e)/(-5))/(sqrt((((((1+(-7))))+((((-") + _T("e)*(-e)))-8))*(-5)/((-e)))*(-6)-((((((-2)-(-9)-(-e)-1)/3))))/(sqrt((8+(e-((-6))+(9*(-9))))*(((3+2-8))*(7+6") + _T("+(-5))+((0/(-e)*(-pi))+7)))+(((((-e)/e/e)+((-6)*5)*e+(3+(-5)/pi))))+pi))/sqrt((((9))+((((pi))-8+2))+pi))/e") + _T("*4)*((-5)/(((-pi))*(sqrt(e)))))-(((((((-e)*(e)-pi))/4+(pi)*(-9)))))))+(-pi)"), -12.23016549, true); + + // long formula (Reference: Matlab) + iStat += EqnTest( + _T("(atan(sin((((((((((((((((pi/cos((a/((((0.53-b)-pi)*e)/b))))+2.51)+a)-0.54)/0.98)+b)*b)+e)/a)+b)+a)+b)+pi)/e") + _T(")+a)))*2.77)"), -2.16995656, true); + + // long formula (Reference: Matlab) + iStat += EqnTest(_T("1+2-3*4/5^6*(2*(1-5+(3*7^9)*(4+6*7-3)))+12"), -7995810.09926, true); + + if (iStat == 0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + return iStat; + } + + + + //--------------------------------------------------------------------------- + int ParserTester::TestIfThenElse() + { + int iStat = 0; + mu::console() << _T("testing if-then-else operator..."); + + // from oss-fuzz.com: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=24167 + iStat += ThrowTest(_T(R"(0^3^avg(0>3?4:(""),0^3?4:("")))"), ecUNEXPECTED_STR); + // derivatives + iStat += ThrowTest(_T(R"(avg(0?(""):4,1))"), ecUNEXPECTED_STR); + iStat += ThrowTest(_T(R"(avg(0>3?4:(""),0^3?4:("")))"), ecUNEXPECTED_STR); + + iStat += ThrowTest(_T(R"(0?4:(""))"), ecUNEXPECTED_STR); + iStat += ThrowTest(_T(R"((0)?4:(""))"), ecUNEXPECTED_STR); + iStat += ThrowTest(_T(R"((0>3)?4:(""))"), ecUNEXPECTED_STR); + iStat += ThrowTest(_T(R"(0>3?4:(""))"), ecUNEXPECTED_STR); + + // from oss-fuzz.com: https://oss-fuzz.com/testcase-detail/4777121158529024 + iStat += ThrowTest(_T("3!=min(0?2>2,2>5,1:6)"), ecUNEXPECTED_ARG_SEP); + + // Test error detection + iStat += ThrowTest(_T(":3"), ecUNEXPECTED_CONDITIONAL); + iStat += ThrowTest(_T("? 1 : 2"), ecUNEXPECTED_CONDITIONAL); + iStat += ThrowTest(_T("(a3?2,4,2:4)"), ecUNEXPECTED_ARG_SEP); + iStat += ThrowTest(_T("sum(2>3?2,4,sin(2):4)"), ecUNEXPECTED_ARG_SEP); + iStat += ThrowTest(_T("sum(2>3?sin(2),4,2:4)"), ecUNEXPECTED_ARG_SEP); + iStat += ThrowTest(_T("sum(2>3?sin(a),4,2:4)"), ecUNEXPECTED_ARG_SEP); + iStat += ThrowTest(_T("sum(2>3?sin(2),4,2:4)"), ecUNEXPECTED_ARG_SEP); + + iStat += EqnTest(_T("1 ? 128 : 255"), 128, true); + iStat += EqnTest(_T("1<2 ? 128 : 255"), 128, true); + iStat += EqnTest(_T("ab) ? 10 : 11"), 11, true); + iStat += EqnTest(_T("(ab) ? c : d"), -2, true); + + iStat += EqnTest(_T("(a>b) ? 1 : 0"), 0, true); + iStat += EqnTest(_T("((a>b) ? 1 : 0) ? 1 : 2"), 2, true); + iStat += EqnTest(_T("((a>b) ? 1 : 0) ? 1 : sum((a>b) ? 1 : 2)"), 2, true); + iStat += EqnTest(_T("((a>b) ? 0 : 1) ? 1 : sum((a>b) ? 1 : 2)"), 1, true); + + iStat += EqnTest(_T("sum((a>b) ? 1 : 2)"), 2, true); + iStat += EqnTest(_T("sum((1) ? 1 : 2)"), 1, true); + iStat += EqnTest(_T("sum((a>b) ? 1 : 2, 100)"), 102, true); + iStat += EqnTest(_T("sum((1) ? 1 : 2, 100)"), 101, true); + iStat += EqnTest(_T("sum(3, (a>b) ? 3 : 10)"), 13, true); + iStat += EqnTest(_T("sum(3, (ab) ? 3 : 10)"), 130, true); + iStat += EqnTest(_T("10*sum(3, (ab) ? 3 : 10)*10"), 130, true); + iStat += EqnTest(_T("sum(3, (ab) ? sum(3, (ab) ? sum(3, (ab) ? sum(3, (ab)&&(a2)&&(1<2) ? 128 : 255"), 255, true); + iStat += EqnTest(_T("((1<2)&&(1<2)) ? 128 : 255"), 128, true); + iStat += EqnTest(_T("((1>2)&&(1<2)) ? 128 : 255"), 255, true); + iStat += EqnTest(_T("((ab)&&(a0 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 64"), 255, true); + iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 :(1>0 ? 32 : 64)"), 255, true); + iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 : 1>2 ? 32 : 64"), 128, true); + iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 :(1>2 ? 32 : 64)"), 128, true); + iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 64"), 32, true); + iStat += EqnTest(_T("1>2 ? 1>0 ? 128 : 255 : 1>2 ? 32 : 64"), 64, true); + iStat += EqnTest(_T("1>0 ? 50 : 1>0 ? 128 : 255"), 50, true); + iStat += EqnTest(_T("1>0 ? 50 : (1>0 ? 128 : 255)"), 50, true); + iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 : 50"), 128, true); + iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 1>2 ? 64 : 16"), 32, true); + iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 :(1>2 ? 64 : 16)"), 32, true); + iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : 1>0 ? 32 :1>2 ? 64 : 16"), 255, true); + iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : (1>0 ? 32 :1>2 ? 64 : 16)"), 255, true); + iStat += EqnTest(_T("1 ? 0 ? 128 : 255 : 1 ? 32 : 64"), 255, true); + + // assignment operators + iStat += EqnTest(_T("a= 0 ? 128 : 255, a"), 255, true); + iStat += EqnTest(_T("a=((a>b)&&(a + // this is now legal, for reference see: + // https://sourceforge.net/forum/message.php?msg_id=7411373 + // iStat += ThrowTest( _T("sin=9"), ecUNEXPECTED_OPERATOR); + // + + iStat += ThrowTest(_T("(8)=5"), ecUNEXPECTED_OPERATOR); + iStat += ThrowTest(_T("(a)=5"), ecUNEXPECTED_OPERATOR); + iStat += ThrowTest(_T("a=\"tttt\""), ecOPRT_TYPE_CONFLICT); + + if (iStat == 0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + return iStat; + } + + int ParserTester::TestLocalization() + { + int iStat = 0; + mu::console() << _T("testing localization..."); + + iStat += EqnTestLocalized(_T("1,2"), 1.2, true); + + if (iStat == 0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + // Reset the locale to the "C" locale. + Parser().ResetLocale(); + + return iStat; + } + + + void ParserTester::AddTest(testfun_type a_pFun) + { + m_vTestFun.push_back(a_pFun); + } + + int ParserTester::Run() + { + int iStat = 0; + try + { + for (int i = 0; i < (int)m_vTestFun.size(); ++i) + iStat += (this->*m_vTestFun[i])(); + } + catch (Parser::exception_type& e) + { + mu::console() << "\n" << e.GetMsg() << endl; + mu::console() << e.GetToken() << endl; + Abort(); + } + catch (std::exception& e) + { + mu::console() << e.what() << endl; + Abort(); + } + catch (...) + { + mu::console() << "Internal error"; + Abort(); + } + + if (iStat == 0) + { + mu::console() << "Test passed (" << ParserTester::c_iCount << " expressions)" << endl; + } + else + { + mu::console() << "Test failed with " << iStat + << " errors (" << ParserTester::c_iCount + << " expressions)" << endl; + } + ParserTester::c_iCount = 0; + return iStat; + } + + + //--------------------------------------------------------------------------- + int ParserTester::ThrowTest(const string_type& a_str, int a_iErrc, bool a_expectedToFail) + { + ParserTester::c_iCount++; + + try + { + value_type fVal[] = { 1,1,1 }; + Parser p; + + p.DefineVar(_T("a"), &fVal[0]); + p.DefineVar(_T("b"), &fVal[1]); + p.DefineVar(_T("c"), &fVal[2]); + p.DefinePostfixOprt(_T("{m}"), Milli); + p.DefinePostfixOprt(_T("m"), Milli); + p.DefineFun(_T("ping"), Ping); + p.DefineFun(_T("valueof"), ValueOf); + p.DefineFun(_T("strfun1"), StrFun1); + p.DefineFun(_T("strfun2"), StrFun2); + p.DefineFun(_T("strfun3"), StrFun3); + p.DefineFun(_T("strfun4"), StrFun4); + p.DefineFun(_T("strfun5"), StrFun5); + p.DefineFun(_T("strfun6"), StrFun6); + p.SetExpr(a_str); + // p.EnableDebugDump(1, 0); + p.Eval(); + } + catch (ParserError& e) + { + // output the formula in case of an failed test + if (a_expectedToFail == false || (a_expectedToFail == true && a_iErrc != e.GetCode())) + { + mu::console() << _T("\n ") + << _T("Expression: ") << a_str + << _T(" Code:") << e.GetCode() << _T("(") << e.GetMsg() << _T(")") + << _T(" Expected:") << a_iErrc; + } + + return (a_iErrc == e.GetCode()) ? 0 : 1; + } + + // if a_expectedToFail == false no exception is expected + bool bRet((a_expectedToFail == false) ? 0 : 1); + if (bRet == 1) + { + mu::console() << _T("\n ") + << _T("Expression: ") << a_str + << _T(" did evaluate; Expected error:") << a_iErrc; + } + + return bRet; + } + + //--------------------------------------------------------------------------- + /** \brief Evaluate a test expression. + + \return 1 in case of a failure, 0 otherwise. + */ + int ParserTester::EqnTestWithVarChange(const string_type& a_str, + double a_fVar1, + double a_fRes1, + double a_fVar2, + double a_fRes2) + { + ParserTester::c_iCount++; + + try + { + value_type fVal[2] = { -999, -999 }; // should be equal + + Parser p; + value_type var = 0; + + // variable + p.DefineVar(_T("a"), &var); + p.SetExpr(a_str); + + var = a_fVar1; + fVal[0] = p.Eval(); + + var = a_fVar2; + fVal[1] = p.Eval(); + + if (fabs(a_fRes1 - fVal[0]) > 0.0000000001) + throw std::runtime_error("incorrect result (first pass)"); + + if (fabs(a_fRes2 - fVal[1]) > 0.0000000001) + throw std::runtime_error("incorrect result (second pass)"); + } + catch (Parser::exception_type& e) + { + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.GetMsg() << _T(")"); + return 1; + } + catch (std::exception& e) + { + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.what() << _T(")"); + return 1; // always return a failure since this exception is not expected + } + catch (...) + { + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)"); + return 1; // exceptions other than ParserException are not allowed + } + + return 0; + } + + //--------------------------------------------------------------------------- + /** \brief Evaluate a test expression. + + \return 1 in case of a failure, 0 otherwise. + */ + int ParserTester::EqnTestLocalized(const string_type& a_str, double a_fRes, bool a_fPass) + { + ParserTester::c_iCount++; + + try + { + Parser p; + value_type var[2] = { 1, 2 }; + + // variable + p.SetDecSep(','); + p.SetArgSep(';'); + p.SetThousandsSep('.'); + + p.DefineVar(_T("a"), &var[0]); + p.DefineVar(_T("b"), &var[1]); + p.SetExpr(a_str); + + auto result = p.Eval(); + + if (fabs(result - a_fRes) > 0.0000000001) + throw std::runtime_error("incorrect result (first pass)"); + } + catch (Parser::exception_type& e) + { + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.GetMsg() << _T(")"); + return 1; + } + catch (std::exception& e) + { + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.what() << _T(")"); + return 1; // always return a failure since this exception is not expected + } + catch (...) + { + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)"); + return 1; // exceptions other than ParserException are not allowed + } + + return 0; + } + + //--------------------------------------------------------------------------- + /** \brief Evaluate a tet expression. + + \return 1 in case of a failure, 0 otherwise. + */ + int ParserTester::EqnTest(const string_type& a_str, double a_fRes, bool a_fPass) + { + ParserTester::c_iCount++; + int iRet(0); + value_type fVal[6] = { -999, -998, -997, -996, -995, -994 }; // initially should be different + + try + { + std::unique_ptr p1; + Parser p2, p3; // three parser objects + // they will be used for testing copy and assignment operators + // p1 is a pointer since i'm going to delete it in order to test if + // parsers after copy construction still refer to members of it. + // !! If this is the case this function will crash !! + + p1.reset(new mu::Parser()); + // Add constants + p1->DefineConst(_T("pi"), MathImpl::CONST_PI); + p1->DefineConst(_T("e"), MathImpl::CONST_E); + p1->DefineConst(_T("const"), 1); + p1->DefineConst(_T("const1"), 2); + p1->DefineConst(_T("const2"), 3); + // string constants + p1->DefineStrConst(_T("str1"), _T("1.11")); + p1->DefineStrConst(_T("str2"), _T("2.22")); + // variables + value_type vVarVal[] = { 1, 2, 3, -2 }; + p1->DefineVar(_T("a"), &vVarVal[0]); + p1->DefineVar(_T("aa"), &vVarVal[1]); + p1->DefineVar(_T("b"), &vVarVal[1]); + p1->DefineVar(_T("c"), &vVarVal[2]); + p1->DefineVar(_T("d"), &vVarVal[3]); + + // custom value ident functions + p1->AddValIdent(&ParserTester::IsHexVal); + + // functions + p1->DefineFun(_T("ping"), Ping); + p1->DefineFun(_T("f0"), f0); // no parameter + p1->DefineFun(_T("f1of1"), f1of1); // one parameter + p1->DefineFun(_T("f1of2"), f1of2); // two parameter + p1->DefineFun(_T("f2of2"), f2of2); + p1->DefineFun(_T("f1of3"), f1of3); // three parameter + p1->DefineFun(_T("f2of3"), f2of3); + p1->DefineFun(_T("f3of3"), f3of3); + p1->DefineFun(_T("f1of4"), f1of4); // four parameter + p1->DefineFun(_T("f2of4"), f2of4); + p1->DefineFun(_T("f3of4"), f3of4); + p1->DefineFun(_T("f4of4"), f4of4); + p1->DefineFun(_T("f1of5"), f1of5); // five parameter + p1->DefineFun(_T("f2of5"), f2of5); + p1->DefineFun(_T("f3of5"), f3of5); + p1->DefineFun(_T("f4of5"), f4of5); + p1->DefineFun(_T("f5of5"), f5of5); + + // binary operators + p1->DefineOprt(_T("add"), add, 0); + p1->DefineOprt(_T("++"), add, 0); + p1->DefineOprt(_T("&"), land, prLAND); + + // sample functions + p1->DefineFun(_T("min"), Min); + p1->DefineFun(_T("max"), Max); + p1->DefineFun(_T("sum"), Sum); + p1->DefineFun(_T("valueof"), ValueOf); + p1->DefineFun(_T("atof"), StrToFloat); + p1->DefineFun(_T("strfun1"), StrFun1); + p1->DefineFun(_T("strfun2"), StrFun2); + p1->DefineFun(_T("strfun3"), StrFun3); + p1->DefineFun(_T("strfun4"), StrFun4); + p1->DefineFun(_T("strfun5"), StrFun5); + p1->DefineFun(_T("strfun6"), StrFun6); + p1->DefineFun(_T("lastArg"), LastArg); + p1->DefineFun(_T("firstArg"), FirstArg); + p1->DefineFun(_T("order"), FirstArg); + + // functions with user data + p1->DefineFunUserData(_T("funud0_8"), FunUd0, reinterpret_cast(8)); + p1->DefineFunUserData(_T("funud1_16"), FunUd1, reinterpret_cast(16)); + p1->DefineFunUserData(_T("funud2_24"), FunUd2, reinterpret_cast(24)); + p1->DefineFunUserData(_T("funud10_32"), FunUd10, reinterpret_cast(32)); + p1->DefineFunUserData(_T("funud0_9"), FunUd0, reinterpret_cast(9)); + p1->DefineFunUserData(_T("funud1_17"), FunUd1, reinterpret_cast(17)); + p1->DefineFunUserData(_T("funud2_25"), FunUd2, reinterpret_cast(25)); + p1->DefineFunUserData(_T("funud10_33"), FunUd10, reinterpret_cast(33)); + p1->DefineFunUserData(_T("strfunud3_10"), StrFunUd3, reinterpret_cast(10)); + p1->DefineFunUserData(_T("sumud_100"), SumUd, reinterpret_cast(100)); + + // infix / postfix operator + // Note: Identifiers used here do not have any meaning + // they are mere placeholders to test certain features. + p1->DefineInfixOprt(_T("$"), sign, prPOW + 1); // sign with high priority + p1->DefineInfixOprt(_T("~"), plus2); // high priority + p1->DefineInfixOprt(_T("~~"), plus2); + p1->DefinePostfixOprt(_T("{m}"), Milli); + p1->DefinePostfixOprt(_T("{M}"), Mega); + p1->DefinePostfixOprt(_T("m"), Milli); + p1->DefinePostfixOprt(_T("n"), [](double value){return value * 1E-9;}); + p1->DefinePostfixOprt(_T("meg"), Mega); + p1->DefinePostfixOprt(_T("#"), times3); + p1->DefinePostfixOprt(_T("'"), sqr); + p1->SetExpr(a_str); + + // Test bytecode integrity + // String parsing and bytecode parsing must yield the same result + fVal[0] = p1->Eval(); // result from stringparsing + fVal[1] = p1->Eval(); // result from bytecode + if (fVal[0] != fVal[1]) + throw Parser::exception_type(_T("Bytecode / string parsing mismatch.")); + + // Test copy and assignment operators + try + { + // Test copy constructor + std::vector vParser; + vParser.push_back(*(p1.get())); + mu::Parser p4 = vParser[0]; // take parser from vector + + // destroy the originals from p2 + vParser.clear(); // delete the vector + p1.reset(nullptr); + + fVal[2] = p4.Eval(); + + // Test assignment operator + // additionally disable Optimizer this time + mu::Parser p5; + p5 = p4; + p5.EnableOptimizer(false); + fVal[3] = p5.Eval(); + + // Test Eval function for multiple return values + // use p2 since it has the optimizer enabled! + int nNum; + p4.SetExpr(a_str); // reset bytecode to trigger #94 (https://github.com/beltoforion/muparser/issues/94) + value_type* v = p4.Eval(nNum); + fVal[4] = v[nNum - 1]; + + v = p4.Eval(nNum); + fVal[5] = v[nNum - 1]; + + } + catch (std::exception& e) + { + mu::console() << _T("\n ") << e.what() << _T("\n"); + } + + // limited floating point accuracy requires the following test + bool bCloseEnough(true); + for (unsigned i = 0; i < sizeof(fVal) / sizeof(value_type); ++i) + { + bCloseEnough &= (fabs(a_fRes - fVal[i]) <= fabs(fVal[i] * 0.00001)); + + // The tests equations never result in infinity, if they do thats a bug. + // reference: + // http://sourceforge.net/projects/muparser/forums/forum/462843/topic/5037825 + bCloseEnough &= std::isfinite(fVal[i]); + } + + iRet = ((bCloseEnough && a_fPass) || (!bCloseEnough && !a_fPass)) ? 0 : 1; + + + if (iRet == 1) + { + mu::console() << _T("\n fail: ") << a_str.c_str() + << _T(" (incorrect result; expected: ") << a_fRes + << _T(" ;calculated: ") << fVal[0] << _T(",") + << fVal[1] << _T(",") + << fVal[2] << _T(",") + << fVal[3] << _T(",") + << fVal[4] << _T(",") + << fVal[5] << _T(")."); + } + } + catch (Parser::exception_type& e) + { + if (a_fPass) + { + if (fVal[0] != fVal[2] && fVal[0] != -999 && fVal[1] != -998) + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (copy construction)"); + else + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.GetMsg() << _T(")"); + return 1; + } + } + catch (std::exception& e) + { + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.what() << _T(")"); + return 1; // always return a failure since this exception is not expected + } + catch (...) + { + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)"); + return 1; // exceptions other than ParserException are not allowed + } + + return iRet; + } + + //--------------------------------------------------------------------------- + int ParserTester::EqnTestInt(const string_type& a_str, double a_fRes, bool a_fPass) + { + ParserTester::c_iCount++; + + value_type vVarVal[] = { 1, 2, 3 }; // variable values + int iRet(0); + + try + { + value_type fVal[2] = { -99, -999 }; // results: initially should be different + ParserInt p; + p.DefineConst(_T("const1"), 1); + p.DefineConst(_T("const2"), 2); + p.DefineVar(_T("a"), &vVarVal[0]); + p.DefineVar(_T("b"), &vVarVal[1]); + p.DefineVar(_T("c"), &vVarVal[2]); + + p.SetExpr(a_str); + fVal[0] = p.Eval(); // result from stringparsing + fVal[1] = p.Eval(); // result from bytecode + + if (fVal[0] != fVal[1]) + throw Parser::exception_type(_T("Bytecode corrupt.")); + + iRet = ((a_fRes == fVal[0] && a_fPass) || + (a_fRes != fVal[0] && !a_fPass)) ? 0 : 1; + if (iRet == 1) + { + mu::console() << _T("\n fail: ") << a_str.c_str() + << _T(" (incorrect result; expected: ") << a_fRes + << _T(" ;calculated: ") << fVal[0] << _T(")."); + } + } + catch (Parser::exception_type& e) + { + if (a_fPass) + { + mu::console() << _T("\n fail: ") << e.GetExpr() << _T(" : ") << e.GetMsg(); + iRet = 1; + } + } + catch (...) + { + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)"); + iRet = 1; // exceptions other than ParserException are not allowed + } + + return iRet; + } + + //--------------------------------------------------------------------------- + /** \brief Test an expression in Bulk Mode. */ + int ParserTester::EqnTestBulk(const string_type& a_str, double a_fRes[4], bool a_fPass) + { + ParserTester::c_iCount++; + + // Define Bulk Variables + int nBulkSize = 4; + value_type vVariableA[] = { 1, 2, 3, 4 }; // variable values + value_type vVariableB[] = { 2, 2, 2, 2 }; // variable values + value_type vVariableC[] = { 3, 3, 3, 3 }; // variable values + value_type vResults[] = { 0, 0, 0, 0 }; // variable values + int iRet(0); + + try + { + Parser p; + p.DefineConst(_T("const1"), 1); + p.DefineConst(_T("const2"), 2); + p.DefineVar(_T("a"), vVariableA); + p.DefineVar(_T("b"), vVariableB); + p.DefineVar(_T("c"), vVariableC); + + p.SetExpr(a_str); + p.Eval(vResults, nBulkSize); + + bool bCloseEnough(true); + for (int i = 0; i < nBulkSize; ++i) + { + bCloseEnough &= (fabs(a_fRes[i] - vResults[i]) <= fabs(a_fRes[i] * 0.00001)); + } + + iRet = ((bCloseEnough && a_fPass) || (!bCloseEnough && !a_fPass)) ? 0 : 1; + if (iRet == 1) + { + mu::console() << _T("\n fail: ") << a_str.c_str() + << _T(" (incorrect result; expected: {") << a_fRes[0] << _T(",") << a_fRes[1] << _T(",") << a_fRes[2] << _T(",") << a_fRes[3] << _T("}") + << _T(" ;calculated: ") << vResults[0] << _T(",") << vResults[1] << _T(",") << vResults[2] << _T(",") << vResults[3] << _T("}"); + } + } + catch (Parser::exception_type& e) + { + if (a_fPass) + { + mu::console() << _T("\n fail: ") << e.GetExpr() << _T(" : ") << e.GetMsg(); + iRet = 1; + } + } + catch (...) + { + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)"); + iRet = 1; // exceptions other than ParserException are not allowed + } + + return iRet; + } + + //--------------------------------------------------------------------------- + /** \brief Internal error in test class Test is going to be aborted. */ + void ParserTester::Abort() const + { + mu::console() << _T("Test failed (internal error in test class)") << endl; + while (!getchar()); + exit(-1); + } + } // namespace test +} // namespace mu diff --git a/3rdparty/muparser/muParserTest.h b/3rdparty/muparser/muParserTest.h new file mode 100644 index 00000000..a3582cd3 --- /dev/null +++ b/3rdparty/muparser/muParserTest.h @@ -0,0 +1,298 @@ +/* + + _____ __ _____________ _______ ______ ___________ + / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ + | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ + |__|_| /____/| __(____ /__| /____ >\___ >__| + \/ |__| \/ \/ \/ + Copyright (C) 2004 - 2022 Ingo Berg + + Redistribution and use in source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef MU_PARSER_TEST_H +#define MU_PARSER_TEST_H + +#include +#include +#include +#include // for accumulate +#include "muParser.h" +#include "muParserInt.h" + +#if defined(_MSC_VER) + #pragma warning(push) + #pragma warning(disable : 4251) // ...needs to have dll-interface to be used by clients of class ... +#endif + +/** \file + \brief This file contains the parser test class. +*/ + +namespace mu +{ + /** \brief Namespace for test cases. */ + namespace Test + { + /** \brief Test cases for unit testing. */ + class API_EXPORT_CXX ParserTester final + { + private: + static int c_iCount; + + static value_type f0() { return 42; }; + + // Multiarg callbacks + static value_type f1of1(value_type v) { return v; }; + + static value_type f1of2(value_type v, value_type) { return v; }; + static value_type f2of2(value_type, value_type v) { return v; }; + + static value_type f1of3(value_type v, value_type, value_type) { return v; }; + static value_type f2of3(value_type, value_type v, value_type) { return v; }; + static value_type f3of3(value_type, value_type, value_type v) { return v; }; + + static value_type f1of4(value_type v, value_type, value_type, value_type) { return v; } + static value_type f2of4(value_type, value_type v, value_type, value_type) { return v; } + static value_type f3of4(value_type, value_type, value_type v, value_type) { return v; } + static value_type f4of4(value_type, value_type, value_type, value_type v) { return v; } + + static value_type f1of5(value_type v, value_type, value_type, value_type, value_type) { return v; } + static value_type f2of5(value_type, value_type v, value_type, value_type, value_type) { return v; } + static value_type f3of5(value_type, value_type, value_type v, value_type, value_type) { return v; } + static value_type f4of5(value_type, value_type, value_type, value_type v, value_type) { return v; } + static value_type f5of5(value_type, value_type, value_type, value_type, value_type v) { return v; } + + static value_type Min(value_type a_fVal1, value_type a_fVal2) { return (a_fVal1 < a_fVal2) ? a_fVal1 : a_fVal2; } + static value_type Max(value_type a_fVal1, value_type a_fVal2) { return (a_fVal1 > a_fVal2) ? a_fVal1 : a_fVal2; } + + static value_type plus2(value_type v1) { return v1 + 2; } + static value_type times3(value_type v1) { return v1 * 3; } + static value_type sqr(value_type v1) { return v1 * v1; } + static value_type sign(value_type v) { return -v; } + static value_type add(value_type v1, value_type v2) { return v1 + v2; } + static value_type land(value_type v1, value_type v2) { return (int)v1 & (int)v2; } + + + static value_type FirstArg(const value_type* a_afArg, int a_iArgc) + { + if (!a_iArgc) + throw mu::Parser::exception_type(_T("too few arguments for function FirstArg.")); + + return a_afArg[0]; + } + + static value_type LastArg(const value_type* a_afArg, int a_iArgc) + { + if (!a_iArgc) + throw mu::Parser::exception_type(_T("too few arguments for function LastArg.")); + + return a_afArg[a_iArgc - 1]; + } + + static value_type Sum(const value_type* a_afArg, int a_iArgc) + { + if (!a_iArgc) + throw mu::Parser::exception_type(_T("too few arguments for function sum.")); + + value_type fRes = 0; + for (int i = 0; i < a_iArgc; ++i) fRes += a_afArg[i]; + return fRes; + } + + static value_type Rnd(value_type v) + { + return (value_type)(1 + (v * std::rand() / (RAND_MAX + 1.0))); + } + + static value_type RndWithString(const char_type*) + { + return (value_type)(1.0 + (1000.0 * std::rand() / (RAND_MAX + 1.0))); + } + + static value_type Ping() + { + return 10; + } + + static value_type ValueOf(const char_type*) + { + return 123; + } + + static value_type StrFun1(const char_type* v1) + { + int val(0); + stringstream_type(v1) >> val; + return (value_type)val; + } + + static value_type StrFun2(const char_type* v1, value_type v2) + { + int val(0); + stringstream_type(v1) >> val; + return (value_type)(val + v2); + } + + static value_type StrFun3(const char_type* v1, value_type v2, value_type v3) + { + int val(0); + stringstream_type(v1) >> val; + return val + v2 + v3; + } + + static value_type StrFun4(const char_type* v1, value_type v2, value_type v3, value_type v4) + { + int val(0); + stringstream_type(v1) >> val; + return val + v2 + v3 + v4; + } + + static value_type StrFun5(const char_type* v1, value_type v2, value_type v3, value_type v4, value_type v5) + { + int val(0); + stringstream_type(v1) >> val; + return val + v2 + v3 + v4 + v5; + } + + static value_type StrFun6(const char_type* v1, value_type v2, value_type v3, value_type v4, value_type v5, value_type v6) + { + int val(0); + stringstream_type(v1) >> val; + return val + v2 + v3 + v4 + v5 + v6; + } + + static value_type StrToFloat(const char_type* a_szMsg) + { + value_type val(0); + stringstream_type(a_szMsg) >> val; + return val; + } + + // postfix operator callback + static value_type Mega(value_type a_fVal) + { + return a_fVal * (value_type)1e6; + } + + static value_type Micro(value_type a_fVal) + { + return a_fVal * (value_type)1e-6; + } + + static value_type Milli(value_type a_fVal) + { + return a_fVal / (value_type)1e3; + } + + // Custom value recognition + static int IsHexVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal); + + // With user data + static value_type FunUd0(void* data) + { + return reinterpret_cast(data); + } + + static value_type FunUd1(void* data, value_type v) + { + return reinterpret_cast(data) + v; + } + + static value_type FunUd2(void* data, value_type v1, value_type v2) + { + return reinterpret_cast(data) + v1 + v2; + } + + static value_type FunUd10(void* data, value_type v1, value_type v2, value_type v3, value_type v4, value_type v5, value_type v6, value_type v7, value_type v8, value_type v9, value_type v10) + { + return reinterpret_cast(data) + v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8 + v9 + v10; + } + + static value_type StrFunUd3(void* data, const char_type* v1, value_type v2, value_type v3) + { + int val(0); + stringstream_type(v1) >> val; + return reinterpret_cast(data) + val + v2 + v3; + } + + static value_type SumUd(void* data, const value_type* a_afArg, int a_iArgc) + { + if (!a_iArgc) + throw mu::Parser::exception_type(_T("too few arguments for function sum.")); + + value_type fRes = 0; + for (int i = 0; i < a_iArgc; ++i) + fRes += a_afArg[i]; + + return reinterpret_cast(data) + fRes; + } + + int TestNames(); + int TestSyntax(); + int TestMultiArg(); + int TestPostFix(); + int TestExpression(); + int TestInfixOprt(); + int TestBinOprt(); + int TestVarConst(); + int TestInterface(); + int TestException(); + int TestStrArg(); + int TestIfThenElse(); + int TestBulkMode(); + int TestOssFuzzTestCases(); + int TestOptimizer(); + int TestLocalization(); + + void Abort() const; + + public: + typedef int (ParserTester::* testfun_type)(); + + ParserTester(); + int Run(); + + private: + std::vector m_vTestFun; + void AddTest(testfun_type a_pFun); + + // Test Double Parser + int EqnTest(const string_type& a_str, double a_fRes, bool a_fPass); + int EqnTestWithVarChange(const string_type& a_str, double a_fRes1, double a_fVar1, double a_fRes2, double a_fVar2); + int EqnTestLocalized(const string_type& a_str, double a_fRes, bool a_fPass); + int ThrowTest(const string_type& a_str, int a_iErrc, bool a_bFail = true); + + // Test Int Parser + int EqnTestInt(const string_type& a_str, double a_fRes, bool a_fPass); + + // Test Bulkmode + int EqnTestBulk(const string_type& a_str, double a_fRes[4], bool a_fPass); + + }; + } // namespace Test +} // namespace mu + + +#if defined(_MSC_VER) + #pragma warning(pop) +#endif + +#endif + diff --git a/3rdparty/muparser/muParserToken.h b/3rdparty/muparser/muParserToken.h index 0cca469b..3a40d06c 100644 --- a/3rdparty/muparser/muParserToken.h +++ b/3rdparty/muparser/muParserToken.h @@ -1,401 +1,524 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2004-2013 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef MU_PARSER_TOKEN_H -#define MU_PARSER_TOKEN_H - -#include -#include -#include -#include -#include - -#include "muParserError.h" -#include "muParserCallback.h" - -/** \file - \brief This file contains the parser token definition. -*/ - -namespace mu -{ - /** \brief Encapsulation of the data for a single formula token. - - Formula token implementation. Part of the Math Parser Package. - Formula tokens can be either one of the following: -
    -
  • value
  • -
  • variable
  • -
  • function with numerical arguments
  • -
  • functions with a string as argument
  • -
  • prefix operators
  • -
  • infix operators
  • -
  • binary operator
  • -
- - \author (C) 2004-2013 Ingo Berg - */ - template - class ParserToken - { - private: - - ECmdCode m_iCode; ///< Type of the token; The token type is a constant of type #ECmdCode. - ETypeCode m_iType; - void *m_pTok; ///< Stores Token pointer; not applicable for all tokens - int m_iIdx; ///< An otional index to an external buffer storing the token data - TString m_strTok; ///< Token string - TString m_strVal; ///< Value for string variables - value_type m_fVal; ///< the value - std::unique_ptr m_pCallback; - - public: - - //--------------------------------------------------------------------------- - /** \brief Constructor (default). - - Sets token to an neutral state of type cmUNKNOWN. - \throw nothrow - \sa ECmdCode - */ - ParserToken() - :m_iCode(cmUNKNOWN) - ,m_iType(tpVOID) - ,m_pTok(0) - ,m_iIdx(-1) - ,m_strTok() - ,m_strVal() - ,m_fVal(0) - ,m_pCallback() - {} - - //------------------------------------------------------------------------------ - /** \brief Create token from another one. - - Implemented by calling Assign(...) - \throw nothrow - \post m_iType==cmUNKNOWN - \sa #Assign - */ - ParserToken(const ParserToken &a_Tok) - { - Assign(a_Tok); - } - - //------------------------------------------------------------------------------ - /** \brief Assignement operator. - - Copy token state from another token and return this. - Implemented by calling Assign(...). - \throw nothrow - */ - ParserToken& operator=(const ParserToken &a_Tok) - { - Assign(a_Tok); - return *this; - } - - //------------------------------------------------------------------------------ - /** \brief Copy token information from argument. - - \throw nothrow - */ - void Assign(const ParserToken &a_Tok) - { - m_iCode = a_Tok.m_iCode; - m_pTok = a_Tok.m_pTok; - m_strTok = a_Tok.m_strTok; - m_iIdx = a_Tok.m_iIdx; - m_strVal = a_Tok.m_strVal; - m_iType = a_Tok.m_iType; - m_fVal = a_Tok.m_fVal; - // create new callback object if a_Tok has one - m_pCallback.reset(a_Tok.m_pCallback.get() ? a_Tok.m_pCallback->Clone() : 0); - } - - //------------------------------------------------------------------------------ - /** \brief Assign a token type. - - Token may not be of type value, variable or function. Those have seperate set functions. - - \pre [assert] a_iType!=cmVAR - \pre [assert] a_iType!=cmVAL - \pre [assert] a_iType!=cmFUNC - \post m_fVal = 0 - \post m_pTok = 0 - */ - ParserToken& Set(ECmdCode a_iType, const TString &a_strTok=TString()) - { - // The following types cant be set this way, they have special Set functions - assert(a_iType!=cmVAR); - assert(a_iType!=cmVAL); - assert(a_iType!=cmFUNC); - - m_iCode = a_iType; - m_iType = tpVOID; - m_pTok = 0; - m_strTok = a_strTok; - m_iIdx = -1; - - return *this; - } - - //------------------------------------------------------------------------------ - /** \brief Set Callback type. */ - ParserToken& Set(const ParserCallback &a_pCallback, const TString &a_sTok) - { - assert(a_pCallback.GetAddr()); - - m_iCode = a_pCallback.GetCode(); - m_iType = tpVOID; - m_strTok = a_sTok; - m_pCallback.reset(new ParserCallback(a_pCallback)); - - m_pTok = 0; - m_iIdx = -1; - - return *this; - } - - //------------------------------------------------------------------------------ - /** \brief Make this token a value token. - - Member variables not necessary for value tokens will be invalidated. - \throw nothrow - */ - ParserToken& SetVal(TBase a_fVal, const TString &a_strTok=TString()) - { - m_iCode = cmVAL; - m_iType = tpDBL; - m_fVal = a_fVal; - m_strTok = a_strTok; - m_iIdx = -1; - - m_pTok = 0; - m_pCallback.reset(0); - - return *this; - } - - //------------------------------------------------------------------------------ - /** \brief make this token a variable token. - - Member variables not necessary for variable tokens will be invalidated. - \throw nothrow - */ - ParserToken& SetVar(TBase *a_pVar, const TString &a_strTok) - { - m_iCode = cmVAR; - m_iType = tpDBL; - m_strTok = a_strTok; - m_iIdx = -1; - m_pTok = (void*)a_pVar; - m_pCallback.reset(0); - return *this; - } - - //------------------------------------------------------------------------------ - /** \brief Make this token a variable token. - - Member variables not necessary for variable tokens will be invalidated. - \throw nothrow - */ - ParserToken& SetString(const TString &a_strTok, std::size_t a_iSize) - { - m_iCode = cmSTRING; - m_iType = tpSTR; - m_strTok = a_strTok; - m_iIdx = static_cast(a_iSize); - - m_pTok = 0; - m_pCallback.reset(0); - return *this; - } - - //------------------------------------------------------------------------------ - /** \brief Set an index associated with the token related data. - - In cmSTRFUNC - This is the index to a string table in the main parser. - \param a_iIdx The index the string function result will take in the bytecode parser. - \throw exception_type if #a_iIdx<0 or #m_iType!=cmSTRING - */ - void SetIdx(int a_iIdx) - { - if (m_iCode!=cmSTRING || a_iIdx<0) - throw ParserError(ecINTERNAL_ERROR); - - m_iIdx = a_iIdx; - } - - //------------------------------------------------------------------------------ - /** \brief Return Index associated with the token related data. - - In cmSTRFUNC - This is the index to a string table in the main parser. - - \throw exception_type if #m_iIdx<0 or #m_iType!=cmSTRING - \return The index the result will take in the Bytecode calculatin array (#m_iIdx). - */ - int GetIdx() const - { - if (m_iIdx<0 || m_iCode!=cmSTRING ) - throw ParserError(ecINTERNAL_ERROR); - - return m_iIdx; - } - - //------------------------------------------------------------------------------ - /** \brief Return the token type. - - \return #m_iType - \throw nothrow - */ - ECmdCode GetCode() const - { - if (m_pCallback.get()) - { - return m_pCallback->GetCode(); - } - else - { - return m_iCode; - } - } - - //------------------------------------------------------------------------------ - ETypeCode GetType() const - { - if (m_pCallback.get()) - { - return m_pCallback->GetType(); - } - else - { - return m_iType; - } - } - - //------------------------------------------------------------------------------ - int GetPri() const - { - if ( !m_pCallback.get()) - throw ParserError(ecINTERNAL_ERROR); - - if ( m_pCallback->GetCode()!=cmOPRT_BIN && m_pCallback->GetCode()!=cmOPRT_INFIX) - throw ParserError(ecINTERNAL_ERROR); - - return m_pCallback->GetPri(); - } - - //------------------------------------------------------------------------------ - EOprtAssociativity GetAssociativity() const - { - if (m_pCallback.get()==NULL || m_pCallback->GetCode()!=cmOPRT_BIN) - throw ParserError(ecINTERNAL_ERROR); - - return m_pCallback->GetAssociativity(); - } - - //------------------------------------------------------------------------------ - /** \brief Return the address of the callback function assoziated with - function and operator tokens. - - \return The pointer stored in #m_pTok. - \throw exception_type if token type is non of: -
    -
  • cmFUNC
  • -
  • cmSTRFUNC
  • -
  • cmPOSTOP
  • -
  • cmINFIXOP
  • -
  • cmOPRT_BIN
  • -
- \sa ECmdCode - */ - generic_fun_type GetFuncAddr() const - { - return (m_pCallback.get()) ? (generic_fun_type)m_pCallback->GetAddr() : 0; - } - - //------------------------------------------------------------------------------ - /** \biref Get value of the token. - - Only applicable to variable and value tokens. - \throw exception_type if token is no value/variable token. - */ - TBase GetVal() const - { - switch (m_iCode) - { - case cmVAL: return m_fVal; - case cmVAR: return *((TBase*)m_pTok); - default: throw ParserError(ecVAL_EXPECTED); - } - } - - //------------------------------------------------------------------------------ - /** \brief Get address of a variable token. - - Valid only if m_iType==CmdVar. - \throw exception_type if token is no variable token. - */ - TBase* GetVar() const - { - if (m_iCode!=cmVAR) - throw ParserError(ecINTERNAL_ERROR); - - return (TBase*)m_pTok; - } - - //------------------------------------------------------------------------------ - /** \brief Return the number of function arguments. - - Valid only if m_iType==CmdFUNC. - */ - int GetArgCount() const - { - assert(m_pCallback.get()); - - if (!m_pCallback->GetAddr()) - throw ParserError(ecINTERNAL_ERROR); - - return m_pCallback->GetArgc(); - } - - //------------------------------------------------------------------------------ - /** \brief Return the token identifier. - - If #m_iType is cmSTRING the token identifier is the value of the string argument - for a string function. - \return #m_strTok - \throw nothrow - \sa m_strTok - */ - const TString& GetAsString() const - { - return m_strTok; - } - }; -} // namespace mu - -#endif +/* + + _____ __ _____________ _______ ______ ___________ + / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ + | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ + |__|_| /____/| __(____ /__| /____ >\___ >__| + \/ |__| \/ \/ \/ + Copyright (C) 2004 - 2022 Ingo Berg + + Redistribution and use in source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef MU_PARSER_TOKEN_H +#define MU_PARSER_TOKEN_H + +#include +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) + #pragma warning(push) + #pragma warning(disable : 26812) +#endif + +#include "muParserError.h" +#include "muParserCallback.h" + +/** \file + \brief This file contains the parser token definition. +*/ + +namespace mu +{ + template struct TplCallType; + template <> struct TplCallType<0> { using fun_type = fun_type0; using fun_userdata_type = fun_userdata_type0; using bulkfun_type = bulkfun_type0; using bulkfun_userdata_type = bulkfun_userdata_type0; }; + template <> struct TplCallType<1> { using fun_type = fun_type1; using fun_userdata_type = fun_userdata_type1; using bulkfun_type = bulkfun_type1; using bulkfun_userdata_type = bulkfun_userdata_type1; using strfun_type = strfun_type1; using strfun_userdata_type = strfun_userdata_type1; }; + template <> struct TplCallType<2> { using fun_type = fun_type2; using fun_userdata_type = fun_userdata_type2; using bulkfun_type = bulkfun_type2; using bulkfun_userdata_type = bulkfun_userdata_type2; using strfun_type = strfun_type2; using strfun_userdata_type = strfun_userdata_type2; }; + template <> struct TplCallType<3> { using fun_type = fun_type3; using fun_userdata_type = fun_userdata_type3; using bulkfun_type = bulkfun_type3; using bulkfun_userdata_type = bulkfun_userdata_type3; using strfun_type = strfun_type3; using strfun_userdata_type = strfun_userdata_type3; }; + template <> struct TplCallType<4> { using fun_type = fun_type4; using fun_userdata_type = fun_userdata_type4; using bulkfun_type = bulkfun_type4; using bulkfun_userdata_type = bulkfun_userdata_type4; using strfun_type = strfun_type4; using strfun_userdata_type = strfun_userdata_type4; }; + template <> struct TplCallType<5> { using fun_type = fun_type5; using fun_userdata_type = fun_userdata_type5; using bulkfun_type = bulkfun_type5; using bulkfun_userdata_type = bulkfun_userdata_type5; using strfun_type = strfun_type5; using strfun_userdata_type = strfun_userdata_type5; }; + template <> struct TplCallType<6> { using fun_type = fun_type6; using fun_userdata_type = fun_userdata_type6; using bulkfun_type = bulkfun_type6; using bulkfun_userdata_type = bulkfun_userdata_type6; using strfun_type = strfun_type6; using strfun_userdata_type = strfun_userdata_type6; }; + template <> struct TplCallType<7> { using fun_type = fun_type7; using fun_userdata_type = fun_userdata_type7; using bulkfun_type = bulkfun_type7; using bulkfun_userdata_type = bulkfun_userdata_type7; }; + template <> struct TplCallType<8> { using fun_type = fun_type8; using fun_userdata_type = fun_userdata_type8; using bulkfun_type = bulkfun_type8; using bulkfun_userdata_type = bulkfun_userdata_type8; }; + template <> struct TplCallType<9> { using fun_type = fun_type9; using fun_userdata_type = fun_userdata_type9; using bulkfun_type = bulkfun_type9; using bulkfun_userdata_type = bulkfun_userdata_type9; }; + template <> struct TplCallType<10> { using fun_type = fun_type10; using fun_userdata_type = fun_userdata_type10; using bulkfun_type = bulkfun_type10; using bulkfun_userdata_type = bulkfun_userdata_type10; }; + + struct generic_callable_type + { + // Note: we keep generic_callable_type a pod for the purpose of layout + + erased_fun_type _pRawFun; + void* _pUserData; + + template + value_type call_fun(Args&&... args) const + { + static_assert(NbParams == sizeof...(Args), "mismatch between NbParams and Args"); + if (_pUserData == nullptr) + { + auto fun_typed_ptr = reinterpret_cast::fun_type>(_pRawFun); + return (*fun_typed_ptr)(std::forward(args)...); + } + else + { + auto fun_userdata_typed_ptr = reinterpret_cast::fun_userdata_type>(_pRawFun); + return (*fun_userdata_typed_ptr)(_pUserData, std::forward(args)...); + } + } + + template + value_type call_bulkfun(Args&&... args) const + { + static_assert(NbParams == sizeof...(Args) - 2, "mismatch between NbParams and Args"); + if (_pUserData == nullptr) { + auto bulkfun_typed_ptr = reinterpret_cast::bulkfun_type>(_pRawFun); + return (*bulkfun_typed_ptr)(std::forward(args)...); + } else { + auto bulkfun_userdata_typed_ptr = reinterpret_cast::bulkfun_userdata_type>(_pRawFun); + return (*bulkfun_userdata_typed_ptr)(_pUserData, std::forward(args)...); + } + } + + value_type call_multfun(const value_type* a_afArg, int a_iArgc) const + { + if (_pUserData == nullptr) { + auto multfun_typed_ptr = reinterpret_cast(_pRawFun); + return (*multfun_typed_ptr)(a_afArg, a_iArgc); + } else { + auto multfun_userdata_typed_ptr = reinterpret_cast(_pRawFun); + return (*multfun_userdata_typed_ptr)(_pUserData, a_afArg, a_iArgc); + } + } + + template + value_type call_strfun(Args&&... args) const + { + static_assert(NbParams == sizeof...(Args), "mismatch between NbParams and Args"); + if (_pUserData == nullptr) + { + auto strfun_typed_ptr = reinterpret_cast::strfun_type>(_pRawFun); + return (*strfun_typed_ptr)(std::forward(args)...); + } + else + { + auto strfun_userdata_typed_ptr = reinterpret_cast::strfun_userdata_type>(_pRawFun); + return (*strfun_userdata_typed_ptr)(_pUserData, std::forward(args)...); + } + } + + bool operator==(generic_callable_type other) const + { + return _pRawFun == other._pRawFun && _pUserData == other._pUserData; + } + + explicit operator bool() const + { + return _pRawFun != nullptr; + } + + bool operator==(std::nullptr_t) const + { + return _pRawFun == nullptr; + } + + bool operator!=(std::nullptr_t) const + { + return _pRawFun != nullptr; + } + }; + + static_assert(std::is_trivial::value, "generic_callable_type shall be trivial"); + static_assert(std::is_standard_layout::value, "generic_callable_type shall have standard layout"); + // C++17: static_assert(std::is_aggregate::value, "generic_callable_type shall be an aggregate"); + + /** \brief Encapsulation of the data for a single formula token. + + Formula token implementation. Part of the Math Parser Package. + Formula tokens can be either one of the following: +
    +
  • value
  • +
  • variable
  • +
  • function with numerical arguments
  • +
  • functions with a string as argument
  • +
  • prefix operators
  • +
  • infix operators
  • +
  • binary operator
  • +
+ */ + template + class ParserToken final + { + private: + + ECmdCode m_iCode; ///< Type of the token; The token type is a constant of type #ECmdCode. + ETypeCode m_iType; + void* m_pTok; ///< Stores Token pointer; not applicable for all tokens + int m_iIdx; ///< An otional index to an external buffer storing the token data + TString m_strTok; ///< Token string + TString m_strVal; ///< Value for string variables + value_type m_fVal; ///< the value + std::unique_ptr m_pCallback; + + public: + + /** \brief Constructor (default). + + Sets token to an neutral state of type cmUNKNOWN. + \throw nothrow + \sa ECmdCode + */ + ParserToken() + :m_iCode(cmUNKNOWN) + , m_iType(tpVOID) + , m_pTok(0) + , m_iIdx(-1) + , m_strTok() + , m_strVal() + , m_fVal(0) + , m_pCallback() + {} + + //------------------------------------------------------------------------------ + /** \brief Create token from another one. + + Implemented by calling Assign(...) + \throw nothrow + \post m_iType==cmUNKNOWN + \sa #Assign + */ + ParserToken(const ParserToken& a_Tok) + { + Assign(a_Tok); + } + + + /** \brief Assignment operator. + + Copy token state from another token and return this. + Implemented by calling Assign(...). + \throw nothrow + */ + ParserToken& operator=(const ParserToken& a_Tok) + { + Assign(a_Tok); + return *this; + } + + + /** \brief Copy token information from argument. + + \throw nothrow + */ + void Assign(const ParserToken& a_Tok) + { + m_iCode = a_Tok.m_iCode; + m_pTok = a_Tok.m_pTok; + m_strTok = a_Tok.m_strTok; + m_iIdx = a_Tok.m_iIdx; + m_strVal = a_Tok.m_strVal; + m_iType = a_Tok.m_iType; + m_fVal = a_Tok.m_fVal; + // create new callback object if a_Tok has one + m_pCallback.reset(a_Tok.m_pCallback.get() ? a_Tok.m_pCallback->Clone() : 0); + } + + //------------------------------------------------------------------------------ + /** \brief Assign a token type. + + Token may not be of type value, variable or function. Those have separate set functions. + + \pre [assert] a_iType!=cmVAR + \pre [assert] a_iType!=cmVAL + \pre [assert] a_iType!=cmFUNC + \post m_fVal = 0 + \post m_pTok = 0 + */ + ParserToken& Set(ECmdCode a_iType, const TString& a_strTok = TString()) + { + // The following types can't be set this way, they have special Set functions + MUP_ASSERT(a_iType != cmVAR); + MUP_ASSERT(a_iType != cmVAL); + MUP_ASSERT(a_iType != cmFUNC); + + m_iCode = a_iType; + m_iType = tpVOID; + m_pTok = 0; + m_strTok = a_strTok; + m_iIdx = -1; + + return *this; + } + + //------------------------------------------------------------------------------ + /** \brief Set Callback type. */ + ParserToken& Set(const ParserCallback& a_pCallback, const TString& a_sTok) + { + MUP_ASSERT(a_pCallback.IsValid()); + + m_iCode = a_pCallback.GetCode(); + m_iType = tpVOID; + m_strTok = a_sTok; + m_pCallback.reset(new ParserCallback(a_pCallback)); + + m_pTok = 0; + m_iIdx = -1; + + return *this; + } + + //------------------------------------------------------------------------------ + /** \brief Make this token a value token. + + Member variables not necessary for value tokens will be invalidated. + \throw nothrow + */ + ParserToken& SetVal(TBase a_fVal, const TString& a_strTok = TString()) + { + m_iCode = cmVAL; + m_iType = tpDBL; + m_fVal = a_fVal; + m_strTok = a_strTok; + m_iIdx = -1; + + m_pTok = 0; + m_pCallback.reset(0); + + return *this; + } + + //------------------------------------------------------------------------------ + /** \brief make this token a variable token. + + Member variables not necessary for variable tokens will be invalidated. + \throw nothrow + */ + ParserToken& SetVar(TBase* a_pVar, const TString& a_strTok) + { + m_iCode = cmVAR; + m_iType = tpDBL; + m_strTok = a_strTok; + m_iIdx = -1; + m_pTok = (void*)a_pVar; + m_pCallback.reset(0); + return *this; + } + + //------------------------------------------------------------------------------ + /** \brief Make this token a variable token. + + Member variables not necessary for variable tokens will be invalidated. + \throw nothrow + */ + ParserToken& SetString(const TString& a_strTok, std::size_t a_iSize) + { + m_iCode = cmSTRING; + m_iType = tpSTR; + m_strTok = a_strTok; + m_iIdx = static_cast(a_iSize); + + m_pTok = 0; + m_pCallback.reset(0); + return *this; + } + + //------------------------------------------------------------------------------ + /** \brief Set an index associated with the token related data. + + In cmSTRFUNC - This is the index to a string table in the main parser. + \param a_iIdx The index the string function result will take in the bytecode parser. + \throw exception_type if #a_iIdx<0 or #m_iType!=cmSTRING + */ + void SetIdx(int a_iIdx) + { + if (m_iCode != cmSTRING || a_iIdx < 0) + throw ParserError(ecINTERNAL_ERROR); + + m_iIdx = a_iIdx; + } + + //------------------------------------------------------------------------------ + /** \brief Return Index associated with the token related data. + + In cmSTRFUNC - This is the index to a string table in the main parser. + + \throw exception_type if #m_iIdx<0 or #m_iType!=cmSTRING + \return The index the result will take in the Bytecode calculatin array (#m_iIdx). + */ + int GetIdx() const + { + if (m_iIdx < 0 || m_iCode != cmSTRING) + throw ParserError(ecINTERNAL_ERROR); + + return m_iIdx; + } + + //------------------------------------------------------------------------------ + /** \brief Return the token type. + + \return #m_iType + \throw nothrow + */ + ECmdCode GetCode() const + { + if (m_pCallback.get()) + { + return m_pCallback->GetCode(); + } + else + { + return m_iCode; + } + } + + //------------------------------------------------------------------------------ + ETypeCode GetType() const + { + if (m_pCallback.get()) + { + return m_pCallback->GetType(); + } + else + { + return m_iType; + } + } + + //------------------------------------------------------------------------------ + int GetPri() const + { + if (!m_pCallback.get()) + throw ParserError(ecINTERNAL_ERROR); + + if (m_pCallback->GetCode() != cmOPRT_BIN && m_pCallback->GetCode() != cmOPRT_INFIX) + throw ParserError(ecINTERNAL_ERROR); + + return m_pCallback->GetPri(); + } + + //------------------------------------------------------------------------------ + EOprtAssociativity GetAssociativity() const + { + if (m_pCallback.get() == nullptr || m_pCallback->GetCode() != cmOPRT_BIN) + throw ParserError(ecINTERNAL_ERROR); + + return m_pCallback->GetAssociativity(); + } + + //------------------------------------------------------------------------------ + /** \brief Return the address of the callback function assoziated with + function and operator tokens. + + \return The pointer stored in #m_pTok. + \throw exception_type if token type is non of: +
    +
  • cmFUNC
  • +
  • cmSTRFUNC
  • +
  • cmPOSTOP
  • +
  • cmINFIXOP
  • +
  • cmOPRT_BIN
  • +
+ \sa ECmdCode + */ + generic_callable_type GetFuncAddr() const + { + return (m_pCallback.get()) + ? generic_callable_type{(erased_fun_type)m_pCallback->GetAddr(), + m_pCallback->GetUserData()} + : generic_callable_type{}; + } + + //------------------------------------------------------------------------------ + /** \biref Get value of the token. + + Only applicable to variable and value tokens. + \throw exception_type if token is no value/variable token. + */ + TBase GetVal() const + { + switch (m_iCode) + { + case cmVAL: return m_fVal; + case cmVAR: return *((TBase*)m_pTok); + default: throw ParserError(ecVAL_EXPECTED); + } + } + + //------------------------------------------------------------------------------ + /** \brief Get address of a variable token. + + Valid only if m_iType==CmdVar. + \throw exception_type if token is no variable token. + */ + TBase* GetVar() const + { + if (m_iCode != cmVAR) + throw ParserError(ecINTERNAL_ERROR); + + return (TBase*)m_pTok; + } + + //------------------------------------------------------------------------------ + /** \brief Return the number of function arguments. + + Valid only if m_iType==CmdFUNC. + */ + int GetArgCount() const + { + MUP_ASSERT(m_pCallback.get()); + + if (!m_pCallback->IsValid()) + throw ParserError(ecINTERNAL_ERROR); + + return m_pCallback->GetArgc(); + } + + //------------------------------------------------------------------------------ + /** \brief Return true if the token is a function token that can be optimized. + */ + bool IsOptimizable() const + { + return m_pCallback->IsValid() && m_pCallback->IsOptimizable(); + } + + //------------------------------------------------------------------------------ + /** \brief Return the token identifier. + + If #m_iType is cmSTRING the token identifier is the value of the string argument + for a string function. + \return #m_strTok + \throw nothrow + \sa m_strTok + */ + const TString& GetAsString() const + { + return m_strTok; + } + }; +} // namespace mu + +#if defined(_MSC_VER) + #pragma warning(pop) +#endif + +#endif diff --git a/3rdparty/muparser/muParserTokenReader.cpp b/3rdparty/muparser/muParserTokenReader.cpp index 49cee68c..34c8800a 100644 --- a/3rdparty/muparser/muParserTokenReader.cpp +++ b/3rdparty/muparser/muParserTokenReader.cpp @@ -1,958 +1,997 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2013 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -#include -#include -#include -#include -#include -#include - -#include "muParserTokenReader.h" -#include "muParserBase.h" - -/** \file - \brief This file contains the parser token reader implementation. -*/ - - -namespace mu -{ - - // Forward declaration - class ParserBase; - - //--------------------------------------------------------------------------- - /** \brief Copy constructor. - - \sa Assign - \throw nothrow - */ - ParserTokenReader::ParserTokenReader(const ParserTokenReader &a_Reader) - { - Assign(a_Reader); - } - - //--------------------------------------------------------------------------- - /** \brief Assignment operator. - - Self assignment will be suppressed otherwise #Assign is called. - - \param a_Reader Object to copy to this token reader. - \throw nothrow - */ - ParserTokenReader& ParserTokenReader::operator=(const ParserTokenReader &a_Reader) - { - if (&a_Reader!=this) - Assign(a_Reader); - - return *this; - } - - //--------------------------------------------------------------------------- - /** \brief Assign state of a token reader to this token reader. - - \param a_Reader Object from which the state should be copied. - \throw nothrow - */ - void ParserTokenReader::Assign(const ParserTokenReader &a_Reader) - { - m_pParser = a_Reader.m_pParser; - m_strFormula = a_Reader.m_strFormula; - m_iPos = a_Reader.m_iPos; - m_iSynFlags = a_Reader.m_iSynFlags; - - m_UsedVar = a_Reader.m_UsedVar; - m_pFunDef = a_Reader.m_pFunDef; - m_pConstDef = a_Reader.m_pConstDef; - m_pVarDef = a_Reader.m_pVarDef; - m_pStrVarDef = a_Reader.m_pStrVarDef; - m_pPostOprtDef = a_Reader.m_pPostOprtDef; - m_pInfixOprtDef = a_Reader.m_pInfixOprtDef; - m_pOprtDef = a_Reader.m_pOprtDef; - m_bIgnoreUndefVar = a_Reader.m_bIgnoreUndefVar; - m_vIdentFun = a_Reader.m_vIdentFun; - m_pFactory = a_Reader.m_pFactory; - m_pFactoryData = a_Reader.m_pFactoryData; - m_iBrackets = a_Reader.m_iBrackets; - m_cArgSep = a_Reader.m_cArgSep; - m_fZero = a_Reader.m_fZero; - m_lastTok = a_Reader.m_lastTok; - } - - //--------------------------------------------------------------------------- - /** \brief Constructor. - - Create a Token reader and bind it to a parser object. - - \pre [assert] a_pParser may not be NULL - \post #m_pParser==a_pParser - \param a_pParent Parent parser object of the token reader. - */ - ParserTokenReader::ParserTokenReader(ParserBase *a_pParent) - :m_pParser(a_pParent) - ,m_strFormula() - ,m_iPos(0) - ,m_iSynFlags(0) - ,m_bIgnoreUndefVar(false) - ,m_pFunDef(NULL) - ,m_pPostOprtDef(NULL) - ,m_pInfixOprtDef(NULL) - ,m_pOprtDef(NULL) - ,m_pConstDef(NULL) - ,m_pStrVarDef(NULL) - ,m_pVarDef(NULL) - ,m_pFactory(NULL) - ,m_pFactoryData(NULL) - ,m_vIdentFun() - ,m_UsedVar() - ,m_fZero(0) - ,m_iBrackets(0) - ,m_lastTok() - ,m_cArgSep(',') - { - assert(m_pParser); - SetParent(m_pParser); - } - - //--------------------------------------------------------------------------- - /** \brief Create instance of a ParserTokenReader identical with this - and return its pointer. - - This is a factory method the calling function must take care of the object destruction. - - \return A new ParserTokenReader object. - \throw nothrow - */ - ParserTokenReader* ParserTokenReader::Clone(ParserBase *a_pParent) const - { - std::unique_ptr ptr(new ParserTokenReader(*this)); - ptr->SetParent(a_pParent); - return ptr.release(); - } - - //--------------------------------------------------------------------------- - ParserTokenReader::token_type& ParserTokenReader::SaveBeforeReturn(const token_type &tok) - { - m_lastTok = tok; - return m_lastTok; - } - - //--------------------------------------------------------------------------- - void ParserTokenReader::AddValIdent(identfun_type a_pCallback) - { - // Use push_front is used to give user defined callbacks a higher priority than - // the built in ones. Otherwise reading hex numbers would not work - // since the "0" in "0xff" would always be read first making parsing of - // the rest impossible. - // reference: - // http://sourceforge.net/projects/muparser/forums/forum/462843/topic/4824956 - m_vIdentFun.push_front(a_pCallback); - } - - //--------------------------------------------------------------------------- - void ParserTokenReader::SetVarCreator(facfun_type a_pFactory, void *pUserData) - { - m_pFactory = a_pFactory; - m_pFactoryData = pUserData; - } - - //--------------------------------------------------------------------------- - /** \brief Return the current position of the token reader in the formula string. - - \return #m_iPos - \throw nothrow - */ - int ParserTokenReader::GetPos() const - { - return m_iPos; - } - - //--------------------------------------------------------------------------- - /** \brief Return a reference to the formula. - - \return #m_strFormula - \throw nothrow - */ - const string_type& ParserTokenReader::GetExpr() const - { - return m_strFormula; - } - - //--------------------------------------------------------------------------- - /** \brief Return a map containing the used variables only. */ - varmap_type& ParserTokenReader::GetUsedVar() - { - return m_UsedVar; - } - - //--------------------------------------------------------------------------- - /** \brief Initialize the token Reader. - - Sets the formula position index to zero and set Syntax flags to default for initial formula parsing. - \pre [assert] triggered if a_szFormula==0 - */ - void ParserTokenReader::SetFormula(const string_type &a_strFormula) - { - m_strFormula = a_strFormula; - ReInit(); - } - - //--------------------------------------------------------------------------- - /** \brief Set Flag that controls behaviour in case of undefined variables being found. - - If true, the parser does not throw an exception if an undefined variable is found. - otherwise it does. This variable is used internally only! - It suppresses a "undefined variable" exception in GetUsedVar(). - Those function should return a complete list of variables including - those the are not defined by the time of it's call. - */ - void ParserTokenReader::IgnoreUndefVar(bool bIgnore) - { - m_bIgnoreUndefVar = bIgnore; - } - - //--------------------------------------------------------------------------- - /** \brief Reset the token reader to the start of the formula. - - The syntax flags will be reset to a value appropriate for the - start of a formula. - \post #m_iPos==0, #m_iSynFlags = noOPT | noBC | noPOSTOP | noSTR - \throw nothrow - \sa ESynCodes - */ - void ParserTokenReader::ReInit() - { - m_iPos = 0; - m_iSynFlags = sfSTART_OF_LINE; - m_iBrackets = 0; - m_UsedVar.clear(); - m_lastTok = token_type(); - } - - //--------------------------------------------------------------------------- - /** \brief Read the next token from the string. */ - ParserTokenReader::token_type ParserTokenReader::ReadNextToken() - { - assert(m_pParser); - - const char_type *szFormula = m_strFormula.c_str(); - token_type tok; - - // Ignore all non printable characters when reading the expression - while (szFormula[m_iPos]>0 && szFormula[m_iPos]<=0x20) - ++m_iPos; - - if ( IsEOF(tok) ) return SaveBeforeReturn(tok); // Check for end of formula - if ( IsOprt(tok) ) return SaveBeforeReturn(tok); // Check for user defined binary operator - if ( IsFunTok(tok) ) return SaveBeforeReturn(tok); // Check for function token - if ( IsBuiltIn(tok) ) return SaveBeforeReturn(tok); // Check built in operators / tokens - if ( IsArgSep(tok) ) return SaveBeforeReturn(tok); // Check for function argument separators - if ( IsValTok(tok) ) return SaveBeforeReturn(tok); // Check for values / constant tokens - if ( IsVarTok(tok) ) return SaveBeforeReturn(tok); // Check for variable tokens - if ( IsStrVarTok(tok) ) return SaveBeforeReturn(tok); // Check for string variables - if ( IsString(tok) ) return SaveBeforeReturn(tok); // Check for String tokens - if ( IsInfixOpTok(tok) ) return SaveBeforeReturn(tok); // Check for unary operators - if ( IsPostOpTok(tok) ) return SaveBeforeReturn(tok); // Check for unary operators - - // Check String for undefined variable token. Done only if a - // flag is set indicating to ignore undefined variables. - // This is a way to conditionally avoid an error if - // undefined variables occur. - // (The GetUsedVar function must suppress the error for - // undefined variables in order to collect all variable - // names including the undefined ones.) - if ( (m_bIgnoreUndefVar || m_pFactory) && IsUndefVarTok(tok) ) - return SaveBeforeReturn(tok); - - // Check for unknown token - // - // !!! From this point on there is no exit without an exception possible... - // - string_type strTok; - int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos); - if (iEnd!=m_iPos) - Error(ecUNASSIGNABLE_TOKEN, m_iPos, strTok); - - Error(ecUNASSIGNABLE_TOKEN, m_iPos, m_strFormula.substr(m_iPos)); - return token_type(); // never reached - } - - //--------------------------------------------------------------------------- - void ParserTokenReader::SetParent(ParserBase *a_pParent) - { - m_pParser = a_pParent; - m_pFunDef = &a_pParent->m_FunDef; - m_pOprtDef = &a_pParent->m_OprtDef; - m_pInfixOprtDef = &a_pParent->m_InfixOprtDef; - m_pPostOprtDef = &a_pParent->m_PostOprtDef; - m_pVarDef = &a_pParent->m_VarDef; - m_pStrVarDef = &a_pParent->m_StrVarDef; - m_pConstDef = &a_pParent->m_ConstDef; - } - - //--------------------------------------------------------------------------- - /** \brief Extract all characters that belong to a certain charset. - - \param a_szCharSet [in] Const char array of the characters allowed in the token. - \param a_strTok [out] The string that consists entirely of characters listed in a_szCharSet. - \param a_iPos [in] Position in the string from where to start reading. - \return The Position of the first character not listed in a_szCharSet. - \throw nothrow - */ - int ParserTokenReader::ExtractToken(const char_type *a_szCharSet, - string_type &a_sTok, - int a_iPos) const - { - int iEnd = (int)m_strFormula.find_first_not_of(a_szCharSet, a_iPos); - - if (iEnd==(int)string_type::npos) - iEnd = (int)m_strFormula.length(); - - // Assign token string if there was something found - if (a_iPos!=iEnd) - a_sTok = string_type( m_strFormula.begin()+a_iPos, m_strFormula.begin()+iEnd); - - return iEnd; - } - - //--------------------------------------------------------------------------- - /** \brief Check Expression for the presence of a binary operator token. - - Userdefined binary operator "++" gives inconsistent parsing result for - the equations "a++b" and "a ++ b" if alphabetic characters are allowed - in operator tokens. To avoid this this function checks specifically - for operator tokens. - */ - int ParserTokenReader::ExtractOperatorToken(string_type &a_sTok, - int a_iPos) const - { - // Changed as per Issue 6: https://code.google.com/p/muparser/issues/detail?id=6 - int iEnd = (int)m_strFormula.find_first_not_of(m_pParser->ValidOprtChars(), a_iPos); - if (iEnd==(int)string_type::npos) - iEnd = (int)m_strFormula.length(); - - // Assign token string if there was something found - if (a_iPos!=iEnd) - { - a_sTok = string_type( m_strFormula.begin() + a_iPos, m_strFormula.begin() + iEnd); - return iEnd; - } - else - { - // There is still the chance of having to deal with an operator consisting exclusively - // of alphabetic characters. - return ExtractToken(MUP_CHARS, a_sTok, a_iPos); - } - } - - //--------------------------------------------------------------------------- - /** \brief Check if a built in operator or other token can be found - \param a_Tok [out] Operator token if one is found. This can either be a binary operator or an infix operator token. - \return true if an operator token has been found. - */ - bool ParserTokenReader::IsBuiltIn(token_type &a_Tok) - { - const char_type **const pOprtDef = m_pParser->GetOprtDef(), - *const szFormula = m_strFormula.c_str(); - - // Compare token with function and operator strings - // check string for operator/function - for (int i=0; pOprtDef[i]; i++) - { - std::size_t len( std::char_traits::length(pOprtDef[i]) ); - if ( string_type(pOprtDef[i]) == string_type(szFormula + m_iPos, szFormula + m_iPos + len) ) - { - switch(i) - { - //case cmAND: - //case cmOR: - //case cmXOR: - case cmLAND: - case cmLOR: - case cmLT: - case cmGT: - case cmLE: - case cmGE: - case cmNEQ: - case cmEQ: - case cmADD: - case cmSUB: - case cmMUL: - case cmDIV: - case cmPOW: - case cmASSIGN: - //if (len!=sTok.length()) - // continue; - - // The assignment operator need special treatment - if (i==cmASSIGN && m_iSynFlags & noASSIGN) - Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]); - - if (!m_pParser->HasBuiltInOprt()) continue; - if (m_iSynFlags & noOPT) - { - // Maybe its an infix operator not an operator - // Both operator types can share characters in - // their identifiers - if ( IsInfixOpTok(a_Tok) ) - return true; - - Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]); - } - - m_iSynFlags = noBC | noOPT | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE | noEND; - break; - - case cmBO: - if (m_iSynFlags & noBO) - Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); - - if (m_lastTok.GetCode()==cmFUNC) - m_iSynFlags = noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE; - else - m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN| noIF | noELSE; - - ++m_iBrackets; - break; - - case cmBC: - if (m_iSynFlags & noBC) - Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); - - m_iSynFlags = noBO | noVAR | noVAL | noFUN | noINFIXOP | noSTR | noASSIGN; - - if (--m_iBrackets<0) - Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); - break; - - case cmELSE: - if (m_iSynFlags & noELSE) - Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]); - - m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE; - break; - - case cmIF: - if (m_iSynFlags & noIF) - Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]); - - m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE; - break; - - default: // The operator is listed in c_DefaultOprt, but not here. This is a bad thing... - Error(ecINTERNAL_ERROR); - } // switch operator id - - m_iPos += (int)len; - a_Tok.Set( (ECmdCode)i, pOprtDef[i] ); - return true; - } // if operator string found - } // end of for all operator strings - - return false; - } - - //--------------------------------------------------------------------------- - bool ParserTokenReader::IsArgSep(token_type &a_Tok) - { - const char_type* szFormula = m_strFormula.c_str(); - - if (szFormula[m_iPos]==m_cArgSep) - { - // copy the separator into null terminated string - char_type szSep[2]; - szSep[0] = m_cArgSep; - szSep[1] = 0; - - if (m_iSynFlags & noARG_SEP) - Error(ecUNEXPECTED_ARG_SEP, m_iPos, szSep); - - m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN; - m_iPos++; - a_Tok.Set(cmARG_SEP, szSep); - return true; - } - - return false; - } - - //--------------------------------------------------------------------------- - /** \brief Check for End of Formula. - - \return true if an end of formula is found false otherwise. - \param a_Tok [out] If an eof is found the corresponding token will be stored there. - \throw nothrow - \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsString, IsInfixOpTok, IsPostOpTok - */ - bool ParserTokenReader::IsEOF(token_type &a_Tok) - { - const char_type* szFormula = m_strFormula.c_str(); - - // check for EOF - if ( !szFormula[m_iPos] /*|| szFormula[m_iPos] == '\n'*/) - { - if ( m_iSynFlags & noEND ) - Error(ecUNEXPECTED_EOF, m_iPos); - - if (m_iBrackets>0) - Error(ecMISSING_PARENS, m_iPos, _T(")")); - - m_iSynFlags = 0; - a_Tok.Set(cmEND); - return true; - } - - return false; - } - - //--------------------------------------------------------------------------- - /** \brief Check if a string position contains a unary infix operator. - \return true if a function token has been found false otherwise. - */ - bool ParserTokenReader::IsInfixOpTok(token_type &a_Tok) - { - string_type sTok; - int iEnd = ExtractToken(m_pParser->ValidInfixOprtChars(), sTok, m_iPos); - if (iEnd==m_iPos) - return false; - - // iterate over all postfix operator strings - funmap_type::const_reverse_iterator it = m_pInfixOprtDef->rbegin(); - for ( ; it!=m_pInfixOprtDef->rend(); ++it) - { - if (sTok.find(it->first)!=0) - continue; - - a_Tok.Set(it->second, it->first); - m_iPos += (int)it->first.length(); - - if (m_iSynFlags & noINFIXOP) - Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); - - m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN; - return true; - } - - return false; - -/* - a_Tok.Set(item->second, sTok); - m_iPos = (int)iEnd; - - if (m_iSynFlags & noINFIXOP) - Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); - - m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN; - return true; -*/ - } - - //--------------------------------------------------------------------------- - /** \brief Check whether the token at a given position is a function token. - \param a_Tok [out] If a value token is found it will be placed here. - \throw ParserException if Syntaxflags do not allow a function at a_iPos - \return true if a function token has been found false otherwise. - \pre [assert] m_pParser!=0 - */ - bool ParserTokenReader::IsFunTok(token_type &a_Tok) - { - string_type strTok; - int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos); - if (iEnd==m_iPos) - return false; - - funmap_type::const_iterator item = m_pFunDef->find(strTok); - if (item==m_pFunDef->end()) - return false; - - // Check if the next sign is an opening bracket - const char_type *szFormula = m_strFormula.c_str(); - if (szFormula[iEnd]!='(') - return false; - - a_Tok.Set(item->second, strTok); - - m_iPos = (int)iEnd; - if (m_iSynFlags & noFUN) - Error(ecUNEXPECTED_FUN, m_iPos-(int)a_Tok.GetAsString().length(), a_Tok.GetAsString()); - - m_iSynFlags = noANY ^ noBO; - return true; - } - - //--------------------------------------------------------------------------- - /** \brief Check if a string position contains a binary operator. - \param a_Tok [out] Operator token if one is found. This can either be a binary operator or an infix operator token. - \return true if an operator token has been found. - */ - bool ParserTokenReader::IsOprt(token_type &a_Tok) - { - const char_type *const szExpr = m_strFormula.c_str(); - string_type strTok; - - int iEnd = ExtractOperatorToken(strTok, m_iPos); - if (iEnd==m_iPos) - return false; - - // Check if the operator is a built in operator, if so ignore it here - const char_type **const pOprtDef = m_pParser->GetOprtDef(); - for (int i=0; m_pParser->HasBuiltInOprt() && pOprtDef[i]; ++i) - { - if (string_type(pOprtDef[i])==strTok) - return false; - } - - // Note: - // All tokens in oprt_bin_maptype are have been sorted by their length - // Long operators must come first! Otherwise short names (like: "add") that - // are part of long token names (like: "add123") will be found instead - // of the long ones. - // Length sorting is done with ascending length so we use a reverse iterator here. - funmap_type::const_reverse_iterator it = m_pOprtDef->rbegin(); - for ( ; it!=m_pOprtDef->rend(); ++it) - { - const string_type &sID = it->first; - if ( sID == string_type(szExpr + m_iPos, szExpr + m_iPos + sID.length()) ) - { - a_Tok.Set(it->second, strTok); - - // operator was found - if (m_iSynFlags & noOPT) - { - // An operator was found but is not expected to occur at - // this position of the formula, maybe it is an infix - // operator, not a binary operator. Both operator types - // can share characters in their identifiers. - if ( IsInfixOpTok(a_Tok) ) - return true; - else - { - // nope, no infix operator - return false; - //Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); - } - - } - - m_iPos += (int)sID.length(); - m_iSynFlags = noBC | noOPT | noARG_SEP | noPOSTOP | noEND | noASSIGN; - return true; - } - } - - return false; - } - - //--------------------------------------------------------------------------- - /** \brief Check if a string position contains a unary post value operator. */ - bool ParserTokenReader::IsPostOpTok(token_type &a_Tok) - { - // Do not check for postfix operators if they are not allowed at - // the current expression index. - // - // This will fix the bug reported here: - // - // http://sourceforge.net/tracker/index.php?func=detail&aid=3343891&group_id=137191&atid=737979 - // - if (m_iSynFlags & noPOSTOP) - return false; - // - - // Tricky problem with equations like "3m+5": - // m is a postfix operator, + is a valid sign for postfix operators and - // for binary operators parser detects "m+" as operator string and - // finds no matching postfix operator. - // - // This is a special case so this routine slightly differs from the other - // token readers. - - // Test if there could be a postfix operator - string_type sTok; - int iEnd = ExtractToken(m_pParser->ValidOprtChars(), sTok, m_iPos); - if (iEnd==m_iPos) - return false; - - // iterate over all postfix operator strings - funmap_type::const_reverse_iterator it = m_pPostOprtDef->rbegin(); - for ( ; it!=m_pPostOprtDef->rend(); ++it) - { - if (sTok.find(it->first)!=0) - continue; - - a_Tok.Set(it->second, sTok); - m_iPos += (int)it->first.length(); - - m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noSTR | noASSIGN; - return true; - } - - return false; - } - - //--------------------------------------------------------------------------- - /** \brief Check whether the token at a given position is a value token. - - Value tokens are either values or constants. - - \param a_Tok [out] If a value token is found it will be placed here. - \return true if a value token has been found. - */ - bool ParserTokenReader::IsValTok(token_type &a_Tok) - { - assert(m_pConstDef); - assert(m_pParser); - - string_type strTok; - value_type fVal(0); - int iEnd(0); - - // 2.) Check for user defined constant - // Read everything that could be a constant name - iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos); - if (iEnd!=m_iPos) - { - valmap_type::const_iterator item = m_pConstDef->find(strTok); - if (item!=m_pConstDef->end()) - { - m_iPos = iEnd; - a_Tok.SetVal(item->second, strTok); - - if (m_iSynFlags & noVAL) - Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok); - - m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; - return true; - } - } - - // 3.call the value recognition functions provided by the user - // Call user defined value recognition functions - std::list::const_iterator item = m_vIdentFun.begin(); - for (item = m_vIdentFun.begin(); item!=m_vIdentFun.end(); ++item) - { - int iStart = m_iPos; - if ( (*item)(m_strFormula.c_str() + m_iPos, &m_iPos, &fVal)==1 ) - { - // 2013-11-27 Issue 2: https://code.google.com/p/muparser/issues/detail?id=2 - strTok.assign(m_strFormula.c_str(), iStart, m_iPos-iStart); - - if (m_iSynFlags & noVAL) - Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok); - - a_Tok.SetVal(fVal, strTok); - m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; - return true; - } - } - - return false; - } - - //--------------------------------------------------------------------------- - /** \brief Check wheter a token at a given position is a variable token. - \param a_Tok [out] If a variable token has been found it will be placed here. - \return true if a variable token has been found. - */ - bool ParserTokenReader::IsVarTok(token_type &a_Tok) - { - if (m_pVarDef->empty()) - return false; - - string_type strTok; - int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos); - if (iEnd==m_iPos) - return false; - - varmap_type::const_iterator item = m_pVarDef->find(strTok); - if (item==m_pVarDef->end()) - return false; - - if (m_iSynFlags & noVAR) - Error(ecUNEXPECTED_VAR, m_iPos, strTok); - - m_pParser->OnDetectVar(&m_strFormula, m_iPos, iEnd); - - m_iPos = iEnd; - a_Tok.SetVar(item->second, strTok); - m_UsedVar[item->first] = item->second; // Add variable to used-var-list - - m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR; - -// Zur Info hier die SynFlags von IsVal(): -// m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; - return true; - } - - //--------------------------------------------------------------------------- - bool ParserTokenReader::IsStrVarTok(token_type &a_Tok) - { - if (!m_pStrVarDef || m_pStrVarDef->empty()) - return false; - - string_type strTok; - int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos); - if (iEnd==m_iPos) - return false; - - strmap_type::const_iterator item = m_pStrVarDef->find(strTok); - if (item==m_pStrVarDef->end()) - return false; - - if (m_iSynFlags & noSTR) - Error(ecUNEXPECTED_VAR, m_iPos, strTok); - - m_iPos = iEnd; - if (!m_pParser->m_vStringVarBuf.size()) - Error(ecINTERNAL_ERROR); - - a_Tok.SetString(m_pParser->m_vStringVarBuf[item->second], m_pParser->m_vStringVarBuf.size() ); - - m_iSynFlags = noANY ^ ( noBC | noOPT | noEND | noARG_SEP); - return true; - } - - - //--------------------------------------------------------------------------- - /** \brief Check wheter a token at a given position is an undefined variable. - - \param a_Tok [out] If a variable tom_pParser->m_vStringBufken has been found it will be placed here. - \return true if a variable token has been found. - \throw nothrow - */ - bool ParserTokenReader::IsUndefVarTok(token_type &a_Tok) - { - string_type strTok; - int iEnd( ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos) ); - if ( iEnd==m_iPos ) - return false; - - if (m_iSynFlags & noVAR) - { - // 20061021 added token string strTok instead of a_Tok.GetAsString() as the - // token identifier. - // related bug report: - // http://sourceforge.net/tracker/index.php?func=detail&aid=1578779&group_id=137191&atid=737979 - Error(ecUNEXPECTED_VAR, m_iPos - (int)a_Tok.GetAsString().length(), strTok); - } - - // If a factory is available implicitely create new variables - if (m_pFactory) - { - value_type *fVar = m_pFactory(strTok.c_str(), m_pFactoryData); - a_Tok.SetVar(fVar, strTok ); - - // Do not use m_pParser->DefineVar( strTok, fVar ); - // in order to define the new variable, it will clear the - // m_UsedVar array which will kill previously defined variables - // from the list - // This is safe because the new variable can never override an existing one - // because they are checked first! - (*m_pVarDef)[strTok] = fVar; - m_UsedVar[strTok] = fVar; // Add variable to used-var-list - } - else - { - a_Tok.SetVar((value_type*)&m_fZero, strTok); - m_UsedVar[strTok] = 0; // Add variable to used-var-list - } - - m_iPos = iEnd; - - // Call the variable factory in order to let it define a new parser variable - m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noINFIXOP | noSTR; - return true; - } - - - //--------------------------------------------------------------------------- - /** \brief Check wheter a token at a given position is a string. - \param a_Tok [out] If a variable token has been found it will be placed here. - \return true if a string token has been found. - \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsEOF, IsInfixOpTok, IsPostOpTok - \throw nothrow - */ - bool ParserTokenReader::IsString(token_type &a_Tok) - { - if (m_strFormula[m_iPos]!='"') - return false; - - string_type strBuf(&m_strFormula[m_iPos+1]); - std::size_t iEnd(0), iSkip(0); - - // parser over escaped '\"' end replace them with '"' - for(iEnd=(int)strBuf.find( _T("\"") ); iEnd!=0 && iEnd!=string_type::npos; iEnd=(int)strBuf.find( _T("\""), iEnd)) - { - if (strBuf[iEnd-1]!='\\') break; - strBuf.replace(iEnd-1, 2, _T("\"") ); - iSkip++; - } - - if (iEnd==string_type::npos) - Error(ecUNTERMINATED_STRING, m_iPos, _T("\"") ); - - string_type strTok(strBuf.begin(), strBuf.begin()+iEnd); - - if (m_iSynFlags & noSTR) - Error(ecUNEXPECTED_STR, m_iPos, strTok); - - m_pParser->m_vStringBuf.push_back(strTok); // Store string in internal buffer - a_Tok.SetString(strTok, m_pParser->m_vStringBuf.size()); - - m_iPos += (int)strTok.length() + 2 + (int)iSkip; // +2 wg Anführungszeichen; +iSkip für entfernte escape zeichen - m_iSynFlags = noANY ^ ( noARG_SEP | noBC | noOPT | noEND ); - - return true; - } - - //--------------------------------------------------------------------------- - /** \brief Create an error containing the parse error position. - - This function will create an Parser Exception object containing the error text and its position. - - \param a_iErrc [in] The error code of type #EErrorCodes. - \param a_iPos [in] The position where the error was detected. - \param a_strTok [in] The token string representation associated with the error. - \throw ParserException always throws thats the only purpose of this function. - */ - void ParserTokenReader::Error( EErrorCodes a_iErrc, - int a_iPos, - const string_type &a_sTok) const - { - m_pParser->Error(a_iErrc, a_iPos, a_sTok); - } - - //--------------------------------------------------------------------------- - void ParserTokenReader::SetArgSep(char_type cArgSep) - { - m_cArgSep = cArgSep; - } - - //--------------------------------------------------------------------------- - char_type ParserTokenReader::GetArgSep() const - { - return m_cArgSep; - } -} // namespace mu - +/* + + _____ __ _____________ _______ ______ ___________ + / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ + | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ + |__|_| /____/| __(____ /__| /____ >\___ >__| + \/ |__| \/ \/ \/ + Copyright (C) 2004 - 2022 Ingo Berg + + Redistribution and use in source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#include +#include + +#include "muParserTokenReader.h" +#include "muParserBase.h" + +#if defined(_MSC_VER) + #pragma warning(push) + #pragma warning(disable : 26812) +#endif + +/** \file + \brief This file contains the parser token reader implementation. +*/ + + +namespace mu +{ + + // Forward declaration + class ParserBase; + + /** \brief Copy constructor. + + \sa Assign + \throw nothrow + */ + ParserTokenReader::ParserTokenReader(const ParserTokenReader& a_Reader) + { + Assign(a_Reader); + } + + + /** \brief Assignment operator. + + Self assignment will be suppressed otherwise #Assign is called. + + \param a_Reader Object to copy to this token reader. + \throw nothrow + */ + ParserTokenReader& ParserTokenReader::operator=(const ParserTokenReader& a_Reader) + { + if (&a_Reader != this) + Assign(a_Reader); + + return *this; + } + + + /** \brief Assign state of a token reader to this token reader. + + \param a_Reader Object from which the state should be copied. + \throw nothrow + */ + void ParserTokenReader::Assign(const ParserTokenReader& a_Reader) + { + m_pParser = a_Reader.m_pParser; + m_strFormula = a_Reader.m_strFormula; + m_iPos = a_Reader.m_iPos; + m_iSynFlags = a_Reader.m_iSynFlags; + + m_UsedVar = a_Reader.m_UsedVar; + m_pFunDef = a_Reader.m_pFunDef; + m_pConstDef = a_Reader.m_pConstDef; + m_pVarDef = a_Reader.m_pVarDef; + m_pStrVarDef = a_Reader.m_pStrVarDef; + m_pPostOprtDef = a_Reader.m_pPostOprtDef; + m_pInfixOprtDef = a_Reader.m_pInfixOprtDef; + m_pOprtDef = a_Reader.m_pOprtDef; + m_bIgnoreUndefVar = a_Reader.m_bIgnoreUndefVar; + m_vIdentFun = a_Reader.m_vIdentFun; + m_pFactory = a_Reader.m_pFactory; + m_pFactoryData = a_Reader.m_pFactoryData; + m_bracketStack = a_Reader.m_bracketStack; + m_cArgSep = a_Reader.m_cArgSep; + m_fZero = a_Reader.m_fZero; + m_lastTok = a_Reader.m_lastTok; + } + + + /** \brief Constructor. + + Create a Token reader and bind it to a parser object. + + \pre [assert] a_pParser may not be NULL + \post #m_pParser==a_pParser + \param a_pParent Parent parser object of the token reader. + */ + ParserTokenReader::ParserTokenReader(ParserBase* a_pParent) + :m_pParser(a_pParent) + , m_strFormula() + , m_iPos(0) + , m_iSynFlags(0) + , m_bIgnoreUndefVar(false) + , m_pFunDef(nullptr) + , m_pPostOprtDef(nullptr) + , m_pInfixOprtDef(nullptr) + , m_pOprtDef(nullptr) + , m_pConstDef(nullptr) + , m_pStrVarDef(nullptr) + , m_pVarDef(nullptr) + , m_pFactory(nullptr) + , m_pFactoryData(nullptr) + , m_vIdentFun() + , m_UsedVar() + , m_fZero(0) + , m_bracketStack() + , m_lastTok() + , m_cArgSep(',') + { + MUP_ASSERT(m_pParser != nullptr); + SetParent(m_pParser); + } + + + /** \brief Create instance of a ParserTokenReader identical with this + and return its pointer. + + This is a factory method the calling function must take care of the object destruction. + + \return A new ParserTokenReader object. + \throw nothrow + */ + ParserTokenReader* ParserTokenReader::Clone(ParserBase* a_pParent) const + { + std::unique_ptr ptr(new ParserTokenReader(*this)); + ptr->SetParent(a_pParent); + return ptr.release(); + } + + + ParserTokenReader::token_type& ParserTokenReader::SaveBeforeReturn(const token_type& tok) + { + m_lastTok = tok; + return m_lastTok; + } + + + void ParserTokenReader::AddValIdent(identfun_type a_pCallback) + { + // Use push_front is used to give user defined callbacks a higher priority than + // the built in ones. Otherwise reading hex numbers would not work + // since the "0" in "0xff" would always be read first making parsing of + // the rest impossible. + // reference: + // http://sourceforge.net/projects/muparser/forums/forum/462843/topic/4824956 + m_vIdentFun.push_front(a_pCallback); + } + + + void ParserTokenReader::SetVarCreator(facfun_type a_pFactory, void* pUserData) + { + m_pFactory = a_pFactory; + m_pFactoryData = pUserData; + } + + + /** \brief Return the current position of the token reader in the formula string. + + \return #m_iPos + \throw nothrow + */ + int ParserTokenReader::GetPos() const + { + return m_iPos; + } + + + /** \brief Return a reference to the formula. + + \return #m_strFormula + \throw nothrow + */ + const string_type& ParserTokenReader::GetExpr() const + { + return m_strFormula; + } + + + /** \brief Return a map containing the used variables only. */ + varmap_type& ParserTokenReader::GetUsedVar() + { + return m_UsedVar; + } + + + /** \brief Initialize the token Reader. + + Sets the formula position index to zero and set Syntax flags to default for initial formula parsing. + \pre [assert] triggered if a_szFormula==0 + */ + void ParserTokenReader::SetFormula(const string_type& a_strFormula) + { + m_strFormula = a_strFormula; + ReInit(); + } + + + /** \brief Set Flag that controls behaviour in case of undefined variables being found. + + If true, the parser does not throw an exception if an undefined variable is found. + otherwise it does. This variable is used internally only! + It suppresses a "undefined variable" exception in GetUsedVar(). + Those function should return a complete list of variables including + those the are not defined by the time of it's call. + */ + void ParserTokenReader::IgnoreUndefVar(bool bIgnore) + { + m_bIgnoreUndefVar = bIgnore; + } + + + /** \brief Reset the token reader to the start of the formula. + + The syntax flags will be reset to a value appropriate for the + start of a formula. + \post #m_iPos==0, #m_iSynFlags = noOPT | noBC | noPOSTOP | noSTR + \throw nothrow + \sa ESynCodes + */ + void ParserTokenReader::ReInit() + { + m_iPos = 0; + m_iSynFlags = sfSTART_OF_LINE; + m_bracketStack = std::stack(); + m_UsedVar.clear(); + m_lastTok = token_type(); + } + + + /** \brief Read the next token from the string. */ + ParserTokenReader::token_type ParserTokenReader::ReadNextToken() + { + MUP_ASSERT(m_pParser != nullptr); + + const char_type* szExpr = m_strFormula.c_str(); + token_type tok; + + // Ignore all non printable characters when reading the expression + while (szExpr[m_iPos] > 0 && szExpr[m_iPos] <= 0x20) + { + // 14-31 are control characters. I donÄt want to have to deal with such strings at all! + // (see https://en.cppreference.com/w/cpp/string/byte/isprint) + if (szExpr[m_iPos] >= 14 && szExpr[m_iPos] <= 31) + Error(ecINVALID_CHARACTERS_FOUND, m_iPos); + + ++m_iPos; + } + + // Check for end of formula + if (IsEOF(tok)) + return SaveBeforeReturn(tok); + + // Check for user defined binary operator + if (IsOprt(tok)) + return SaveBeforeReturn(tok); + + // Check for function token + if (IsFunTok(tok)) + return SaveBeforeReturn(tok); + + // Check built in operators / tokens + if (IsBuiltIn(tok)) + return SaveBeforeReturn(tok); + + // Check for function argument separators + if (IsArgSep(tok)) + return SaveBeforeReturn(tok); + + // Check for values / constant tokens + if (IsValTok(tok)) + return SaveBeforeReturn(tok); + + // Check for variable tokens + if (IsVarTok(tok)) + return SaveBeforeReturn(tok); + + // Check for string variables + if (IsStrVarTok(tok)) + return SaveBeforeReturn(tok); + + // Check for String tokens + if (IsString(tok)) + return SaveBeforeReturn(tok); + + // Check for unary operators + if (IsInfixOpTok(tok)) + return SaveBeforeReturn(tok); + + // Check for unary operators + if (IsPostOpTok(tok)) + return SaveBeforeReturn(tok); + + // Check String for undefined variable token. Done only if a + // flag is set indicating to ignore undefined variables. + // This is a way to conditionally avoid an error if + // undefined variables occur. + // (The GetUsedVar function must suppress the error for + // undefined variables in order to collect all variable + // names including the undefined ones.) + if ((m_bIgnoreUndefVar || m_pFactory) && IsUndefVarTok(tok)) + return SaveBeforeReturn(tok); + + // Check for unknown token + // + // !!! From this point on there is no exit without an exception possible... + // + string_type strTok; + auto iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, (std::size_t)m_iPos); + if (iEnd != m_iPos) + Error(ecUNASSIGNABLE_TOKEN, m_iPos, strTok); + + Error(ecUNASSIGNABLE_TOKEN, m_iPos, m_strFormula.substr(m_iPos)); + return token_type(); // never reached + } + + + void ParserTokenReader::SetParent(ParserBase* a_pParent) + { + m_pParser = a_pParent; + m_pFunDef = &a_pParent->m_FunDef; + m_pOprtDef = &a_pParent->m_OprtDef; + m_pInfixOprtDef = &a_pParent->m_InfixOprtDef; + m_pPostOprtDef = &a_pParent->m_PostOprtDef; + m_pVarDef = &a_pParent->m_VarDef; + m_pStrVarDef = &a_pParent->m_StrVarDef; + m_pConstDef = &a_pParent->m_ConstDef; + } + + + /** \brief Extract all characters that belong to a certain charset. + + \param a_szCharSet [in] Const char array of the characters allowed in the token. + \param a_strTok [out] The string that consists entirely of characters listed in a_szCharSet. + \param a_iPos [in] Position in the string from where to start reading. + \return The Position of the first character not listed in a_szCharSet. + \throw nothrow + */ + int ParserTokenReader::ExtractToken(const char_type* a_szCharSet, string_type& a_sTok, std::size_t a_iPos) const + { + auto iEnd = m_strFormula.find_first_not_of(a_szCharSet, a_iPos); + + if (iEnd == string_type::npos) + iEnd = m_strFormula.length(); + + // Assign token string if there was something found + if (a_iPos != iEnd) + a_sTok = string_type(m_strFormula.begin() + a_iPos, m_strFormula.begin() + iEnd); + + return static_cast(iEnd); + } + + + /** \brief Check Expression for the presence of a binary operator token. + + Userdefined binary operator "++" gives inconsistent parsing result for + the equations "a++b" and "a ++ b" if alphabetic characters are allowed + in operator tokens. To avoid this this function checks specifically + for operator tokens. + */ + int ParserTokenReader::ExtractOperatorToken(string_type& a_sTok, std::size_t a_iPos) const + { + // Changed as per Issue 6: https://code.google.com/p/muparser/issues/detail?id=6 + auto iEnd = m_strFormula.find_first_not_of(m_pParser->ValidOprtChars(), a_iPos); + if (iEnd == string_type::npos) + iEnd = m_strFormula.length(); + + // Assign token string if there was something found + if (a_iPos != iEnd) + { + a_sTok = string_type(m_strFormula.begin() + a_iPos, m_strFormula.begin() + iEnd); + return static_cast(iEnd); + } + else + { + // There is still the chance of having to deal with an operator consisting exclusively + // of alphabetic characters. + return ExtractToken(_T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), a_sTok, (std::size_t)a_iPos); + } + } + + + /** \brief Check if a built in operator or other token can be found + \param a_Tok [out] Operator token if one is found. This can either be a binary operator or an infix operator token. + \return true if an operator token has been found. + */ + bool ParserTokenReader::IsBuiltIn(token_type& a_Tok) + { + const char_type** const pOprtDef = m_pParser->GetOprtDef(), + * const szFormula = m_strFormula.c_str(); + + // Compare token with function and operator strings + // check string for operator/function + for (int i = 0; pOprtDef[i]; i++) + { + std::size_t len(std::char_traits::length(pOprtDef[i])); + if (string_type(pOprtDef[i]) == string_type(szFormula + m_iPos, szFormula + m_iPos + len)) + { + switch (i) + { + case cmLAND: + case cmLOR: + case cmLT: + case cmGT: + case cmLE: + case cmGE: + case cmNEQ: + case cmEQ: + case cmADD: + case cmSUB: + case cmMUL: + case cmDIV: + case cmPOW: + case cmASSIGN: + // The assignment operator need special treatment + if (i == cmASSIGN && m_iSynFlags & noASSIGN) + Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]); + + if (!m_pParser->HasBuiltInOprt()) continue; + if (m_iSynFlags & noOPT) + { + // Maybe its an infix operator not an operator + // Both operator types can share characters in + // their identifiers + if (IsInfixOpTok(a_Tok)) + return true; + + Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]); + } + + m_iSynFlags = noBC | noOPT | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE | noEND; + break; + + case cmBO: + if (m_iSynFlags & noBO) + Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); + + if (m_lastTok.GetCode() == cmFUNC) + m_iSynFlags = noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE; + else + m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE; + + m_bracketStack.push(cmBO); + break; + + case cmBC: + if (m_iSynFlags & noBC) + Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); + + m_iSynFlags = noBO | noVAR | noVAL | noFUN | noINFIXOP | noSTR | noASSIGN; + + if (!m_bracketStack.empty()) + m_bracketStack.pop(); + else + Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); + break; + + case cmELSE: + if (m_iSynFlags & noELSE) + Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]); + + m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE | noSTR; + break; + + case cmIF: + if (m_iSynFlags & noIF) + Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]); + + m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE | noSTR; + break; + + default: // The operator is listed in c_DefaultOprt, but not here. This is a bad thing... + Error(ecINTERNAL_ERROR); + } // switch operator id + + m_iPos += (int)len; + a_Tok.Set((ECmdCode)i, pOprtDef[i]); + return true; + } // if operator string found + } // end of for all operator strings + + return false; + } + + + bool ParserTokenReader::IsArgSep(token_type& a_Tok) + { + const char_type* szFormula = m_strFormula.c_str(); + + if (szFormula[m_iPos] == m_cArgSep) + { + // copy the separator into null terminated string + char_type szSep[2]; + szSep[0] = m_cArgSep; + szSep[1] = 0; + + if (m_iSynFlags & noARG_SEP) + Error(ecUNEXPECTED_ARG_SEP, m_iPos, szSep); + + m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN; + m_iPos++; + a_Tok.Set(cmARG_SEP, szSep); + return true; + } + + return false; + } + + + /** \brief Check for End of Formula. + + \return true if an end of formula is found false otherwise. + \param a_Tok [out] If an eof is found the corresponding token will be stored there. + \throw nothrow + \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsString, IsInfixOpTok, IsPostOpTok + */ + bool ParserTokenReader::IsEOF(token_type& a_Tok) + { + const char_type* szFormula = m_strFormula.c_str(); + + // check for EOF + if (!szFormula[m_iPos] /*|| szFormula[m_iPos] == '\n'*/) + { + if (m_iSynFlags & noEND) + Error(ecUNEXPECTED_EOF, m_iPos); + + if (!m_bracketStack.empty()) + Error(ecMISSING_PARENS, m_iPos, _T(")")); + + m_iSynFlags = 0; + a_Tok.Set(cmEND); + return true; + } + + return false; + } + + + /** \brief Check if a string position contains a unary infix operator. + \return true if a function token has been found false otherwise. + */ + bool ParserTokenReader::IsInfixOpTok(token_type& a_Tok) + { + string_type sTok; + auto iEnd = ExtractToken(m_pParser->ValidInfixOprtChars(), sTok, (std::size_t)m_iPos); + if (iEnd == m_iPos) + return false; + + // iterate over all postfix operator strings + funmap_type::const_reverse_iterator it = m_pInfixOprtDef->rbegin(); + for (; it != m_pInfixOprtDef->rend(); ++it) + { + if (sTok.find(it->first) != 0) + continue; + + a_Tok.Set(it->second, it->first); + m_iPos += (int)it->first.length(); + + if (m_iSynFlags & noINFIXOP) + Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); + + m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN | noARG_SEP; + return true; + } + + return false; + + /* + a_Tok.Set(item->second, sTok); + m_iPos = (int)iEnd; + + if (m_iSynFlags & noINFIXOP) + Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); + + m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN; + return true; + */ + } + + + /** \brief Check whether the token at a given position is a function token. + \param a_Tok [out] If a value token is found it will be placed here. + \throw ParserException if Syntaxflags do not allow a function at a_iPos + \return true if a function token has been found false otherwise. + \pre [assert] m_pParser!=0 + */ + bool ParserTokenReader::IsFunTok(token_type& a_Tok) + { + string_type strTok; + auto iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, (std::size_t)m_iPos); + if (iEnd == m_iPos) + return false; + + funmap_type::const_iterator item = m_pFunDef->find(strTok); + if (item == m_pFunDef->end()) + return false; + + // Check if the next sign is an opening bracket + const char_type* szFormula = m_strFormula.c_str(); + if (szFormula[iEnd] != '(') + return false; + + a_Tok.Set(item->second, strTok); + + m_iPos = (int)iEnd; + if (m_iSynFlags & noFUN) + Error(ecUNEXPECTED_FUN, m_iPos - (int)a_Tok.GetAsString().length(), a_Tok.GetAsString()); + + m_iSynFlags = noANY ^ noBO; + return true; + } + + + /** \brief Check if a string position contains a binary operator. + \param a_Tok [out] Operator token if one is found. This can either be a binary operator or an infix operator token. + \return true if an operator token has been found. + */ + bool ParserTokenReader::IsOprt(token_type& a_Tok) + { + const char_type* const szExpr = m_strFormula.c_str(); + string_type strTok; + + auto iEnd = ExtractOperatorToken(strTok, (std::size_t)m_iPos); + if (iEnd == m_iPos) + return false; + + // Check if the operator is a built in operator, if so ignore it here + const char_type** const pOprtDef = m_pParser->GetOprtDef(); + for (int i = 0; m_pParser->HasBuiltInOprt() && pOprtDef[i]; ++i) + { + if (string_type(pOprtDef[i]) == strTok) + return false; + } + + // Note: + // All tokens in oprt_bin_maptype are have been sorted by their length + // Long operators must come first! Otherwise short names (like: "add") that + // are part of long token names (like: "add123") will be found instead + // of the long ones. + // Length sorting is done with ascending length so we use a reverse iterator here. + funmap_type::const_reverse_iterator it = m_pOprtDef->rbegin(); + for (; it != m_pOprtDef->rend(); ++it) + { + const string_type& sID = it->first; + if (sID == string_type(szExpr + m_iPos, szExpr + m_iPos + sID.length())) + { + a_Tok.Set(it->second, strTok); + + // operator was found + if (m_iSynFlags & noOPT) + { + // An operator was found but is not expected to occur at + // this position of the formula, maybe it is an infix + // operator, not a binary operator. Both operator types + // can share characters in their identifiers. + if (IsInfixOpTok(a_Tok)) + return true; + else + { + // nope, no infix operator + return false; + //Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); + } + + } + + m_iPos += (int)sID.length(); + m_iSynFlags = noBC | noOPT | noARG_SEP | noPOSTOP | noEND | noASSIGN; + return true; + } + } + + return false; + } + + + /** \brief Check if a string position contains a unary post value operator. */ + bool ParserTokenReader::IsPostOpTok(token_type& a_Tok) + { + // Do not check for postfix operators if they are not allowed at + // the current expression index. + // + // This will fix the bug reported here: + // + // http://sourceforge.net/tracker/index.php?func=detail&aid=3343891&group_id=137191&atid=737979 + // + if (m_iSynFlags & noPOSTOP) + return false; + // + + // Tricky problem with equations like "3m+5": + // m is a postfix operator, + is a valid sign for postfix operators and + // for binary operators parser detects "m+" as operator string and + // finds no matching postfix operator. + // + // This is a special case so this routine slightly differs from the other + // token readers. + + // Test if there could be a postfix operator + string_type sTok; + auto iEnd = ExtractToken(m_pParser->ValidOprtChars(), sTok, (std::size_t)m_iPos); + if (iEnd == m_iPos) + return false; + + // iterate over all postfix operator strings + funmap_type::const_reverse_iterator it = m_pPostOprtDef->rbegin(); + for (; it != m_pPostOprtDef->rend(); ++it) + { + if (sTok.find(it->first) != 0) + continue; + + a_Tok.Set(it->second, sTok); + m_iPos += (int)it->first.length(); + + m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noSTR | noASSIGN; + return true; + } + + return false; + } + + + /** \brief Check whether the token at a given position is a value token. + + Value tokens are either values or constants. + + \param a_Tok [out] If a value token is found it will be placed here. + \return true if a value token has been found. + */ + bool ParserTokenReader::IsValTok(token_type& a_Tok) + { + MUP_ASSERT(m_pConstDef != nullptr); + MUP_ASSERT(m_pParser != nullptr); + + string_type strTok; + value_type fVal(0); + + // 2.) Check for user defined constant + // Read everything that could be a constant name + auto iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, (std::size_t)m_iPos); + if (iEnd != m_iPos) + { + valmap_type::const_iterator item = m_pConstDef->find(strTok); + if (item != m_pConstDef->end()) + { + m_iPos = iEnd; + a_Tok.SetVal(item->second, strTok); + + if (m_iSynFlags & noVAL) + Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok); + + m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; + return true; + } + } + + // 3.call the value recognition functions provided by the user + // Call user defined value recognition functions + std::list::const_iterator item = m_vIdentFun.begin(); + for (item = m_vIdentFun.begin(); item != m_vIdentFun.end(); ++item) + { + int iStart = m_iPos; + if ((*item)(m_strFormula.c_str() + m_iPos, &m_iPos, &fVal) == 1) + { + // 2013-11-27 Issue 2: https://code.google.com/p/muparser/issues/detail?id=2 + strTok.assign(m_strFormula.c_str(), iStart, (std::size_t)m_iPos - iStart); + + if (m_iSynFlags & noVAL) + Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok); + + a_Tok.SetVal(fVal, strTok); + m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; + return true; + } + } + + return false; + } + + + /** \brief Check wheter a token at a given position is a variable token. + \param a_Tok [out] If a variable token has been found it will be placed here. + \return true if a variable token has been found. + */ + bool ParserTokenReader::IsVarTok(token_type& a_Tok) + { + if (m_pVarDef->empty()) + return false; + + string_type strTok; + auto iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, (std::size_t)m_iPos); + if (iEnd == m_iPos) + return false; + + varmap_type::const_iterator item = m_pVarDef->find(strTok); + if (item == m_pVarDef->end()) + return false; + + if (m_iSynFlags & noVAR) + Error(ecUNEXPECTED_VAR, m_iPos, strTok); + + m_pParser->OnDetectVar(&m_strFormula, m_iPos, iEnd); + + m_iPos = iEnd; + a_Tok.SetVar(item->second, strTok); + m_UsedVar[item->first] = item->second; // Add variable to used-var-list + + m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR; + + // Zur Info hier die SynFlags von IsVal(): + // m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; + return true; + } + + + bool ParserTokenReader::IsStrVarTok(token_type& a_Tok) + { + if (!m_pStrVarDef || m_pStrVarDef->empty()) + return false; + + string_type strTok; + auto iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, (std::size_t)m_iPos); + if (iEnd == m_iPos) + return false; + + strmap_type::const_iterator item = m_pStrVarDef->find(strTok); + if (item == m_pStrVarDef->end()) + return false; + + if (m_iSynFlags & noSTR) + Error(ecUNEXPECTED_VAR, m_iPos, strTok); + + m_iPos = iEnd; + if (!m_pParser->m_vStringVarBuf.size()) + Error(ecINTERNAL_ERROR); + + a_Tok.SetString(m_pParser->m_vStringVarBuf[item->second], m_pParser->m_vStringVarBuf.size()); + + m_iSynFlags = noANY ^ (noBC | noOPT | noEND | noARG_SEP); + return true; + } + + + + /** \brief Check wheter a token at a given position is an undefined variable. + + \param a_Tok [out] If a variable tom_pParser->m_vStringBufken has been found it will be placed here. + \return true if a variable token has been found. + \throw nothrow + */ + bool ParserTokenReader::IsUndefVarTok(token_type& a_Tok) + { + string_type strTok; + auto iEnd(ExtractToken(m_pParser->ValidNameChars(), strTok, (std::size_t)m_iPos)); + if (iEnd == m_iPos) + return false; + + if (m_iSynFlags & noVAR) + { + // 20061021 added token string strTok instead of a_Tok.GetAsString() as the + // token identifier. + // related bug report: + // http://sourceforge.net/tracker/index.php?func=detail&aid=1578779&group_id=137191&atid=737979 + Error(ecUNEXPECTED_VAR, m_iPos - (int)a_Tok.GetAsString().length(), strTok); + } + + // If a factory is available implicitely create new variables + if (m_pFactory) + { + value_type* fVar = m_pFactory(strTok.c_str(), m_pFactoryData); + a_Tok.SetVar(fVar, strTok); + + // Do not use m_pParser->DefineVar( strTok, fVar ); + // in order to define the new variable, it will clear the + // m_UsedVar array which will kill previously defined variables + // from the list + // This is safe because the new variable can never override an existing one + // because they are checked first! + (*m_pVarDef)[strTok] = fVar; + m_UsedVar[strTok] = fVar; // Add variable to used-var-list + } + else + { + a_Tok.SetVar((value_type*)&m_fZero, strTok); + m_UsedVar[strTok] = 0; // Add variable to used-var-list + } + + m_iPos = iEnd; + + // Call the variable factory in order to let it define a new parser variable + m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noINFIXOP | noSTR; + return true; + } + + + + /** \brief Check wheter a token at a given position is a string. + \param a_Tok [out] If a variable token has been found it will be placed here. + \return true if a string token has been found. + \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsEOF, IsInfixOpTok, IsPostOpTok + \throw nothrow + */ + bool ParserTokenReader::IsString(token_type& a_Tok) + { + if (m_strFormula[m_iPos] != '"') + return false; + + string_type strBuf(&m_strFormula[(std::size_t)m_iPos + 1]); + std::size_t iEnd(0), iSkip(0); + + // parser over escaped '\"' end replace them with '"' + for (iEnd = (int)strBuf.find(_T('\"')); iEnd != 0 && iEnd != string_type::npos; iEnd = (int)strBuf.find(_T('\"'), iEnd)) + { + if (strBuf[iEnd - 1] != '\\') break; + strBuf.replace(iEnd - 1, 2, _T("\"")); + iSkip++; + } + + if (iEnd == string_type::npos) + Error(ecUNTERMINATED_STRING, m_iPos, _T("\"")); + + string_type strTok(strBuf.begin(), strBuf.begin() + iEnd); + + if (m_iSynFlags & noSTR) + Error(ecUNEXPECTED_STR, m_iPos, strTok); + + m_pParser->m_vStringBuf.push_back(strTok); // Store string in internal buffer + a_Tok.SetString(strTok, m_pParser->m_vStringBuf.size()); + + m_iPos += (int)strTok.length() + 2 + (int)iSkip; // +2 for quotes; +iSkip for escape characters + m_iSynFlags = noANY ^ (noARG_SEP | noBC | noOPT | noEND); + + return true; + } + + + /** \brief Create an error containing the parse error position. + + This function will create an Parser Exception object containing the error text and its position. + + \param a_iErrc [in] The error code of type #EErrorCodes. + \param a_iPos [in] The position where the error was detected. + \param a_strTok [in] The token string representation associated with the error. + \throw ParserException always throws thats the only purpose of this function. + */ + void ParserTokenReader::Error(EErrorCodes a_iErrc, int a_iPos, const string_type& a_sTok) const + { + m_pParser->Error(a_iErrc, a_iPos, a_sTok); + } + + + void ParserTokenReader::SetArgSep(char_type cArgSep) + { + m_cArgSep = cArgSep; + } + + + char_type ParserTokenReader::GetArgSep() const + { + return m_cArgSep; + } +} // namespace mu + +#if defined(_MSC_VER) + #pragma warning(pop) +#endif diff --git a/3rdparty/muparser/muParserTokenReader.h b/3rdparty/muparser/muParserTokenReader.h index 9d96225d..b3739fa0 100644 --- a/3rdparty/muparser/muParserTokenReader.h +++ b/3rdparty/muparser/muParserTokenReader.h @@ -1,161 +1,169 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2004-2013 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef MU_PARSER_TOKEN_READER_H -#define MU_PARSER_TOKEN_READER_H - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "muParserDef.h" -#include "muParserToken.h" - -/** \file - \brief This file contains the parser token reader definition. -*/ - - -namespace mu -{ - // Forward declaration - class ParserBase; - - /** \brief Token reader for the ParserBase class. - - */ - class ParserTokenReader - { - private: - - typedef ParserToken token_type; - - public: - - ParserTokenReader(ParserBase *a_pParent); - ParserTokenReader* Clone(ParserBase *a_pParent) const; - - void AddValIdent(identfun_type a_pCallback); - void SetVarCreator(facfun_type a_pFactory, void *pUserData); - void SetFormula(const string_type &a_strFormula); - void SetArgSep(char_type cArgSep); - - int GetPos() const; - const string_type& GetExpr() const; - varmap_type& GetUsedVar(); - char_type GetArgSep() const; - - void IgnoreUndefVar(bool bIgnore); - void ReInit(); - token_type ReadNextToken(); - - private: - - /** \brief Syntax codes. - - The syntax codes control the syntax check done during the first time parsing of - the expression string. They are flags that indicate which tokens are allowed next - if certain tokens are identified. - */ - enum ESynCodes - { - noBO = 1 << 0, ///< to avoid i.e. "cos(7)(" - noBC = 1 << 1, ///< to avoid i.e. "sin)" or "()" - noVAL = 1 << 2, ///< to avoid i.e. "tan 2" or "sin(8)3.14" - noVAR = 1 << 3, ///< to avoid i.e. "sin a" or "sin(8)a" - noARG_SEP = 1 << 4, ///< to avoid i.e. ",," or "+," ... - noFUN = 1 << 5, ///< to avoid i.e. "sqrt cos" or "(1)sin" - noOPT = 1 << 6, ///< to avoid i.e. "(+)" - noPOSTOP = 1 << 7, ///< to avoid i.e. "(5!!)" "sin!" - noINFIXOP = 1 << 8, ///< to avoid i.e. "++4" "!!4" - noEND = 1 << 9, ///< to avoid unexpected end of formula - noSTR = 1 << 10, ///< to block numeric arguments on string functions - noASSIGN = 1 << 11, ///< to block assignement to constant i.e. "4=7" - noIF = 1 << 12, - noELSE = 1 << 13, - sfSTART_OF_LINE = noOPT | noBC | noPOSTOP | noASSIGN | noIF | noELSE | noARG_SEP, - noANY = ~0 ///< All of he above flags set - }; - - ParserTokenReader(const ParserTokenReader &a_Reader); - ParserTokenReader& operator=(const ParserTokenReader &a_Reader); - void Assign(const ParserTokenReader &a_Reader); - - void SetParent(ParserBase *a_pParent); - int ExtractToken(const char_type *a_szCharSet, - string_type &a_strTok, - int a_iPos) const; - int ExtractOperatorToken(string_type &a_sTok, int a_iPos) const; - - bool IsBuiltIn(token_type &a_Tok); - bool IsArgSep(token_type &a_Tok); - bool IsEOF(token_type &a_Tok); - bool IsInfixOpTok(token_type &a_Tok); - bool IsFunTok(token_type &a_Tok); - bool IsPostOpTok(token_type &a_Tok); - bool IsOprt(token_type &a_Tok); - bool IsValTok(token_type &a_Tok); - bool IsVarTok(token_type &a_Tok); - bool IsStrVarTok(token_type &a_Tok); - bool IsUndefVarTok(token_type &a_Tok); - bool IsString(token_type &a_Tok); - void Error(EErrorCodes a_iErrc, - int a_iPos = -1, - const string_type &a_sTok = string_type() ) const; - - token_type& SaveBeforeReturn(const token_type &tok); - - ParserBase *m_pParser; - string_type m_strFormula; - int m_iPos; - int m_iSynFlags; - bool m_bIgnoreUndefVar; - - const funmap_type *m_pFunDef; - const funmap_type *m_pPostOprtDef; - const funmap_type *m_pInfixOprtDef; - const funmap_type *m_pOprtDef; - const valmap_type *m_pConstDef; - const strmap_type *m_pStrVarDef; - varmap_type *m_pVarDef; ///< The only non const pointer to parser internals - facfun_type m_pFactory; - void *m_pFactoryData; - std::list m_vIdentFun; ///< Value token identification function - varmap_type m_UsedVar; - value_type m_fZero; ///< Dummy value of zero, referenced by undefined variables - int m_iBrackets; - token_type m_lastTok; - char_type m_cArgSep; ///< The character used for separating function arguments - }; -} // namespace mu - -#endif - - +/* + + _____ __ _____________ _______ ______ ___________ + / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ + | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ + |__|_| /____/| __(____ /__| /____ >\___ >__| + \/ |__| \/ \/ \/ + Copyright (C) 2004 - 2022 Ingo Berg + + Redistribution and use in source and binary forms, with or without modification, are permitted + provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef MU_PARSER_TOKEN_READER_H +#define MU_PARSER_TOKEN_READER_H + +#include +#include +#include +#include +#include +#include +#include + +#include "muParserDef.h" +#include "muParserToken.h" + +/** \file + \brief This file contains the parser token reader definition. +*/ + + +namespace mu +{ + // Forward declaration + class ParserBase; + + /** \brief Token reader for the ParserBase class. */ + class API_EXPORT_CXX ParserTokenReader final + { + private: + + typedef ParserToken token_type; + + public: + + ParserTokenReader(ParserBase* a_pParent); + ParserTokenReader* Clone(ParserBase* a_pParent) const; + + void AddValIdent(identfun_type a_pCallback); + void SetVarCreator(facfun_type a_pFactory, void* pUserData); + void SetFormula(const string_type& a_strFormula); + void SetArgSep(char_type cArgSep); + + /** \brief Check whether a variable factory is installed. + + Variable factories automatically create new variables when a unknown variable is found in an expression. + */ + bool HasVarCreator() const + { + return m_pFactory != nullptr; + } + + int GetPos() const; + const string_type& GetExpr() const; + varmap_type& GetUsedVar(); + char_type GetArgSep() const; + + void IgnoreUndefVar(bool bIgnore); + void ReInit(); + token_type ReadNextToken(); + + private: + + /** \brief Syntax codes. + + The syntax codes control the syntax check done during the first time parsing of + the expression string. They are flags that indicate which tokens are allowed next + if certain tokens are identified. + */ + enum ESynCodes + { + noBO = 1 << 0, ///< to avoid i.e. "cos(7)(" + noBC = 1 << 1, ///< to avoid i.e. "sin)" or "()" + noVAL = 1 << 2, ///< to avoid i.e. "tan 2" or "sin(8)3.14" + noVAR = 1 << 3, ///< to avoid i.e. "sin a" or "sin(8)a" + noARG_SEP = 1 << 4, ///< to avoid i.e. ",," or "+," ... + noFUN = 1 << 5, ///< to avoid i.e. "sqrt cos" or "(1)sin" + noOPT = 1 << 6, ///< to avoid i.e. "(+)" + noPOSTOP = 1 << 7, ///< to avoid i.e. "(5!!)" "sin!" + noINFIXOP = 1 << 8, ///< to avoid i.e. "++4" "!!4" + noEND = 1 << 9, ///< to avoid unexpected end of formula + noSTR = 1 << 10, ///< to block numeric arguments on string functions + noASSIGN = 1 << 11, ///< to block assignment to constant i.e. "4=7" + noIF = 1 << 12, + noELSE = 1 << 13, + sfSTART_OF_LINE = noOPT | noBC | noPOSTOP | noASSIGN | noIF | noELSE | noARG_SEP, + noANY = ~0 ///< All of he above flags set + }; + + ParserTokenReader(const ParserTokenReader& a_Reader); + ParserTokenReader& operator=(const ParserTokenReader& a_Reader); + void Assign(const ParserTokenReader& a_Reader); + + void SetParent(ParserBase* a_pParent); + int ExtractToken(const char_type* a_szCharSet, string_type& a_strTok, std::size_t a_iPos) const; + int ExtractOperatorToken(string_type& a_sTok, std::size_t a_iPos) const; + + bool IsBuiltIn(token_type& a_Tok); + bool IsArgSep(token_type& a_Tok); + bool IsEOF(token_type& a_Tok); + bool IsInfixOpTok(token_type& a_Tok); + bool IsFunTok(token_type& a_Tok); + bool IsPostOpTok(token_type& a_Tok); + bool IsOprt(token_type& a_Tok); + bool IsValTok(token_type& a_Tok); + bool IsVarTok(token_type& a_Tok); + bool IsStrVarTok(token_type& a_Tok); + bool IsUndefVarTok(token_type& a_Tok); + bool IsString(token_type& a_Tok); + void Error(EErrorCodes a_iErrc, int a_iPos = -1, const string_type& a_sTok = string_type()) const; + + token_type& SaveBeforeReturn(const token_type& tok); + + ParserBase* m_pParser; + string_type m_strFormula; + int m_iPos; + int m_iSynFlags; + bool m_bIgnoreUndefVar; + + const funmap_type* m_pFunDef; + const funmap_type* m_pPostOprtDef; + const funmap_type* m_pInfixOprtDef; + const funmap_type* m_pOprtDef; + const valmap_type* m_pConstDef; + const strmap_type* m_pStrVarDef; + + varmap_type* m_pVarDef; ///< The only non const pointer to parser internals + facfun_type m_pFactory; + void* m_pFactoryData; + std::list m_vIdentFun; ///< Value token identification function + varmap_type m_UsedVar; + value_type m_fZero; ///< Dummy value of zero, referenced by undefined variables + + std::stack m_bracketStack; + + token_type m_lastTok; + char_type m_cArgSep; ///< The character used for separating function arguments + }; +} // namespace mu + +#endif + + diff --git a/3rdparty/qt-colorpicker/qtcolorpicker.cpp b/3rdparty/qt-colorpicker/qtcolorpicker.cpp index 1095728a..21c0ff6e 100644 --- a/3rdparty/qt-colorpicker/qtcolorpicker.cpp +++ b/3rdparty/qt-colorpicker/qtcolorpicker.cpp @@ -47,7 +47,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -191,7 +192,7 @@ QtColorPicker::~QtColorPicker() {} void QtColorPicker::buttonPressed(bool toggled) { if (!toggled) return; - const QRect desktop = QApplication::desktop()->geometry(); + const QRect desktop = QGuiApplication::primaryScreen()->geometry(); // Make sure the popup is inside the desktop. QPoint pos = mapToGlobal(rect().bottomLeft()); if (pos.x() < desktop.left()) pos.setX(desktop.left()); diff --git a/COPYING b/COPYING index 3912109b..e72bfdda 100644 --- a/COPYING +++ b/COPYING @@ -1,285 +1,626 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. - Preamble + Preamble - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of this License. - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it @@ -287,15 +628,15 @@ free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least +state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) - This program is free software; you can redistribute it and/or modify + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -304,37 +645,30 @@ the "copyright" line and a pointer to where the full notice is found. GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - + along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. \ No newline at end of file diff --git a/Changelog b/Changelog index 48693ed6..1647b7fb 100644 --- a/Changelog +++ b/Changelog @@ -1,7 +1,11 @@ === Progress === -* move to c++ 14 +* full porting to Qt6 +* update license from GPL-2.0 to GPL-3.0 for Qt6 compatibility +* fix last column auto-resize when "Set Column(s) As" is used +* add compatibility with Flatpak * use QRandomGenerator class for random number generation * beautify result logs with html styling +* change property browser to model view framework === 18-01-22 Fifth release of AlphaPlot (Stable) - major release === * project explorer drag n drop diff --git a/README.md b/README.md index 7cc89b84..bb979d92 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Download AlphaPlot](https://img.shields.io/sourceforge/dt/alphaplot.svg)](https://sourceforge.net/projects/alphaplot/files/latest/download) [![Download AlphaPlot](https://img.shields.io/sourceforge/dm/alphaplot.svg)](https://sourceforge.net/projects/alphaplot/files/latest/download) [![Download AlphaPlot](https://img.shields.io/sourceforge/dw/alphaplot.svg)](https://sourceforge.net/projects/alphaplot/files/latest/download) [![Download AlphaPlot](https://img.shields.io/sourceforge/dd/alphaplot.svg)](https://sourceforge.net/projects/alphaplot/files/latest/download) [license-page]: COPYING -[license-badge]: http://img.shields.io/badge/License-GPL2-blue.svg +[license-badge]: http://img.shields.io/badge/License-GPL3-blue.svg Alpha Plot is a free application for Scientific Data Analysis and Visualization for Windows, Linux and Mac OS X (probably BSD also). diff --git a/alphaplot.pro b/alphaplot.pro index 9c3eee43..cf341004 100644 --- a/alphaplot.pro +++ b/alphaplot.pro @@ -1,6 +1,6 @@ ####################################################### # AlphaPlot main project file # -# run "qmake AlphaPlot.pro" to generate the Makefile # +# run "qmake6 AlphaPlot.pro" to generate the Makefile # ####################################################### TEMPLATE = subdirs diff --git a/alphaplot.pro.user b/alphaplot.pro.user deleted file mode 100644 index 322e1386..00000000 --- a/alphaplot.pro.user +++ /dev/null @@ -1,265 +0,0 @@ - - - - - - EnvironmentId - {7778cb55-b0a6-43c8-8f71-9ac260bd235e} - - - ProjectExplorer.Project.ActiveTarget - 0 - - - ProjectExplorer.Project.EditorSettings - - true - false - true - - Cpp - - CppGlobal - - - - QmlJS - - QmlJSGlobal - - - 2 - UTF-8 - false - 4 - false - 80 - true - true - 1 - false - true - false - 0 - true - true - 0 - 8 - true - false - 1 - true - true - true - *.md, *.MD, Makefile - false - true - - - - ProjectExplorer.Project.PluginSettings - - - true - false - true - true - true - true - - - 0 - true - - true - Builtin.BuildSystem - - true - true - Builtin.DefaultTidyAndClazy - 6 - - - - true - - - true - - - - - ProjectExplorer.Project.Target.0 - - Desktop - Qt5.15_manual - Qt5.15_manual - {68bacddc-274c-4c6f-bf57-3ea07c065df3} - 0 - 0 - 0 - - 0 - /Users/arun/Documents/build-alphaplot-Qt5_15_manual-Debug - /Users/arun/Documents/build-alphaplot-Qt5_15_manual-Debug - - - true - QtProjectManager.QMakeBuildStep - false - - - - true - Qt4ProjectManager.MakeStep - - 2 - Build - Build - ProjectExplorer.BuildSteps.Build - - - - true - Qt4ProjectManager.MakeStep - clean - - 1 - Clean - Clean - ProjectExplorer.BuildSteps.Clean - - 2 - false - - - Debug - Qt4ProjectManager.Qt4BuildConfiguration - 2 - - - /Users/arun/Documents/build-alphaplot-Qt5_15_manual-Release - /Users/arun/Documents/build-alphaplot-Qt5_15_manual-Release - - - true - QtProjectManager.QMakeBuildStep - false - - - - true - Qt4ProjectManager.MakeStep - - 2 - Build - Build - ProjectExplorer.BuildSteps.Build - - - - true - Qt4ProjectManager.MakeStep - clean - - 1 - Clean - Clean - ProjectExplorer.BuildSteps.Clean - - 2 - false - - - Release - Qt4ProjectManager.Qt4BuildConfiguration - 0 - 0 - - - 0 - /Users/arun/Documents/build-alphaplot-Qt5_15_manual-Profile - /Users/arun/Documents/build-alphaplot-Qt5_15_manual-Profile - - - true - QtProjectManager.QMakeBuildStep - false - - - - true - Qt4ProjectManager.MakeStep - - 2 - Build - Build - ProjectExplorer.BuildSteps.Build - - - - true - Qt4ProjectManager.MakeStep - clean - - 1 - Clean - Clean - ProjectExplorer.BuildSteps.Clean - - 2 - false - - - Profile - Qt4ProjectManager.Qt4BuildConfiguration - 0 - 0 - 0 - - 3 - - - 0 - Deploy - Deploy - ProjectExplorer.BuildSteps.Deploy - - 1 - - false - ProjectExplorer.DefaultDeployConfiguration - - 1 - - true - true - true - - 2 - - Qt4ProjectManager.Qt4RunConfiguration:/Users/arun/Documents/AlphaPlot/alphaplot/alphaplot.pro - /Users/arun/Documents/AlphaPlot/alphaplot/alphaplot.pro - false - true - true - false - true - /Users/arun/Documents/build-alphaplot-Qt5_15_manual-Debug/alphaplot/./alphaplot.app/Contents/MacOS - - 1 - - - - ProjectExplorer.Project.TargetCount - 1 - - - ProjectExplorer.Project.Updater.FileVersion - 22 - - - Version - 22 - - diff --git a/alphaplot/.qmake.stash b/alphaplot/.qmake.stash new file mode 100644 index 00000000..5808fc89 --- /dev/null +++ b/alphaplot/.qmake.stash @@ -0,0 +1,22 @@ +QMAKE_CXX.QT_COMPILER_STDCXX = 201703L +QMAKE_CXX.QMAKE_GCC_MAJOR_VERSION = 15 +QMAKE_CXX.QMAKE_GCC_MINOR_VERSION = 2 +QMAKE_CXX.QMAKE_GCC_PATCH_VERSION = 1 +QMAKE_CXX.COMPILER_MACROS = \ + QT_COMPILER_STDCXX \ + QMAKE_GCC_MAJOR_VERSION \ + QMAKE_GCC_MINOR_VERSION \ + QMAKE_GCC_PATCH_VERSION +QMAKE_CXX.INCDIRS = \ + /usr/include/c++/15 \ + /usr/include/c++/15/x86_64-redhat-linux \ + /usr/include/c++/15/backward \ + /usr/lib/gcc/x86_64-redhat-linux/15/include \ + /usr/local/include \ + /usr/include +QMAKE_CXX.LIBDIRS = \ + /usr/lib/gcc/x86_64-redhat-linux/15 \ + /usr/lib64 \ + /lib64 \ + /usr/lib \ + /lib diff --git a/alphaplot/alphaplot.pro b/alphaplot/alphaplot.pro index 7ac86971..ffd15fa0 100644 --- a/alphaplot/alphaplot.pro +++ b/alphaplot/alphaplot.pro @@ -5,10 +5,17 @@ DEFINES += QCUSTOMPLOT_USE_OPENGL # Qt modules QT += core gui widgets opengl network svg -QT += script scripttools printsupport datavisualization +QT += printsupport datavisualization -# enable C++14 support -CONFIG += c++14 +# Qt 6 specific modules +greaterThan(QT_MAJOR_VERSION, 5) | greaterThan(QT_VERSION_MAJOR, 5) { + QT += core5compat qml +} else { + QT += script scripttools +} + +# enable C++17 runtime support +CONFIG += c++17 CONFIG += qt warn_on exceptions opengl thread @@ -121,7 +128,7 @@ documentation.files += ../data/manual \ ../data/alphaplot-logo.png \ ../data/README.md \ ../data/CHANGES \ - ../data/gpl.txt + ../data/gpl-3.0.txt INSTALLS += documentation diff --git a/alphaplot/muparser.pri b/alphaplot/muparser.pri index 48e4244c..bd386f9b 100644 --- a/alphaplot/muparser.pri +++ b/alphaplot/muparser.pri @@ -2,6 +2,8 @@ ####################### MuParser ############################# ############################################################## +DEFINES += MUPARSER_STATIC + HEADERS += ../3rdparty/muparser/muParser.h \ ../3rdparty/muparser/muParserBase.h \ ../3rdparty/muparser/muParserBytecode.h \ diff --git a/alphaplot/src/2Dplot/Layout2D.cpp b/alphaplot/src/2Dplot/Layout2D.cpp index e1736521..049d5389 100644 --- a/alphaplot/src/2Dplot/Layout2D.cpp +++ b/alphaplot/src/2Dplot/Layout2D.cpp @@ -56,7 +56,7 @@ Layout2D::Layout2D(const QString &label, QWidget *parent, const QString name, if (name.isEmpty()) setObjectName("layout2d"); QDateTime birthday = QDateTime::currentDateTime(); - setBirthDate(birthday.toString(Qt::LocalDate)); + setBirthDate(QLocale().toString(birthday, QLocale::ShortFormat)); layoutManagebuttonsBox_ = new QHBoxLayout(); refreshPlotButton_ = new ToolButton(); @@ -132,7 +132,7 @@ Layout2D::Layout2D(const QString &label, QWidget *parent, const QString name, layout->addLayout(hbox); layout->addWidget(plot2dCanvas_, 1); setWidget(main_widget_); - layout->setMargin(0); + layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); setGeometry(QRect(0, 0, defaultlayout2dwidth_, defaultlayout2dheight_)); setMinimumSize(QSize(minimumlayout2dwidth_, minimumlayout2dheight_)); @@ -1554,7 +1554,7 @@ void Layout2D::save(XmlStreamWriter *xmlwriter, const bool saveastemplate) { xmlwriter->writeAttribute("y", QString::number(pos().y())); xmlwriter->writeAttribute("width", QString::number(width())); xmlwriter->writeAttribute("height", QString::number(height())); - QDateTime datetime = QDateTime::fromString(birthDate(), Qt::LocalDate); + QDateTime datetime = QLocale().toDateTime(birthDate(), QLocale::ShortFormat); xmlwriter->writeAttribute("creation_time", datetime.toString("yyyy-dd-MM hh:mm:ss:zzz")); xmlwriter->writeAttribute("caption_spec", QString::number(captionPolicy())); @@ -1608,11 +1608,11 @@ bool Layout2D::load(XmlStreamReader *xmlreader, QList tabs, QDateTime creation_time = QDateTime::fromString(time, "yyyy-dd-MM hh:mm:ss:zzz"); if (!time.isEmpty() && creation_time.isValid() && ok) { - setBirthDate(creation_time.toString(Qt::LocalDate)); + setBirthDate(QLocale().toString(creation_time, QLocale::ShortFormat)); } else { xmlreader->raiseWarning( tr("Invalid creation time. Using current time insted.")); - setBirthDate(QDateTime::currentDateTime().toString(Qt::LocalDate)); + setBirthDate(QLocale().toString(QDateTime::currentDateTime(), QLocale::ShortFormat)); } // read caption spec int captionspec = xmlreader->readAttributeInt("caption_spec", &ok); @@ -1787,7 +1787,6 @@ void Layout2D::copy(Layout2D *layout, QList
tables, } std::unique_ptr xmlwriter = std::unique_ptr(new XmlStreamWriter(file.get())); - xmlwriter->setCodec("UTF-8"); xmlwriter->setAutoFormatting(false); layout->save(xmlwriter.get()); file->close(); diff --git a/alphaplot/src/2Dplot/widgets/ErrDialog.cpp b/alphaplot/src/2Dplot/widgets/ErrDialog.cpp index 367f121f..656216db 100644 --- a/alphaplot/src/2Dplot/widgets/ErrDialog.cpp +++ b/alphaplot/src/2Dplot/widgets/ErrDialog.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/2Dplot/widgets/ErrDialog.h b/alphaplot/src/2Dplot/widgets/ErrDialog.h index be856858..f5f86b3b 100644 --- a/alphaplot/src/2Dplot/widgets/ErrDialog.h +++ b/alphaplot/src/2Dplot/widgets/ErrDialog.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/3Dplot/Bar3D.cpp b/alphaplot/src/3Dplot/Bar3D.cpp index b39ce67f..8773a54b 100644 --- a/alphaplot/src/3Dplot/Bar3D.cpp +++ b/alphaplot/src/3Dplot/Bar3D.cpp @@ -9,6 +9,11 @@ #include "future/core/column/Column.h" #include "future/lib/XmlStreamReader.h" #include "future/lib/XmlStreamWriter.h" + +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +using namespace QtDataVisualization; +#endif + Bar3D::Bar3D(Q3DBars *bar) : graph_(bar), data_(QVector()), counter_(0) { diff --git a/alphaplot/src/3Dplot/Bar3D.h b/alphaplot/src/3Dplot/Bar3D.h index 45da8040..fa99ac4a 100644 --- a/alphaplot/src/3Dplot/Bar3D.h +++ b/alphaplot/src/3Dplot/Bar3D.h @@ -13,7 +13,7 @@ class DataBlockBar3D; class XmlStreamWriter; class XmlStreamReader; -using namespace QtDataVisualization; + class Bar3D : public QObject { Q_OBJECT diff --git a/alphaplot/src/3Dplot/Custom3DInteractions.cpp b/alphaplot/src/3Dplot/Custom3DInteractions.cpp index 39c280af..5fcc0b00 100644 --- a/alphaplot/src/3Dplot/Custom3DInteractions.cpp +++ b/alphaplot/src/3Dplot/Custom3DInteractions.cpp @@ -1,6 +1,10 @@ #include "Custom3DInteractions.h" #include +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +using namespace QtDataVisualization; +#endif + const int Custom3DInteractions::deltazoom_ = 1; diff --git a/alphaplot/src/3Dplot/Custom3DInteractions.h b/alphaplot/src/3Dplot/Custom3DInteractions.h index 7b6e67ec..0f887fa6 100644 --- a/alphaplot/src/3Dplot/Custom3DInteractions.h +++ b/alphaplot/src/3Dplot/Custom3DInteractions.h @@ -3,7 +3,7 @@ #include -using namespace QtDataVisualization; + class Custom3DInteractions : public QAbstract3DInputHandler { Q_OBJECT diff --git a/alphaplot/src/3Dplot/DataManager3D.cpp b/alphaplot/src/3Dplot/DataManager3D.cpp index 689ed0ad..684420f2 100644 --- a/alphaplot/src/3Dplot/DataManager3D.cpp +++ b/alphaplot/src/3Dplot/DataManager3D.cpp @@ -16,7 +16,9 @@ #include "core/Utilities.h" #include "future/core/column/Column.h" +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) using namespace QtDataVisualization; +#endif void DataBlockAbstract3D::setgradient(QAbstract3DSeries *series, const Graph3DCommon::Gradient &gradient) { diff --git a/alphaplot/src/3Dplot/DataManager3D.h b/alphaplot/src/3Dplot/DataManager3D.h index 41eeba28..4c4fba50 100644 --- a/alphaplot/src/3Dplot/DataManager3D.h +++ b/alphaplot/src/3Dplot/DataManager3D.h @@ -1,6 +1,16 @@ #ifndef DATAMANAGER3D_H #define DATAMANAGER3D_H +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include #include #include #include @@ -13,18 +23,17 @@ class Matrix; class Table; class Column; -namespace QtDataVisualization { -class QSurfaceDataProxy; -class QSurface3DSeries; -class QItemModelSurfaceDataProxy; -class QBarDataProxy; -class QBar3DSeries; -class QItemModelBarDataProxy; -class QScatterDataProxy; -class QScatter3DSeries; -class QItemModelScatterDataProxy; -class QAbstract3DSeries; -} // namespace QtDataVisualization +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// Manual forward declarations of QtDataVisualization classes are removed to avoid ambiguity with headers. class DataBlockAbstract3D : public QObject { public: @@ -42,7 +51,7 @@ class DataBlockAbstract3D : public QObject { void setxcolumn(Column *column) { xcolumn_ = column; } void setycolumn(Column *column) { ycolumn_ = column; } void setzcolumns(Column *column) { zcolumn_ = column; } - void setgradient(QtDataVisualization::QAbstract3DSeries *series, + void setgradient(QAbstract3DSeries *series, const Graph3DCommon::Gradient &gradient); protected: @@ -80,14 +89,14 @@ class DataBlockSurface3D : public DataBlockAbstract3D { QList, double>> *data); // getters - QtDataVisualization::QSurfaceDataArray *getvaluedataarray() { + QSurfaceDataArray *getvaluedataarray() { return valueDataArray_; } - QtDataVisualization::QSurfaceDataProxy *getvaluedataproxy() { + QSurfaceDataProxy *getvaluedataproxy() { return valueDataProxy_; } - QtDataVisualization::QSurface3DSeries *getdataseries() { return dataSeries_; } - QtDataVisualization::QItemModelSurfaceDataProxy *getmodeldataproxy() { + QSurface3DSeries *getdataseries() { return dataSeries_; } + QItemModelSurfaceDataProxy *getmodeldataproxy() { return modelDataProxy_; } bool ismatrix(); @@ -104,10 +113,10 @@ class DataBlockSurface3D : public DataBlockAbstract3D { private: Graph3DCommon::Function3DData funcData_; - QtDataVisualization::QSurfaceDataArray *valueDataArray_; - QtDataVisualization::QSurfaceDataProxy *valueDataProxy_; - QtDataVisualization::QSurface3DSeries *dataSeries_; - QtDataVisualization::QItemModelSurfaceDataProxy *modelDataProxy_; + QSurfaceDataArray *valueDataArray_; + QSurfaceDataProxy *valueDataProxy_; + QSurface3DSeries *dataSeries_; + QItemModelSurfaceDataProxy *modelDataProxy_; }; class DataBlockBar3D : public DataBlockAbstract3D { @@ -126,23 +135,23 @@ class DataBlockBar3D : public DataBlockAbstract3D { void regenerateDataBlockXYZValue(); // getters - QtDataVisualization::QBarDataArray *getvaluedataarray() { + QBarDataArray *getvaluedataarray() { return valueDataArray_; } - QtDataVisualization::QBarDataProxy *getvaluedataproxy() { + QBarDataProxy *getvaluedataproxy() { return valueDataProxy_; } - QtDataVisualization::QBar3DSeries *getdataseries() { return dataSeries_; } - QtDataVisualization::QItemModelBarDataProxy *getmodeldataproxy() { + QBar3DSeries *getdataseries() { return dataSeries_; } + QItemModelBarDataProxy *getmodeldataproxy() { return modelDataProxy_; } bool ismatrix(); private: - QtDataVisualization::QBarDataArray *valueDataArray_; - QtDataVisualization::QBarDataProxy *valueDataProxy_; - QtDataVisualization::QBar3DSeries *dataSeries_; - QtDataVisualization::QItemModelBarDataProxy *modelDataProxy_; + QBarDataArray *valueDataArray_; + QBarDataProxy *valueDataProxy_; + QBar3DSeries *dataSeries_; + QItemModelBarDataProxy *modelDataProxy_; }; class DataBlockScatter3D : public DataBlockAbstract3D { @@ -161,19 +170,19 @@ class DataBlockScatter3D : public DataBlockAbstract3D { void regenerateDataBlockXYZValue(); // getters - QtDataVisualization::QScatterDataArray *getvaluedataarray() { + QScatterDataArray *getvaluedataarray() { return valueDataArray_; } - QtDataVisualization::QScatterDataProxy *getvaluedataproxy() { + QScatterDataProxy *getvaluedataproxy() { return valueDataProxy_; } - QtDataVisualization::QScatter3DSeries *getdataseries() { return dataSeries_; } + QScatter3DSeries *getdataseries() { return dataSeries_; } bool ismatrix(); private: - QtDataVisualization::QScatterDataArray *valueDataArray_; - QtDataVisualization::QScatterDataProxy *valueDataProxy_; - QtDataVisualization::QScatter3DSeries *dataSeries_; + QScatterDataArray *valueDataArray_; + QScatterDataProxy *valueDataProxy_; + QScatter3DSeries *dataSeries_; }; Q_DECLARE_METATYPE(DataBlockBar3D *); diff --git a/alphaplot/src/3Dplot/Layout3D.cpp b/alphaplot/src/3Dplot/Layout3D.cpp index 55202c2a..acbdb16f 100644 --- a/alphaplot/src/3Dplot/Layout3D.cpp +++ b/alphaplot/src/3Dplot/Layout3D.cpp @@ -26,6 +26,11 @@ #include "future/core/column/Column.h" #include "future/lib/XmlStreamReader.h" #include "future/lib/XmlStreamWriter.h" + +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +using namespace QtDataVisualization; +#endif + #include "plotcommon/widgets/ImageExportDialog.h" const int Layout3D::defaultlayout2dwidth_ = 500; @@ -76,7 +81,7 @@ Layout3D::Layout3D(const Graph3DCommon::Plot3DType &plottype, QWidget *widget = new QWidget(this); widget->setContentsMargins(0, 0, 0, 0); QHBoxLayout *hLayout = new QHBoxLayout(widget); - hLayout->setMargin(0); + hLayout->setContentsMargins(0, 0, 0, 0); hLayout->addWidget(main_widget_, 1); hLayout->setAlignment(Qt::AlignTop); widget->setLayout(hLayout); @@ -88,7 +93,7 @@ Layout3D::Layout3D(const Graph3DCommon::Plot3DType &plottype, if (name.isEmpty()) setObjectName("layout3d"); QDateTime birthday = QDateTime::currentDateTime(); - setBirthDate(birthday.toString(Qt::LocalDate)); + setBirthDate(QLocale().toString(birthday, QLocale::ShortFormat)); setFocusPolicy(Qt::TabFocus); setGeometry(QRect(0, 0, defaultlayout2dwidth_, defaultlayout2dheight_)); @@ -348,11 +353,11 @@ void Layout3D::load(XmlStreamReader *xmlreader, QList
tabs, QDateTime creation_time = QDateTime::fromString(time, "yyyy-dd-MM hh:mm:ss:zzz"); if (!time.isEmpty() && creation_time.isValid() && ok) { - setBirthDate(creation_time.toString(Qt::LocalDate)); + setBirthDate(QLocale().toString(creation_time, QLocale::ShortFormat)); } else { xmlreader->raiseWarning( tr("Invalid creation time. Using current time insted.")); - setBirthDate(QDateTime::currentDateTime().toString(Qt::LocalDate)); + setBirthDate(QLocale().toString(QDateTime::currentDateTime(), QLocale::ShortFormat)); } // read caption spec @@ -796,7 +801,7 @@ void Layout3D::save(XmlStreamWriter *xmlwriter, const bool saveastemplate) { xmlwriter->writeAttribute("y", QString::number(pos().y())); xmlwriter->writeAttribute("width", QString::number(width())); xmlwriter->writeAttribute("height", QString::number(height())); - QDateTime datetime = QDateTime::fromString(birthDate(), Qt::LocalDate); + QDateTime datetime = QLocale().toDateTime(birthDate(), QLocale::ShortFormat); xmlwriter->writeAttribute("creation_time", datetime.toString("yyyy-dd-MM hh:mm:ss:zzz")); xmlwriter->writeAttribute("caption_spec", QString::number(captionPolicy())); @@ -1020,7 +1025,9 @@ void Layout3D::copy(Layout3D *layout, QList
tables, } std::unique_ptr xmlwriter = std::unique_ptr(new XmlStreamWriter(file.get())); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) xmlwriter->setCodec("UTF-8"); +#endif xmlwriter->setAutoFormatting(false); layout->save(xmlwriter.get()); file->close(); diff --git a/alphaplot/src/3Dplot/Layout3D.h b/alphaplot/src/3Dplot/Layout3D.h index 88ae0390..3a3fa2ef 100644 --- a/alphaplot/src/3Dplot/Layout3D.h +++ b/alphaplot/src/3Dplot/Layout3D.h @@ -16,7 +16,7 @@ class XmlStreamReader; class XmlStreamWriter; class Custom3DInteractions; class ApplicationWindow; -using namespace QtDataVisualization; + class Layout3D : public MyWidget { Q_OBJECT diff --git a/alphaplot/src/3Dplot/Scatter3D.cpp b/alphaplot/src/3Dplot/Scatter3D.cpp index 6668056f..6b5c6135 100644 --- a/alphaplot/src/3Dplot/Scatter3D.cpp +++ b/alphaplot/src/3Dplot/Scatter3D.cpp @@ -7,6 +7,11 @@ #include "future/core/column/Column.h" #include "future/lib/XmlStreamReader.h" #include "future/lib/XmlStreamWriter.h" + +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +using namespace QtDataVisualization; +#endif + Scatter3D::Scatter3D(Q3DScatter *scatter) : graph_(scatter), data_(QVector()), counter_(0) { diff --git a/alphaplot/src/3Dplot/Scatter3D.h b/alphaplot/src/3Dplot/Scatter3D.h index f6f85c5c..5818f0d2 100644 --- a/alphaplot/src/3Dplot/Scatter3D.h +++ b/alphaplot/src/3Dplot/Scatter3D.h @@ -13,7 +13,7 @@ class Column; class DataBlockScatter3D; class XmlStreamWriter; class XmlStreamReader; -using namespace QtDataVisualization; + class Scatter3D : public QObject { Q_OBJECT diff --git a/alphaplot/src/3Dplot/Surface3D.cpp b/alphaplot/src/3Dplot/Surface3D.cpp index f5a9c111..b78ba84e 100644 --- a/alphaplot/src/3Dplot/Surface3D.cpp +++ b/alphaplot/src/3Dplot/Surface3D.cpp @@ -13,7 +13,9 @@ #include "scripting/Script.h" #include "scripting/ScriptingEnv.h" +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) using namespace QtDataVisualization; +#endif Surface3D::Surface3D(Q3DSurface *surface) : graph_(surface), @@ -612,7 +614,7 @@ void Surface3D::setSurfaceMeshType(const QSurface3DSeries::DrawFlag &type, series->setDrawMode(type); } -QtDataVisualization::QSurface3DSeries::DrawFlag Surface3D::getSurfaceMeshType( +QSurface3DSeries::DrawFlag Surface3D::getSurfaceMeshType( QSurface3DSeries *series) const { if (series->drawMode().testFlag(QSurface3DSeries::DrawFlag::DrawSurface)) return QSurface3DSeries::DrawFlag::DrawSurface; diff --git a/alphaplot/src/3Dplot/Surface3D.h b/alphaplot/src/3Dplot/Surface3D.h index 402519f0..473becd8 100644 --- a/alphaplot/src/3Dplot/Surface3D.h +++ b/alphaplot/src/3Dplot/Surface3D.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "3Dplot/Graph3DCommon.h" @@ -14,7 +15,7 @@ class DataBlockSurface3D; class XmlStreamWriter; class XmlStreamReader; class ApplicationWindow; -using namespace QtDataVisualization; + class Surface3D : public QObject { Q_OBJECT @@ -30,7 +31,7 @@ class Surface3D : public QObject { void setSurfaceMeshType(const QSurface3DSeries::DrawFlag &type, QSurface3DSeries *series); - QtDataVisualization::QSurface3DSeries::DrawFlag getSurfaceMeshType( + QSurface3DSeries::DrawFlag getSurfaceMeshType( QSurface3DSeries *series) const; void setfunctiondata(QList, double>> *data, diff --git a/alphaplot/src/3Dplot/SurfaceDialog.cpp b/alphaplot/src/3Dplot/SurfaceDialog.cpp index fee459fd..6262aad8 100644 --- a/alphaplot/src/3Dplot/SurfaceDialog.cpp +++ b/alphaplot/src/3Dplot/SurfaceDialog.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/3Dplot/SurfaceDialog.h b/alphaplot/src/3Dplot/SurfaceDialog.h index 1e4e3acd..d55f5098 100644 --- a/alphaplot/src/3Dplot/SurfaceDialog.h +++ b/alphaplot/src/3Dplot/SurfaceDialog.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/About.cpp b/alphaplot/src/About.cpp index 1c08f0b4..2d3bd2f4 100644 --- a/alphaplot/src/About.cpp +++ b/alphaplot/src/About.cpp @@ -19,6 +19,7 @@ #include "core/IconLoader.h" #include "core/Utilities.h" +#include #include "globals.h" About::About(QWidget* parent) : QDialog(parent) { diff --git a/alphaplot/src/ApplicationWindow.cpp b/alphaplot/src/ApplicationWindow.cpp index 62325bd2..f543b3d0 100644 --- a/alphaplot/src/ApplicationWindow.cpp +++ b/alphaplot/src/ApplicationWindow.cpp @@ -96,7 +96,7 @@ #include #include #include -#include +#include #include #include #include @@ -507,7 +507,7 @@ ApplicationWindow::ApplicationWindow() connect(ui_->actionRestartScripting, SIGNAL(triggered()), this, SLOT(restartScriptingEnv())); // Plot menu - connect(d_plot_mapper, SIGNAL(mapped(int)), this, SLOT(selectPlotType(int))); + connect(d_plot_mapper, SIGNAL(mappedInt(int)), this, SLOT(selectPlotType(int))); connect(ui_->actionPlot2DLine, SIGNAL(triggered()), d_plot_mapper, SLOT(map())); d_plot_mapper->setMapping(ui_->actionPlot2DLine, @@ -1920,8 +1920,8 @@ Layout2D *ApplicationWindow::newGraph2D(const QString &caption) { connect(layout2d, &Layout2D::showTitleBarMenu, this, &ApplicationWindow::showWindowTitleBarMenu); connect(layout2d, &Layout2D::mousepressevent, [=](MyWidget *widget) { - propertybrowser->populateObjectBrowser(widget); if (d_workspace->activeSubWindow() == widget) return; + propertybrowser->populateObjectBrowser(widget); widget->setNormal(); d_workspace->setActiveSubWindow(widget); }); @@ -1972,8 +1972,8 @@ Layout3D *ApplicationWindow::newGraph3D(const Graph3DCommon::Plot3DType &type, // QWindow doesnt pass mousepressevent to the container widget // so do it here manually connect(layout3d, &Layout3D::mousepressevent, this, [=]() { - propertybrowser->populateObjectBrowser(layout3d); if (d_workspace->activeSubWindow() == layout3d) return; + propertybrowser->populateObjectBrowser(layout3d); d_workspace->setActiveSubWindow(layout3d); }); @@ -2231,8 +2231,8 @@ void ApplicationWindow::initNote(Note *note, const QString &caption) { connect(note, SIGNAL(showTitleBarMenu()), this, SLOT(showWindowTitleBarMenu())); connect(note, &Note::mousepressevent, [=](MyWidget *widget) { - propertybrowser->populateObjectBrowser(widget); if (d_workspace->activeSubWindow() == widget) return; + propertybrowser->populateObjectBrowser(widget); widget->setNormal(); d_workspace->setActiveSubWindow(widget); }); @@ -2271,7 +2271,7 @@ void ApplicationWindow::matrixDeterminant() { if (!matrix) return; QDateTime dt = QDateTime::currentDateTime(); - QString info = "[" + dt.toString(Qt::LocalDate); + QString info = "[" + QLocale().toString(dt, QLocale::ShortFormat); info += tr("Determinant of ''") + QString(matrix->name()) + "'']
"; info += "

det = " + QString::number(matrix->determinant()) + "


"; @@ -2339,8 +2339,8 @@ void ApplicationWindow::initMatrix(Matrix *matrix) { connect(matrix, SIGNAL(showContextMenu()), this, SLOT(showWindowContextMenu())); connect(matrix, &Matrix::mousepressevent, [=](MyWidget *widget) { - propertybrowser->populateObjectBrowser(widget); if (d_workspace->activeSubWindow() == widget) return; + propertybrowser->populateObjectBrowser(widget); widget->setNormal(); d_workspace->setActiveSubWindow(widget); }); @@ -3315,10 +3315,10 @@ void ApplicationWindow::loadSettings() { // Follows an ugly hack to fix Qt4 porting issues (only needed on Windows) #ifdef Q_OS_WIN if (!recentProjects.isEmpty() && recentProjects[0].contains("^e")) - recentProjects = recentProjects[0].split("^e", QString::SkipEmptyParts); + recentProjects = recentProjects[0].split("^e", Qt::SkipEmptyParts); else if (recentProjects.count() == 1) { QString s = recentProjects[0]; - if (s.remove(QRegExp("\\s")).isEmpty()) recentProjects = QStringList(); + if (s.remove(QRegularExpression("\\s")).isEmpty()) recentProjects = QStringList(); } #endif @@ -3630,7 +3630,7 @@ void ApplicationWindow::loadSettings() { strip_spaces = settings.value("StripSpaces", false).toBool(); simplify_spaces = settings.value("SimplifySpaces", false).toBool(); d_ASCII_file_filter = settings.value("AsciiFileTypeFilter", "*").toString(); - d_ASCII_import_locale = settings.value("AsciiImportLocale", "C").toString(); + d_ASCII_import_locale = QLocale(settings.value("AsciiImportLocale", "C").toString()); d_convert_to_numeric = settings.value("ConvertToNumeric", true).toBool(); settings.endGroup(); // Import ASCII @@ -3642,10 +3642,10 @@ void ApplicationWindow::loadSettings() { d_export_resolution = settings.value("Resolution", 72).toInt(); d_export_color = settings.value("ExportColor", true).toBool(); d_export_vector_size = - settings.value("ExportPageSize", QPrinter::Custom).toInt(); + settings.value("ExportPageSize", QPageSize::Custom).toInt(); d_keep_plot_aspect = settings.value("KeepAspect", true).toBool(); d_export_orientation = - settings.value("Orientation", QPrinter::Landscape).toInt(); + settings.value("Orientation", QPageLayout::Landscape).toInt(); settings.endGroup(); // ExportImage } @@ -4259,7 +4259,7 @@ bool ApplicationWindow::renameWindow(MyWidget *w, const QString &text) { if (newName.isEmpty()) { QMessageBox::critical(this, tr("Error"), tr("Please enter a valid name!")); return false; - } else if (!newName.contains(QRegExp("^[a-zA-Z0-9-]*$"))) { + } else if (!newName.contains(QRegularExpression("^[a-zA-Z0-9-]*$"))) { QMessageBox::critical(this, tr("Error"), tr("The name you chose is not valid: only letters, " "digits and hyphen are allowed!") + @@ -5249,7 +5249,7 @@ void ApplicationWindow::addTimeStamp() { return; } - QString date = QDateTime::currentDateTime().toString(Qt::LocalDate); + QString date = QLocale().toString(QDateTime::currentDateTime(), QLocale::ShortFormat); axisrect->addTextItem2D(date); } @@ -6785,8 +6785,8 @@ void ApplicationWindow::connectTable(Table *table) { connect(table->d_future_table, SIGNAL(requestColumnStatistics()), this, SLOT(showColumnStatistics())); connect(table, &Table::mousepressevent, [=](MyWidget *widget) { - propertybrowser->populateObjectBrowser(widget); if (d_workspace->activeSubWindow() == widget) return; + propertybrowser->populateObjectBrowser(widget); widget->setNormal(); d_workspace->setActiveSubWindow(widget); @@ -6806,7 +6806,7 @@ void ApplicationWindow::setAppColors() { QPalette palet = qApp->palette(); palet.setColor(QPalette::Text, panelsTextColor); palet.setColor(QPalette::WindowText, panelsTextColor); - palet.setColor(QPalette::Foreground, panelsTextColor); + palet.setColor(QPalette::WindowText, QColor(Qt::darkGray)); palet.setColor(QPalette::ToolTipText, panelsTextColor); palet.setColor(QPalette::PlaceholderText, panelsTextColor); palet.setColor(QPalette::ButtonText, panelsTextColor); @@ -7586,7 +7586,7 @@ void ApplicationWindow::showFolderPopupMenu(QTreeWidgetItem *it, connect(&windowsInActiveFolder, SIGNAL(triggered()), &mapper, SLOT(map())); connect(&windowsInActiveFoldersAndSubs, SIGNAL(triggered()), &mapper, SLOT(map())); - connect(&mapper, SIGNAL(mapped(int)), this, SLOT(setShowWindowsPolicy(int))); + connect(&mapper, SIGNAL(mappedInt(int)), this, SLOT(setShowWindowsPolicy(int))); cm.addMenu(&viewWindowsMenu); cm.addSeparator(); @@ -8026,8 +8026,8 @@ void ApplicationWindow::folderProperties() { (saved) ? properties.status = tr("Saved") : properties.status = tr("Not Saved"); properties.size = QString::number(fileInfo.size()); - properties.created = fileInfo.birthTime().toString(Qt::LocalDate); - properties.modified = fileInfo.lastModified().toString(Qt::LocalDate); + properties.created = QLocale().toString(fileInfo.birthTime(), QLocale::ShortFormat); + properties.modified = QLocale().toString(fileInfo.lastModified(), QLocale::ShortFormat); properties.label = ""; } else { properties.path = projectname; @@ -9761,128 +9761,49 @@ bool ApplicationWindow::isActiveSubWindow( //----------------------------scripting related code--------------------------- void ApplicationWindow::attachQtScript() { - // pass mainwindow as global object - QScriptValue objectValue = consoleWindow->engine->newQObject(this); - consoleWindow->engine->globalObject().setProperty("Alpha", objectValue); - - QScriptValue clearFunction = consoleWindow->engine->newFunction(&openProj); - clearFunction.setData(objectValue); - consoleWindow->engine->globalObject().setProperty("openAproj", clearFunction); - - qScriptRegisterMetaType
(consoleWindow->engine, - tableObjectToScriptValue, - tableObjectFromScriptValue); - qScriptRegisterMetaType(consoleWindow->engine, - tableObjectToScriptValue, - tableObjectFromScriptValue); - qScriptRegisterMetaType(consoleWindow->engine, - tableObjectToScriptValue, - tableObjectFromScriptValue); - qScriptRegisterMetaType(consoleWindow->engine, - tableObjectToScriptValue, - tableObjectFromScriptValue); - qScriptRegisterMetaType>(consoleWindow->engine, toScriptValue, - fromScriptValue); - qScriptRegisterMetaType>(consoleWindow->engine, toScriptValue, - fromScriptValue); - qScriptRegisterMetaType>(consoleWindow->engine, toScriptValue, - fromScriptValue); - qScriptRegisterMetaType>(consoleWindow->engine, toScriptValue, - fromScriptValue); - qScriptRegisterMetaType>(consoleWindow->engine, - toScriptValue, fromScriptValue); - qScriptRegisterMetaType>(consoleWindow->engine, toScriptValue, - fromScriptValue); - qScriptRegisterMetaType>(consoleWindow->engine, - toScriptValue, fromScriptValue); -} - -Table *ApplicationWindow::getTableHandle() { - if (context()->argumentCount() != 1 || !context()->argument(0).isString()) { - context()->throwError(tr("getTableHandle(string) take one argument!")); - } - - bool namedWidgetPresent = false; + if (!consoleWindow || !consoleWindow->engine) return; + + QJSEngine *engine = consoleWindow->engine; + // Expose the main window as 'Alpha' — all Q_INVOKABLE methods and public + // slots on ApplicationWindow become callable from JavaScript. + QJSValue objectValue = engine->newQObject(this); + engine->globalObject().setProperty("Alpha", objectValue); + + // Inject JS convenience wrappers + engine->evaluate( + "function openAproj(path) { Alpha.open(path); }\n" + ); +} + +Table *ApplicationWindow::getTableHandle(const QString &name) { QList subwindowlist = subWindowsList(); foreach (QMdiSubWindow *subwindow, subwindowlist) { - if (subwindow->objectName() == context()->argument(0).toString()) { - if (qobject_cast
(subwindow)) { - namedWidgetPresent = true; - Table *table = qobject_cast
(subwindow); - return table; - } else { - context()->throwError(context()->argument(0).toString() + - tr(" is not a valid Table object name!")); - } + if (subwindow->objectName() == name) { + Table *table = qobject_cast
(subwindow); + if (table) return table; } } - - if (!namedWidgetPresent) { - context()->throwError(context()->argument(0).toString() + - tr(" is not a valid Table object name!")); - } - - // will never reach here return nullptr; } -Matrix *ApplicationWindow::getMatrixHandle() { - if (context()->argumentCount() != 1 || !context()->argument(0).isString()) { - context()->throwError(tr("getMatrixHandle(string) take one argument!")); - } - - bool namedWidgetPresent = false; +Matrix *ApplicationWindow::getMatrixHandle(const QString &name) { QList subwindowlist = subWindowsList(); foreach (QMdiSubWindow *subwindow, subwindowlist) { - if (subwindow->objectName() == context()->argument(0).toString()) { - if (qobject_cast(subwindow)) { - namedWidgetPresent = true; - Matrix *matrix = qobject_cast(subwindow); - return matrix; - } else { - context()->throwError(context()->argument(0).toString() + - tr(" is not a valid Matrix object name!")); - } + if (subwindow->objectName() == name) { + Matrix *matrix = qobject_cast(subwindow); + if (matrix) return matrix; } } - - if (!namedWidgetPresent) { - context()->throwError(context()->argument(0).toString() + - tr(" is not a valid Matrix object name!")); - } - - // will never reach here return nullptr; } -Note *ApplicationWindow::getNoteHandle() { - if (context()->argumentCount() != 1 || !context()->argument(0).isString()) { - context()->throwError(tr("getNoteHandle(string) take one argument!")); - } - - bool namedWidgetPresent = false; +Note *ApplicationWindow::getNoteHandle(const QString &name) { QList subwindowlist = subWindowsList(); foreach (QMdiSubWindow *subwindow, subwindowlist) { - if (subwindow->objectName() == context()->argument(0).toString()) { - if (qobject_cast(subwindow)) { - namedWidgetPresent = true; - Note *note = qobject_cast(subwindow); - if (!note) { - context()->throwError(tr("Unable to get Note handle!")); - } - return note; - } else { - context()->throwError(context()->argument(0).toString() + - tr(" is not a valid Note object name!")); - } + if (subwindow->objectName() == name) { + Note *note = qobject_cast(subwindow); + if (note) return note; } } - - if (!namedWidgetPresent) { - context()->throwError(context()->argument(0).toString() + - tr(" is not a valid Note object name!")); - } - - // will never reach here return nullptr; } diff --git a/alphaplot/src/ApplicationWindow.h b/alphaplot/src/ApplicationWindow.h index 3cac792d..dfd70edd 100644 --- a/alphaplot/src/ApplicationWindow.h +++ b/alphaplot/src/ApplicationWindow.h @@ -124,8 +124,7 @@ class Function2DDialog; * Project/ProjectExplorer.*/ class ApplicationWindow : public QMainWindow, - public scripted, - public QScriptable { + public scripted { Q_OBJECT public: ApplicationWindow(); @@ -1145,9 +1144,9 @@ class ApplicationWindow : public QMainWindow, void lockToolbars(const bool status); public slots: - Table* getTableHandle(); - Matrix* getMatrixHandle(); - Note* getNoteHandle(); + Table* getTableHandle(const QString &name); + Matrix* getMatrixHandle(const QString &name); + Note* getNoteHandle(const QString &name); }; #endif // APPLICATION_H diff --git a/alphaplot/src/AssociationsDialog.cpp b/alphaplot/src/AssociationsDialog.cpp index f3e39530..bd8a9e00 100644 --- a/alphaplot/src/AssociationsDialog.cpp +++ b/alphaplot/src/AssociationsDialog.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -116,7 +116,7 @@ void AssociationsDialog::changePlotAssociation(int curve, const QString &text) { if (c->plotAssociation() == text) return; - QStringList lst = text.split(",", QString::SkipEmptyParts); + QStringList lst = text.split(",", Qt::SkipEmptyParts); if (lst.count() == 2) { c->setXColumnName(lst[0].remove("(X)")); c->setTitle(lst[1].remove("(Y)")); @@ -135,8 +135,8 @@ void AssociationsDialog::changePlotAssociation(int curve, const QString &text) { QString AssociationsDialog::plotAssociation(const QString &text) { QString s = text; - QStringList lst = s.split(": ", QString::SkipEmptyParts); - QStringList cols = lst[1].split(",", QString::SkipEmptyParts); + QStringList lst = s.split(": ", Qt::SkipEmptyParts); + QStringList cols = lst[1].split(",", Qt::SkipEmptyParts); QString tableName = lst[0]; s = tableName + "_" + cols[0]; @@ -157,7 +157,7 @@ void AssociationsDialog::initTablesList(QList *lst, Table *AssociationsDialog::findTable(int index) { QString text = associations->item(index)->text(); - QStringList lst = text.split(":", QString::SkipEmptyParts); + QStringList lst = text.split(":", Qt::SkipEmptyParts); for (int i = 0; i < (int)tables->count(); i++) { if (tables->at(i)->objectName() == lst[0]) return (Table *)tables->at(i); } @@ -199,8 +199,8 @@ void AssociationsDialog::updateTable(int index) { void AssociationsDialog::updateColumnTypes() { QString text = associations->currentItem()->text(); - QStringList lst = text.split(": ", QString::SkipEmptyParts); - QStringList cols = lst[1].split(",", QString::SkipEmptyParts); + QStringList lst = text.split(": ", Qt::SkipEmptyParts); + QStringList cols = lst[1].split(",", Qt::SkipEmptyParts); QString xColName = cols[0].remove("(X)"); QString yColName = cols[1].remove("(Y)"); @@ -315,8 +315,8 @@ void AssociationsDialog::setAxisRect(AxisRect2D *axisrect) { void AssociationsDialog::updatePlotAssociation(int row, int col) { int index = associations->currentRow(); QString text = associations->currentItem()->text(); - QStringList lst = text.split(": ", QString::SkipEmptyParts); - QStringList cols = lst[1].split(",", QString::SkipEmptyParts); + QStringList lst = text.split(": ", Qt::SkipEmptyParts); + QStringList cols = lst[1].split(",", Qt::SkipEmptyParts); if (col == 1) { cols[0] = table->item(row, 0)->text() + "(X)"; @@ -356,7 +356,7 @@ void AssociationsDialog::updatePlotAssociation(int row, int col) { QString as = plotAssociationsList[i]; if (as.contains(old_as) && (as.contains("(xErr)") || as.contains("(yErr)"))) { - QStringList ls = as.split(",", QString::SkipEmptyParts); + QStringList ls = as.split(",", Qt::SkipEmptyParts); as = text + "," + ls[2]; plotAssociationsList[i] = as; } diff --git a/alphaplot/src/AssociationsDialog.h b/alphaplot/src/AssociationsDialog.h index 712307f2..eba3a6cd 100644 --- a/alphaplot/src/AssociationsDialog.h +++ b/alphaplot/src/AssociationsDialog.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -35,7 +35,7 @@ class QLabel; class QListWidget; class QPushButton; class QTableWidget; -class QStringList; +#include class Table; class QMdiSubWindow; class AxisRect2D; diff --git a/alphaplot/src/ColorBox.cpp b/alphaplot/src/ColorBox.cpp index 5e7498ee..b200aa98 100644 --- a/alphaplot/src/ColorBox.cpp +++ b/alphaplot/src/ColorBox.cpp @@ -14,7 +14,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/ColorBox.h b/alphaplot/src/ColorBox.h index 7915998d..a4db8754 100644 --- a/alphaplot/src/ColorBox.h +++ b/alphaplot/src/ColorBox.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/ColorButton.cpp b/alphaplot/src/ColorButton.cpp index d01f4733..1cb99162 100644 --- a/alphaplot/src/ColorButton.cpp +++ b/alphaplot/src/ColorButton.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -50,7 +50,7 @@ void ColorButton::init() { setColor(QColor(Qt::white)); QHBoxLayout *l = new QHBoxLayout(this); - l->setMargin(0); + l->setContentsMargins(0, 0, 0, 0); l->addWidget(display); l->addWidget(selectButton); diff --git a/alphaplot/src/ColorButton.h b/alphaplot/src/ColorButton.h index 45e28e7c..8ebb77fd 100644 --- a/alphaplot/src/ColorButton.h +++ b/alphaplot/src/ColorButton.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/DataSetDialog.cpp b/alphaplot/src/DataSetDialog.cpp index 3b2c0279..33054dd4 100644 --- a/alphaplot/src/DataSetDialog.cpp +++ b/alphaplot/src/DataSetDialog.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/DataSetDialog.h b/alphaplot/src/DataSetDialog.h index e6340971..55b89665 100644 --- a/alphaplot/src/DataSetDialog.h +++ b/alphaplot/src/DataSetDialog.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/FindDialog.cpp b/alphaplot/src/FindDialog.cpp index 72809771..abfe10fe 100644 --- a/alphaplot/src/FindDialog.cpp +++ b/alphaplot/src/FindDialog.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include "ApplicationWindow.h" diff --git a/alphaplot/src/FindDialog.h b/alphaplot/src/FindDialog.h index 46123e97..b5bf3879 100644 --- a/alphaplot/src/FindDialog.h +++ b/alphaplot/src/FindDialog.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/Folder.cpp b/alphaplot/src/Folder.cpp index 45e8ac34..7a8ea19c 100644 --- a/alphaplot/src/Folder.cpp +++ b/alphaplot/src/Folder.cpp @@ -39,7 +39,7 @@ QStringList Folder::currentFolderNames = {}; Folder::Folder(Folder *parent, const QString &name) : QObject(parent), d_active_window(nullptr) { QObject::setObjectName(name); - birthdate = QDateTime::currentDateTime().toString(Qt::LocalDate); + birthdate = QLocale().toString(QDateTime::currentDateTime(), QLocale::ShortFormat); } QList Folder::folders() const { diff --git a/alphaplot/src/ImageExportDlg.cpp b/alphaplot/src/ImageExportDlg.cpp index bf94ae14..3c2286dc 100644 --- a/alphaplot/src/ImageExportDlg.cpp +++ b/alphaplot/src/ImageExportDlg.cpp @@ -14,7 +14,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -94,57 +94,57 @@ void ImageExportDlg::initAdvancedOptions() { vector_layout->addWidget(d_standard_page, 3, 0, 1, 2); d_box_page_size = new QComboBox(); - d_box_page_size->addItem(tr("A0 - 841 x 1189 mm"), QVariant(QPrinter::A0)); - d_box_page_size->addItem(tr("A1 - 594 x 841 mm"), QVariant(QPrinter::A1)); - d_box_page_size->addItem(tr("A2 - 420 x 594 mm"), QVariant(QPrinter::A2)); - d_box_page_size->addItem(tr("A3 - 297 x 420 mm"), QVariant(QPrinter::A3)); - d_box_page_size->addItem(tr("A4 - 210 x 297 mm"), QVariant(QPrinter::A4)); - d_box_page_size->addItem(tr("A5 - 148 x 210 mm"), QVariant(QPrinter::A5)); - d_box_page_size->addItem(tr("A6 - 105 x 148 mm"), QVariant(QPrinter::A6)); - d_box_page_size->addItem(tr("A7 - 74 x 105 mm"), QVariant(QPrinter::A7)); - d_box_page_size->addItem(tr("A8 - 52 x 74 mm"), QVariant(QPrinter::A8)); - d_box_page_size->addItem(tr("A9 - 37 x 52 mm"), QVariant(QPrinter::A9)); - d_box_page_size->addItem(tr("B0 - 1030 x 1456 mm"), QVariant(QPrinter::B0)); - d_box_page_size->addItem(tr("B1 - 728 x 1030 mm"), QVariant(QPrinter::B1)); - d_box_page_size->addItem(tr("B2 - 515 x 728 mm"), QVariant(QPrinter::B2)); - d_box_page_size->addItem(tr("B3 - 364 x 515 mm"), QVariant(QPrinter::B3)); - d_box_page_size->addItem(tr("B4 - 257 x 364 mm"), QVariant(QPrinter::B4)); - d_box_page_size->addItem(tr("B5 - 182 x 257 mm"), QVariant(QPrinter::B5)); - d_box_page_size->addItem(tr("B6 - 128 x 182 mm"), QVariant(QPrinter::B6)); - d_box_page_size->addItem(tr("B7 - 91 x 128 mm"), QVariant(QPrinter::B7)); - d_box_page_size->addItem(tr("B8 - 64 x 91 mm"), QVariant(QPrinter::B8)); - d_box_page_size->addItem(tr("B9 - 45 x 64 mm"), QVariant(QPrinter::B9)); - d_box_page_size->addItem(tr("B10 - 32 x 45 mm"), QVariant(QPrinter::B10)); - d_box_page_size->addItem(tr("C5E - 163 x 226 mm"), QVariant(QPrinter::C5E)); + d_box_page_size->addItem(tr("A0 - 841 x 1189 mm"), QVariant(QPageSize::A0)); + d_box_page_size->addItem(tr("A1 - 594 x 841 mm"), QVariant(QPageSize::A1)); + d_box_page_size->addItem(tr("A2 - 420 x 594 mm"), QVariant(QPageSize::A2)); + d_box_page_size->addItem(tr("A3 - 297 x 420 mm"), QVariant(QPageSize::A3)); + d_box_page_size->addItem(tr("A4 - 210 x 297 mm"), QVariant(QPageSize::A4)); + d_box_page_size->addItem(tr("A5 - 148 x 210 mm"), QVariant(QPageSize::A5)); + d_box_page_size->addItem(tr("A6 - 105 x 148 mm"), QVariant(QPageSize::A6)); + d_box_page_size->addItem(tr("A7 - 74 x 105 mm"), QVariant(QPageSize::A7)); + d_box_page_size->addItem(tr("A8 - 52 x 74 mm"), QVariant(QPageSize::A8)); + d_box_page_size->addItem(tr("A9 - 37 x 52 mm"), QVariant(QPageSize::A9)); + d_box_page_size->addItem(tr("B0 - 1030 x 1456 mm"), QVariant(QPageSize::B0)); + d_box_page_size->addItem(tr("B1 - 728 x 1030 mm"), QVariant(QPageSize::B1)); + d_box_page_size->addItem(tr("B2 - 515 x 728 mm"), QVariant(QPageSize::B2)); + d_box_page_size->addItem(tr("B3 - 364 x 515 mm"), QVariant(QPageSize::B3)); + d_box_page_size->addItem(tr("B4 - 257 x 364 mm"), QVariant(QPageSize::B4)); + d_box_page_size->addItem(tr("B5 - 182 x 257 mm"), QVariant(QPageSize::B5)); + d_box_page_size->addItem(tr("B6 - 128 x 182 mm"), QVariant(QPageSize::B6)); + d_box_page_size->addItem(tr("B7 - 91 x 128 mm"), QVariant(QPageSize::B7)); + d_box_page_size->addItem(tr("B8 - 64 x 91 mm"), QVariant(QPageSize::B8)); + d_box_page_size->addItem(tr("B9 - 45 x 64 mm"), QVariant(QPageSize::B9)); + d_box_page_size->addItem(tr("B10 - 32 x 45 mm"), QVariant(QPageSize::B10)); + d_box_page_size->addItem(tr("C5E - 163 x 226 mm"), QVariant(QPageSize::C5E)); d_box_page_size->addItem(tr("Comm10E - 105 x 241 mm"), - QVariant(QPrinter::Comm10E)); - d_box_page_size->addItem(tr("DLE - 110 x 220 mm"), QVariant(QPrinter::DLE)); + QVariant(QPageSize::Comm10E)); + d_box_page_size->addItem(tr("DLE - 110 x 220 mm"), QVariant(QPageSize::DLE)); d_box_page_size->addItem(tr("Executive - 191 x 254 mm"), - QVariant(QPrinter::Executive)); - d_box_page_size->addItem(tr("Folio 210 x 330 mm"), QVariant(QPrinter::Folio)); + QVariant(QPageSize::Executive)); + d_box_page_size->addItem(tr("Folio 210 x 330 mm"), QVariant(QPageSize::Folio)); d_box_page_size->addItem(tr("Ledger 432 x 279 mm"), - QVariant(QPrinter::Ledger)); - d_box_page_size->addItem(tr("Legal 216 x 356 mm"), QVariant(QPrinter::Legal)); + QVariant(QPageSize::Ledger)); + d_box_page_size->addItem(tr("Legal 216 x 356 mm"), QVariant(QPageSize::Legal)); d_box_page_size->addItem(tr("Letter 216 x 279 mm"), - QVariant(QPrinter::Letter)); + QVariant(QPageSize::Letter)); d_box_page_size->addItem(tr("Tabloid 279 x 432 mm"), - QVariant(QPrinter::Tabloid)); + QVariant(QPageSize::Tabloid)); vector_layout->addWidget(new QLabel(tr("Page size")), 4, 0); - setPageSize((QPrinter::PageSize)app->d_export_vector_size); - d_standard_page->setChecked(app->d_export_vector_size != QPrinter::Custom); - d_box_page_size->setEnabled(app->d_export_vector_size != QPrinter::Custom); + setPageSize((QPageSize::PageSizeId)app->d_export_vector_size); + d_standard_page->setChecked(app->d_export_vector_size != QPageSize::Custom); + d_box_page_size->setEnabled(app->d_export_vector_size != QPageSize::Custom); vector_layout->addWidget(d_box_page_size, 4, 1, 1, 2); vector_layout->addWidget(new QLabel(tr("Orientation")), 5, 0); d_box_page_orientation = new QComboBox(); d_box_page_orientation->addItem(tr("Portrait", "page orientation"), - QVariant(QPrinter::Portrait)); + QVariant(QPageLayout::Portrait)); d_box_page_orientation->addItem(tr("Landscape", "page orientation"), - QVariant(QPrinter::Landscape)); + QVariant(QPageLayout::Landscape)); d_box_page_orientation->setCurrentIndex(app->d_export_orientation); d_box_page_orientation->setEnabled(app->d_export_vector_size != - QPrinter::Custom); + QPageSize::Custom); vector_layout->addWidget(d_box_page_orientation, 5, 1, 1, 2); connect(d_standard_page, &QCheckBox::toggled, d_box_page_size, @@ -200,16 +200,16 @@ void ImageExportDlg::closeEvent(QCloseEvent *e) { e->accept(); } -QPrinter::PageSize ImageExportDlg::pageSize() const { - if (!d_standard_page->isChecked()) return QPrinter::Custom; +QPageSize::PageSizeId ImageExportDlg::pageSize() const { + if (!d_standard_page->isChecked()) return QPageSize::Custom; - QPrinter::PageSize size; + QPageSize::PageSizeId size; switch (d_box_page_size->currentIndex()) { case -1: - size = QPrinter::A4; + size = QPageSize::A4; break; default: - size = (QPrinter::PageSize)d_box_page_size + size = (QPageSize::PageSizeId)d_box_page_size ->itemData(d_box_page_size->currentIndex()) .toInt(); break; @@ -217,14 +217,14 @@ QPrinter::PageSize ImageExportDlg::pageSize() const { return size; } -QPrinter::Orientation ImageExportDlg::pageOrientation() const { - QPrinter::Orientation orientation; +QPageLayout::Orientation ImageExportDlg::pageOrientation() const { + QPageLayout::Orientation orientation; switch (d_box_page_orientation->currentIndex()) { case -1: - orientation = QPrinter::Portrait; + orientation = QPageLayout::Portrait; break; default: - orientation = (QPrinter::Orientation)d_box_page_orientation + orientation = (QPageLayout::Orientation)d_box_page_orientation ->itemData(d_box_page_orientation->currentIndex()) .toInt(); break; @@ -232,20 +232,20 @@ QPrinter::Orientation ImageExportDlg::pageOrientation() const { return orientation; } -void ImageExportDlg::setPageSize(QPrinter::PageSize size) { - if (size == QPrinter::Custom) return; +void ImageExportDlg::setPageSize(QPageSize::PageSizeId size) { + if (size == QPageSize::Custom) return; int index = d_box_page_size->findData(QVariant(size)); if (index != -1) d_box_page_size->setCurrentIndex(index); else { - index = d_box_page_size->findData(QVariant(QPrinter::A4)); + index = d_box_page_size->findData(QVariant(QPageSize::A4)); Q_ASSERT(index != -1); d_box_page_size->setCurrentIndex(index); } } -void ImageExportDlg::setOrientation(QPrinter::Orientation orientation) { +void ImageExportDlg::setOrientation(QPageLayout::Orientation orientation) { int index = d_box_page_orientation->findData(QVariant(orientation)); if (index != -1) d_box_page_orientation->setCurrentIndex(index); diff --git a/alphaplot/src/ImageExportDlg.h b/alphaplot/src/ImageExportDlg.h index 972fef9b..53ee8138 100644 --- a/alphaplot/src/ImageExportDlg.h +++ b/alphaplot/src/ImageExportDlg.h @@ -14,7 +14,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include #include "ui/ExtensibleFileDialog.h" @@ -87,10 +89,10 @@ class ImageExportDlg : public ExtensibleFileDialog { bool keepAspect() const { return d_keep_aspect->isChecked(); } //! For vector formats: returns a standard output page size (default: //! QPrinter::Custom). - QPrinter::PageSize pageSize() const; - void setPageSize(QPrinter::PageSize size); - QPrinter::Orientation pageOrientation() const; - void setOrientation(QPrinter::Orientation orientation); + QPageSize::PageSizeId pageSize() const; + void setPageSize(QPageSize::PageSizeId size); + QPageLayout::Orientation pageOrientation() const; + void setOrientation(QPageLayout::Orientation orientation); //! Return the quality (in percent) the user selected for export to raster //! formats. int quality() const { return d_quality->value(); } diff --git a/alphaplot/src/ImportASCIIDialog.cpp b/alphaplot/src/ImportASCIIDialog.cpp index 835f87e9..84d8d459 100644 --- a/alphaplot/src/ImportASCIIDialog.cpp +++ b/alphaplot/src/ImportASCIIDialog.cpp @@ -14,7 +14,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include "ApplicationWindow.h" @@ -241,7 +241,7 @@ const QString ImportASCIIDialog::columnSeparator() const { sep.replace("\\t", "\t"); /* TODO - if (sep.contains(QRegExp("[0-9.eE+-]"))) + if (sep.contains(QRegularExpression("[0-9.eE+-]"))) QMessageBox::warning(this, tr("Import options error"), tr("The separator must not contain the following characters: 0-9eE.+-")); diff --git a/alphaplot/src/ImportASCIIDialog.h b/alphaplot/src/ImportASCIIDialog.h index c495a13f..42073df8 100644 --- a/alphaplot/src/ImportASCIIDialog.h +++ b/alphaplot/src/ImportASCIIDialog.h @@ -14,7 +14,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/LineProfileTool.cpp b/alphaplot/src/LineProfileTool.cpp index 1224ea9e..b0da9c80 100644 --- a/alphaplot/src/LineProfileTool.cpp +++ b/alphaplot/src/LineProfileTool.cpp @@ -15,7 +15,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/LineProfileTool.h b/alphaplot/src/LineProfileTool.h index cfaea8b6..571fc559 100644 --- a/alphaplot/src/LineProfileTool.h +++ b/alphaplot/src/LineProfileTool.h @@ -15,7 +15,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/Matrix.cpp b/alphaplot/src/Matrix.cpp index f34850ce..4edfd445 100644 --- a/alphaplot/src/Matrix.cpp +++ b/alphaplot/src/Matrix.cpp @@ -14,7 +14,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -87,7 +87,7 @@ void Matrix::init(int rows, int cols) { d_future_matrix->setCoordinates(1.0, 10.0, 1.0, 10.0); dMatrix = nullptr; - birthdate = d_future_matrix->creationTime().toString(Qt::LocalDate); + birthdate = QLocale().toString(d_future_matrix->creationTime(), QLocale::ShortFormat); // this is not very nice but works for the moment ui._2->removeWidget(ui.formula_box); diff --git a/alphaplot/src/Matrix.h b/alphaplot/src/Matrix.h index 4c42272a..509e78b9 100644 --- a/alphaplot/src/Matrix.h +++ b/alphaplot/src/Matrix.h @@ -14,7 +14,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -289,7 +289,7 @@ class Matrix : public MatrixView, //! Return the creation date virtual QString birthDate() override { - return d_future_matrix->creationTime().toString(Qt::LocalDate); + return QLocale().toString(d_future_matrix->creationTime(), QLocale::ShortFormat); } signals: diff --git a/alphaplot/src/MyWidget.cpp b/alphaplot/src/MyWidget.cpp index f941b1a3..e2704463 100644 --- a/alphaplot/src/MyWidget.cpp +++ b/alphaplot/src/MyWidget.cpp @@ -14,7 +14,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/MyWidget.h b/alphaplot/src/MyWidget.h index 2c67a5ab..0a99a850 100644 --- a/alphaplot/src/MyWidget.h +++ b/alphaplot/src/MyWidget.h @@ -14,7 +14,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/Note.cpp b/alphaplot/src/Note.cpp index 46039b47..ba79f5a8 100644 --- a/alphaplot/src/Note.cpp +++ b/alphaplot/src/Note.cpp @@ -15,7 +15,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -64,7 +64,7 @@ QString Note::getItemTooltip() { return name(); } void Note::init(ScriptingEnv* env) { autoExec = false; QDateTime dt = QDateTime::currentDateTime(); - setBirthDate(dt.toString(Qt::LocalDate)); + setBirthDate(QLocale().toString(dt, QLocale::ShortFormat)); textedit_ = new ScriptEdit(env, this, name()); textedit_->setContext(this); @@ -80,7 +80,7 @@ void Note::modifiedNote() { emit modifiedWindow(this); } void Note::save(QXmlStreamWriter* xmlwriter) { xmlwriter->writeStartElement("note"); - QDateTime datetime = QDateTime::fromString(birthDate(), Qt::LocalDate); + QDateTime datetime = QLocale().toDateTime(birthDate(), QLocale::ShortFormat); xmlwriter->writeAttribute("creation_time", datetime.toString("yyyy-dd-MM hh:mm:ss:zzz")); xmlwriter->writeAttribute("caption_spec", QString::number(captionPolicy())); @@ -125,9 +125,9 @@ bool Note::load(XmlStreamReader* xmlreader) { xmlreader->raiseWarning( tr("Invalid creation time for '%1'. Using current time.") .arg(name())); - setBirthDate(QDateTime::currentDateTime().toString(Qt::LocalDate)); + setBirthDate(QLocale().toString(QDateTime::currentDateTime(), QLocale::ShortFormat)); } else - setBirthDate(creation_time.toString(Qt::LocalDate)); + setBirthDate(QLocale().toString(creation_time, QLocale::ShortFormat)); // read caption spec basicattr = attribs.value(xmlreader->namespaceUri().toString(), "caption_spec") diff --git a/alphaplot/src/Note.h b/alphaplot/src/Note.h index d334485d..0d453906 100644 --- a/alphaplot/src/Note.h +++ b/alphaplot/src/Note.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/OpenProjectDialog.cpp b/alphaplot/src/OpenProjectDialog.cpp index 63477159..4e689cb0 100644 --- a/alphaplot/src/OpenProjectDialog.cpp +++ b/alphaplot/src/OpenProjectDialog.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/OpenProjectDialog.h b/alphaplot/src/OpenProjectDialog.h index d37c5196..f81f1c38 100644 --- a/alphaplot/src/OpenProjectDialog.h +++ b/alphaplot/src/OpenProjectDialog.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/PatternBox.cpp b/alphaplot/src/PatternBox.cpp index cb67a93b..544fcfef 100644 --- a/alphaplot/src/PatternBox.cpp +++ b/alphaplot/src/PatternBox.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/PatternBox.h b/alphaplot/src/PatternBox.h index be29d57c..409b1808 100644 --- a/alphaplot/src/PatternBox.h +++ b/alphaplot/src/PatternBox.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/PlotWizard.cpp b/alphaplot/src/PlotWizard.cpp index 6bc5d0fa..126b7646 100644 --- a/alphaplot/src/PlotWizard.cpp +++ b/alphaplot/src/PlotWizard.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -155,7 +155,7 @@ void PlotWizard::accept() { #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) QStringList lst = text.split(",", Qt::SkipEmptyParts); #else - QStringList lst = text.split(",", QString::SkipEmptyParts); + QStringList lst = text.split(",", Qt::SkipEmptyParts); #endif lst.pop_back(); QString master_curve = lst.join(","); diff --git a/alphaplot/src/PlotWizard.h b/alphaplot/src/PlotWizard.h index 04b4223f..d937d4bb 100644 --- a/alphaplot/src/PlotWizard.h +++ b/alphaplot/src/PlotWizard.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/Table.cpp b/alphaplot/src/Table.cpp index ec0d9b58..8e24fa0e 100644 --- a/alphaplot/src/Table.cpp +++ b/alphaplot/src/Table.cpp @@ -14,7 +14,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -106,7 +106,7 @@ void Table::init() { TableView::setTable(d_future_table); setMinimumSize(QSize(400, 300)); - birthdate = d_future_table->creationTime().toString(Qt::LocalDate); + birthdate = QLocale().toString(d_future_table->creationTime(), QLocale::ShortFormat); ui.formula_tab_layout->removeWidget(ui.formula_box); delete ui.formula_box; ui.formula_box = new ScriptEdit(scriptEnv, ui.formula_tab); @@ -216,7 +216,7 @@ void Table::setTableBackgroundColor(const QColor &col) { QPalette palette = d_view_widget->palette(); palette.setColor(QPalette::Base, col); palette.setColor(QPalette::Window, col); - palette.setColor(QPalette::Background, col); + palette.setColor(QPalette::Window, col); d_view_widget->setPalette(palette); } @@ -754,7 +754,7 @@ bool Table::exportASCII(const QString &fname, const QString &separator, if (withLabels) { QStringList header = colNames(); - QStringList ls = header.filter(QRegExp("\\D")); + QStringList ls = header.filter(QRegularExpression("\\D")); if (exportSelection) { for (i = 1; i < selectedCols; i++) { if (ls.count() > 0) @@ -1052,87 +1052,60 @@ void Table::importASCII(const QString &fname, const QString &sep, } // Scripting Functions -int Table::rowCount() { - if (context()->argumentCount() != 0) { - context()->throwError(tr("rowCount() take no arguments!")); +int Table::rowCount() { return numRows(); } + +int Table::colCount() { return numCols(); } + +double Table::getCell(int row, int col) { + if (row <= 0 || col <= 0) { + // context()->throwError(tr("row/col index cannot be 0 or -ve")); + return 0.0; + } else if (row > numRows()) { + // context()->throwError(tr("row index out of range!")); + return 0.0; + } else if (col > numCols()) { + // context()->throwError(tr("col index out of range!")); + return 0.0; } - return numRows(); + return cell(row - 1, col - 1); } -int Table::colCount() { - if (context()->argumentCount() != 0) { - context()->throwError(tr("colCount() take no arguments!")); - } - return numCols(); -} - -double Table::getCell() { - if (context()->argumentCount() != 2 || !context()->argument(0).isNumber() || - !context()->argument(1).isNumber()) { - context()->throwError( - tr("getCell(intiger, intiger) take two arguments!")); - } else if (context()->argument(0).toNumber() <= 0 || - context()->argument(1).toNumber() <= 0) { - context()->throwError(tr("row/col index cannot be 0 or -ve")); - } else if (context()->argument(0).toNumber() > numRows()) { - context()->throwError(tr("row index out of range!")); - } else if (context()->argument(1).toNumber() > numCols()) { - context()->throwError(tr("col index out of range!")); - } - return cell(context()->argument(0).toInt32() - 1, - context()->argument(1).toInt32() - 1); -} - -void Table::setCell() { - if (context()->argumentCount() != 3 || !context()->argument(0).isNumber() || - !context()->argument(1).isNumber() || - !context()->argument(2).isNumber()) { - context()->throwError( - tr("setCell(intiger, intiger, double) take three " - "arguments!")); - } else if (context()->argument(0).toNumber() <= 0 || - context()->argument(1).toNumber() <= 0) { - context()->throwError(tr("row/col index cannot be 0 or -ve!")); - } else if (context()->argument(0).toNumber() > numRows()) { - context()->throwError(tr("row index out of range!")); - } else if (context()->argument(1).toNumber() > numCols()) { - context()->throwError(tr("col index out of range!")); +void Table::setCell(int row, int col, double val) { + if (row <= 0 || col <= 0) { + // context()->throwError(tr("row/col index cannot be 0 or -ve!")); + return; + } else if (row > numRows()) { + // context()->throwError(tr("row index out of range!")); + return; + } else if (col > numCols()) { + // context()->throwError(tr("col index out of range!")); + return; } - setCellValue(context()->argument(0).toInt32() - 1, - context()->argument(1).toInt32() - 1, - context()->argument(2).toInt32()); + setCellValue(row - 1, col - 1, val); } -void Table::setRowCount() { - if (context()->argumentCount() != 1 || !context()->argument(0).isNumber()) { - context()->throwError(tr("setRowCount(intiger) take one argument!")); - } else if (context()->argument(0).toNumber() <= 0) { - context()->throwError(tr("cannot set row count to 0 or -ve!")); +void Table::setRowCount(int rows) { + if (rows <= 0) { + // context()->throwError(tr("cannot set row count to 0 or -ve!")); + return; } - setNumRows(context()->argument(0).toInt32()); + setNumRows(rows); } -void Table::setColCount() { - if (context()->argumentCount() != 1 || !context()->argument(0).isNumber()) { - context()->throwError(tr("setColCount(intiger) take one argument!")); - } else if (context()->argument(0).toNumber() <= 0) { - context()->throwError(tr("cannot set col count to 0 or -ve!")); +void Table::setColCount(int cols) { + if (cols <= 0) { + // context()->throwError(tr("cannot set col count to 0 or -ve!")); + return; } - setNumCols(context()->argument(0).toInt32()); + setNumCols(cols); } -void Table::applyFunction() { - if (context()->argumentCount() != 2 || !context()->argument(0).isNumber() || - !context()->argument(1).isString()) { - context()->throwError(tr("f(string) take one argument!")); - } - - selectColumn(context()->argument(0).toInt32() - 1); - for (int col = firstSelectedColumn(); col <= lastSelectedColumn(); col++) { - Column *col_ptr = column(context()->argument(0).toInt32() - 1); +void Table::applyFunction(int col, const QString &formula) { + selectColumn(col - 1); + for (int i = firstSelectedColumn(); i <= lastSelectedColumn(); i++) { + Column *col_ptr = column(col - 1); col_ptr->insertRows(col_ptr->rowCount(), numRows() - col_ptr->rowCount()); - col_ptr->setFormula(Interval(0, numRows() - 1), - context()->argument(1).toString()); - if (!recalculate(col, false)) break; + col_ptr->setFormula(Interval(0, numRows() - 1), formula); + if (!recalculate(i, false)) break; } } diff --git a/alphaplot/src/Table.h b/alphaplot/src/Table.h index 3819fcbc..050a81a2 100644 --- a/alphaplot/src/Table.h +++ b/alphaplot/src/Table.h @@ -14,7 +14,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include "MyWidget.h" @@ -49,8 +49,7 @@ */ class Table : public TableView, - public scripted, - public QScriptable { + public scripted { Q_OBJECT public: @@ -298,11 +297,11 @@ class Table : public TableView, public slots: int rowCount(); int colCount(); - double getCell(); - void setCell(); - void setRowCount(); - void setColCount(); - void applyFunction(); + double getCell(int row, int col); + void setCell(int row, int col, double val); + void setRowCount(int rows); + void setColCount(int cols); + void applyFunction(int col, const QString &formula); }; Q_DECLARE_METATYPE(Table*); diff --git a/alphaplot/src/TableStatistics.cpp b/alphaplot/src/TableStatistics.cpp index c5b41772..72352890 100644 --- a/alphaplot/src/TableStatistics.cpp +++ b/alphaplot/src/TableStatistics.cpp @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/TableStatistics.h b/alphaplot/src/TableStatistics.h index b8d79413..59e2fb07 100644 --- a/alphaplot/src/TableStatistics.h +++ b/alphaplot/src/TableStatistics.h @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/TeXTableExportDialog.cpp b/alphaplot/src/TeXTableExportDialog.cpp index 83732f8e..84211aad 100644 --- a/alphaplot/src/TeXTableExportDialog.cpp +++ b/alphaplot/src/TeXTableExportDialog.cpp @@ -29,6 +29,7 @@ #include "TeXTableSettings.h" #include "TeXTableSettingsWidget.h" #include "TeXTableExportDialog.h" +#include TeXTableExportDialog::TeXTableExportDialog(QWidget* parent) : ExtensibleFileDialog(parent) { diff --git a/alphaplot/src/TeXTableSettingsWidget.cpp b/alphaplot/src/TeXTableSettingsWidget.cpp index 7b7c4ab4..128cc310 100644 --- a/alphaplot/src/TeXTableSettingsWidget.cpp +++ b/alphaplot/src/TeXTableSettingsWidget.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include TeXTableSettingsWidget::TeXTableSettingsWidget(QWidget* parent) diff --git a/alphaplot/src/TextFormatButtons.cpp b/alphaplot/src/TextFormatButtons.cpp index d5e5483a..603fd165 100644 --- a/alphaplot/src/TextFormatButtons.cpp +++ b/alphaplot/src/TextFormatButtons.cpp @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -40,7 +40,7 @@ TextFormatButtons::TextFormatButtons(QTextEdit *textEdit, QWidget *parent) connectedTextEdit = textEdit; QHBoxLayout *layout = new QHBoxLayout(this); - layout->setMargin(0); + layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); layout->addStretch(); diff --git a/alphaplot/src/TextFormatButtons.h b/alphaplot/src/TextFormatButtons.h index 5c487223..89c66c97 100644 --- a/alphaplot/src/TextFormatButtons.h +++ b/alphaplot/src/TextFormatButtons.h @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/Convolution.cpp b/alphaplot/src/analysis/Convolution.cpp index 1d7a6657..be062913 100644 --- a/alphaplot/src/analysis/Convolution.cpp +++ b/alphaplot/src/analysis/Convolution.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/Convolution.h b/alphaplot/src/analysis/Convolution.h index 7bc6738f..7993e732 100644 --- a/alphaplot/src/analysis/Convolution.h +++ b/alphaplot/src/analysis/Convolution.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/Correlation.cpp b/alphaplot/src/analysis/Correlation.cpp index d5e5cf57..da20c58f 100644 --- a/alphaplot/src/analysis/Correlation.cpp +++ b/alphaplot/src/analysis/Correlation.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/Correlation.h b/alphaplot/src/analysis/Correlation.h index cc5a35b2..5e93e172 100644 --- a/alphaplot/src/analysis/Correlation.h +++ b/alphaplot/src/analysis/Correlation.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/Differentiation.cpp b/alphaplot/src/analysis/Differentiation.cpp index 8c1a5318..0e206d28 100644 --- a/alphaplot/src/analysis/Differentiation.cpp +++ b/alphaplot/src/analysis/Differentiation.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/Differentiation.h b/alphaplot/src/analysis/Differentiation.h index e8de6128..6610440f 100644 --- a/alphaplot/src/analysis/Differentiation.h +++ b/alphaplot/src/analysis/Differentiation.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/ExpDecayDialog.cpp b/alphaplot/src/analysis/ExpDecayDialog.cpp index de7cff31..2d635d25 100644 --- a/alphaplot/src/analysis/ExpDecayDialog.cpp +++ b/alphaplot/src/analysis/ExpDecayDialog.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -56,7 +56,11 @@ ExpDecayDialog::ExpDecayDialog(int type, QWidget *parent, Qt::WindowFlags fl) gl1->addWidget(new QLabel(tr("Exponential Fit of")), 0, 0); boxName = new QComboBox(); +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + connect(boxName, SIGNAL(textActivated(const QString &)), this, +#else connect(boxName, SIGNAL(activated(const QString &)), this, +#endif SLOT(activateCurve(const QString &))); gl1->addWidget(boxName, 0, 1); diff --git a/alphaplot/src/analysis/ExpDecayDialog.h b/alphaplot/src/analysis/ExpDecayDialog.h index 27088f10..262bbdad 100644 --- a/alphaplot/src/analysis/ExpDecayDialog.h +++ b/alphaplot/src/analysis/ExpDecayDialog.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/ExponentialFit.cpp b/alphaplot/src/analysis/ExponentialFit.cpp index e63d143f..b9326378 100644 --- a/alphaplot/src/analysis/ExponentialFit.cpp +++ b/alphaplot/src/analysis/ExponentialFit.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/ExponentialFit.h b/alphaplot/src/analysis/ExponentialFit.h index 123b31da..14a0bf90 100644 --- a/alphaplot/src/analysis/ExponentialFit.h +++ b/alphaplot/src/analysis/ExponentialFit.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/FFT.cpp b/alphaplot/src/analysis/FFT.cpp index 8f50f015..086de6e4 100644 --- a/alphaplot/src/analysis/FFT.cpp +++ b/alphaplot/src/analysis/FFT.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/FFT.h b/alphaplot/src/analysis/FFT.h index 63850766..47e7d7e0 100644 --- a/alphaplot/src/analysis/FFT.h +++ b/alphaplot/src/analysis/FFT.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/FFTDialog.cpp b/alphaplot/src/analysis/FFTDialog.cpp index 0afd87cb..33e614e7 100644 --- a/alphaplot/src/analysis/FFTDialog.cpp +++ b/alphaplot/src/analysis/FFTDialog.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/FFTDialog.h b/alphaplot/src/analysis/FFTDialog.h index 1747fccc..6d09e750 100644 --- a/alphaplot/src/analysis/FFTDialog.h +++ b/alphaplot/src/analysis/FFTDialog.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/FFTFilter.cpp b/alphaplot/src/analysis/FFTFilter.cpp index 48f5d506..f2fa2cbe 100644 --- a/alphaplot/src/analysis/FFTFilter.cpp +++ b/alphaplot/src/analysis/FFTFilter.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/FFTFilter.h b/alphaplot/src/analysis/FFTFilter.h index d9b0ccd5..65cd47be 100644 --- a/alphaplot/src/analysis/FFTFilter.h +++ b/alphaplot/src/analysis/FFTFilter.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/Filter.cpp b/alphaplot/src/analysis/Filter.cpp index 9b64780b..89c9f6aa 100644 --- a/alphaplot/src/analysis/Filter.cpp +++ b/alphaplot/src/analysis/Filter.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/Filter.h b/alphaplot/src/analysis/Filter.h index 548935ca..857deae6 100644 --- a/alphaplot/src/analysis/Filter.h +++ b/alphaplot/src/analysis/Filter.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/FilterDialog.cpp b/alphaplot/src/analysis/FilterDialog.cpp index 9761b2bb..41931b60 100644 --- a/alphaplot/src/analysis/FilterDialog.cpp +++ b/alphaplot/src/analysis/FilterDialog.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/FilterDialog.h b/alphaplot/src/analysis/FilterDialog.h index a27f5ab8..1df14f53 100644 --- a/alphaplot/src/analysis/FilterDialog.h +++ b/alphaplot/src/analysis/FilterDialog.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/Fit.cpp b/alphaplot/src/analysis/Fit.cpp index e016d3f8..4e948b84 100644 --- a/alphaplot/src/analysis/Fit.cpp +++ b/alphaplot/src/analysis/Fit.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -222,7 +222,7 @@ void Fit::generateFunction(bool yes, int points) { QString Fit::logFitInfo(const std::vector &par, int iterations, int status, const QString &plotName) { QDateTime dt = QDateTime::currentDateTime(); - QString info = "[" + dt.toString(Qt::LocalDate) + " " + tr("Plot") + + QString info = "[" + QLocale().toString(dt, QLocale::ShortFormat) + " " + tr("Plot") + ": ''" + plotName + "'']
"; info += d_explanation + " " + tr("fit of dataset") + ":
" + "Table: " + associateddata_->table->name() + "
" + diff --git a/alphaplot/src/analysis/Fit.h b/alphaplot/src/analysis/Fit.h index 6ec5e8f8..169b24d7 100644 --- a/alphaplot/src/analysis/Fit.h +++ b/alphaplot/src/analysis/Fit.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/FitDialog.cpp b/alphaplot/src/analysis/FitDialog.cpp index 930d47e7..0440371c 100644 --- a/alphaplot/src/analysis/FitDialog.cpp +++ b/alphaplot/src/analysis/FitDialog.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -216,7 +216,11 @@ void FitDialog::initFitPage() { fitPage->setLayout(vbox1); tw->addWidget(fitPage); +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + connect(boxCurve, SIGNAL(textActivated(const QString &)), this, +#else connect(boxCurve, SIGNAL(activated(const QString &)), this, +#endif SLOT(activateCurve(const QString &))); connect(buttonOk, SIGNAL(clicked()), this, SLOT(accept())); connect(buttonCancel1, SIGNAL(clicked()), this, SLOT(close())); @@ -554,7 +558,7 @@ void FitDialog::saveUserFunction() { tr("Please enter a function name!")); boxName->setFocus(); return; - } else if (boxParam->text().remove(QRegExp("[,;\\s]")).isEmpty()) { + } else if (boxParam->text().remove(QRegularExpression("[,;\\s]")).isEmpty()) { QMessageBox::critical(this, tr("Input function error"), tr("Please enter at least one parameter name!")); boxParam->setFocus(); @@ -638,7 +642,7 @@ void FitDialog::showFitPage() { QString par = boxParam->text().simplified(); QStringList paramList = - par.split(QRegExp("[,;]+[\\s]*"), QString::SkipEmptyParts); + par.split(QRegularExpression("[,;]+[\\s]*"), Qt::SkipEmptyParts); int parameters = paramList.count(); boxParams->setRowCount(parameters); boxParams->hideColumn(2); @@ -1269,7 +1273,7 @@ void FitDialog::setSrcTables(QList *tables) { tableNamesBox->addItem(i->objectName()); tableNamesBox->setCurrentIndex(tableNamesBox->findText( - boxCurve->currentText().split("_", QString::SkipEmptyParts)[0])); + boxCurve->currentText().split("_", Qt::SkipEmptyParts)[0])); selectSrcTable(tableNamesBox->currentIndex()); } diff --git a/alphaplot/src/analysis/FitDialog.h b/alphaplot/src/analysis/FitDialog.h index f8d0eb27..e991da7d 100644 --- a/alphaplot/src/analysis/FitDialog.h +++ b/alphaplot/src/analysis/FitDialog.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/IntDialog.cpp b/alphaplot/src/analysis/IntDialog.cpp index 4c563c9c..f2794ac7 100644 --- a/alphaplot/src/analysis/IntDialog.cpp +++ b/alphaplot/src/analysis/IntDialog.cpp @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -90,7 +90,11 @@ IntDialog::IntDialog(QWidget *parent, Qt::WindowFlags fl) connect(buttonOk, SIGNAL(clicked()), this, SLOT(accept())); connect(buttonCancel, SIGNAL(clicked()), this, SLOT(reject())); connect(buttonHelp, SIGNAL(clicked()), this, SLOT(help())); +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + connect(boxName, SIGNAL(textActivated(const QString &)), this, +#else connect(boxName, SIGNAL(activated(const QString &)), this, +#endif SLOT(activateCurve(const QString &))); } diff --git a/alphaplot/src/analysis/IntDialog.h b/alphaplot/src/analysis/IntDialog.h index bcdf364a..8d5c4b8f 100644 --- a/alphaplot/src/analysis/IntDialog.h +++ b/alphaplot/src/analysis/IntDialog.h @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/Integration.cpp b/alphaplot/src/analysis/Integration.cpp index 046b919c..14c8fadb 100644 --- a/alphaplot/src/analysis/Integration.cpp +++ b/alphaplot/src/analysis/Integration.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -134,7 +134,7 @@ QString Integration::logInfo() { associateddata_->xcol->name() + "_" + associateddata_->ycol->name(); QString logInfo = "[" + - QDateTime::currentDateTime().toString(Qt::LocalDate) + + QLocale().toString(QDateTime::currentDateTime(), QLocale::ShortFormat) + " " + tr("Plot") + ": ''" + curvename + "'']
"; logInfo += tr("Numerical integration of") + ": " + curvename + tr(" using ") + method_name + tr("Interpolation") + ":
" + diff --git a/alphaplot/src/analysis/Integration.h b/alphaplot/src/analysis/Integration.h index 66932f02..e28e1f42 100644 --- a/alphaplot/src/analysis/Integration.h +++ b/alphaplot/src/analysis/Integration.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/InterpolationDialog.cpp b/alphaplot/src/analysis/InterpolationDialog.cpp index 5ee907db..f6551d51 100644 --- a/alphaplot/src/analysis/InterpolationDialog.cpp +++ b/alphaplot/src/analysis/InterpolationDialog.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -105,7 +105,11 @@ InterpolationDialog::InterpolationDialog(QWidget *parent, Qt::WindowFlags fl) hb->addWidget(gb1); hb->addLayout(vl); +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + connect(boxName, SIGNAL(textActivated(const QString &)), this, +#else connect(boxName, SIGNAL(activated(const QString &)), this, +#endif SLOT(activateCurve(const QString &))); connect(buttonFit, SIGNAL(clicked()), this, SLOT(interpolate())); connect(buttonCancel, SIGNAL(clicked()), this, SLOT(reject())); diff --git a/alphaplot/src/analysis/InterpolationDialog.h b/alphaplot/src/analysis/InterpolationDialog.h index 13e82842..0b15a093 100644 --- a/alphaplot/src/analysis/InterpolationDialog.h +++ b/alphaplot/src/analysis/InterpolationDialog.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/MultiPeakFit.cpp b/alphaplot/src/analysis/MultiPeakFit.cpp index 897e33bf..af201ff7 100644 --- a/alphaplot/src/analysis/MultiPeakFit.cpp +++ b/alphaplot/src/analysis/MultiPeakFit.cpp @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/MultiPeakFit.h b/alphaplot/src/analysis/MultiPeakFit.h index c950e490..cd369622 100644 --- a/alphaplot/src/analysis/MultiPeakFit.h +++ b/alphaplot/src/analysis/MultiPeakFit.h @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/MultiPeakFitTool.cpp b/alphaplot/src/analysis/MultiPeakFitTool.cpp index cf6623fa..92159f69 100644 --- a/alphaplot/src/analysis/MultiPeakFitTool.cpp +++ b/alphaplot/src/analysis/MultiPeakFitTool.cpp @@ -14,7 +14,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/MultiPeakFitTool.h b/alphaplot/src/analysis/MultiPeakFitTool.h index a09fc84f..658b00b5 100644 --- a/alphaplot/src/analysis/MultiPeakFitTool.h +++ b/alphaplot/src/analysis/MultiPeakFitTool.h @@ -14,7 +14,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/NonLinearFit.cpp b/alphaplot/src/analysis/NonLinearFit.cpp index 46cb1681..cae93dd5 100644 --- a/alphaplot/src/analysis/NonLinearFit.cpp +++ b/alphaplot/src/analysis/NonLinearFit.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/NonLinearFit.h b/alphaplot/src/analysis/NonLinearFit.h index 7d5c1d14..ca3044e4 100644 --- a/alphaplot/src/analysis/NonLinearFit.h +++ b/alphaplot/src/analysis/NonLinearFit.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/PluginFit.cpp b/alphaplot/src/analysis/PluginFit.cpp index 9dbde6c6..be34f41d 100644 --- a/alphaplot/src/analysis/PluginFit.cpp +++ b/alphaplot/src/analysis/PluginFit.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -107,7 +107,7 @@ bool PluginFit::load(const QString &pluginName) { typedef char *(*fitFunc)(); fitFunc fitFunction = (fitFunc)lib.resolve("parameters"); if (fitFunction) { - d_param_names = QString(fitFunction()).split(",", QString::SkipEmptyParts); + d_param_names = QString(fitFunction()).split(",", Qt::SkipEmptyParts); d_p = d_param_names.count(); d_min_points = d_p; d_param_init = gsl_vector_alloc(static_cast(d_p)); @@ -119,7 +119,7 @@ bool PluginFit::load(const QString &pluginName) { fitFunc fitExplain = (fitFunc)lib.resolve("explanations"); if (fitExplain) - d_param_explain = QString(fitExplain()).split(",", QString::SkipEmptyParts); + d_param_explain = QString(fitExplain()).split(",", Qt::SkipEmptyParts); else for (int i = 0; i < d_p; i++) d_param_explain << ""; diff --git a/alphaplot/src/analysis/PluginFit.h b/alphaplot/src/analysis/PluginFit.h index 91fe261c..f2283c9e 100644 --- a/alphaplot/src/analysis/PluginFit.h +++ b/alphaplot/src/analysis/PluginFit.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/PolynomFitDialog.cpp b/alphaplot/src/analysis/PolynomFitDialog.cpp index 795212e5..b52dab19 100644 --- a/alphaplot/src/analysis/PolynomFitDialog.cpp +++ b/alphaplot/src/analysis/PolynomFitDialog.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -98,7 +98,11 @@ PolynomFitDialog::PolynomFitDialog(QWidget *parent, Qt::WindowFlags fl) connect(buttonFit, &QPushButton::clicked, this, &PolynomFitDialog::fit); connect(buttonCancel, &QPushButton::clicked, this, &PolynomFitDialog::reject); +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + connect(boxName, SIGNAL(textActivated(const QString &)), this, +#else connect(boxName, SIGNAL(activated(const QString &)), this, +#endif SLOT(activateCurve(const QString &))); } diff --git a/alphaplot/src/analysis/PolynomFitDialog.h b/alphaplot/src/analysis/PolynomFitDialog.h index f92f1773..55c8e470 100644 --- a/alphaplot/src/analysis/PolynomFitDialog.h +++ b/alphaplot/src/analysis/PolynomFitDialog.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/PolynomialFit.cpp b/alphaplot/src/analysis/PolynomialFit.cpp index dc863c29..3f50910f 100644 --- a/alphaplot/src/analysis/PolynomialFit.cpp +++ b/alphaplot/src/analysis/PolynomialFit.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -172,8 +172,7 @@ QString PolynomialFit::legendInfo() { double cj = d_results[j]; if (cj > 0 && !legend.isEmpty()) legend += "+"; - QString s; - s.sprintf("%.5f", cj); + QString s = QString::asprintf("%.5f", cj); if (s != "1.00000") legend += QLocale().toString(cj, 'g', d_prec); legend += "X"; diff --git a/alphaplot/src/analysis/PolynomialFit.h b/alphaplot/src/analysis/PolynomialFit.h index 0a7e42d1..3428c1f0 100644 --- a/alphaplot/src/analysis/PolynomialFit.h +++ b/alphaplot/src/analysis/PolynomialFit.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/SigmoidalFit.cpp b/alphaplot/src/analysis/SigmoidalFit.cpp index ea6cfd82..0deb8c31 100644 --- a/alphaplot/src/analysis/SigmoidalFit.cpp +++ b/alphaplot/src/analysis/SigmoidalFit.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/SigmoidalFit.h b/alphaplot/src/analysis/SigmoidalFit.h index 81dabf6d..c557fcfd 100644 --- a/alphaplot/src/analysis/SigmoidalFit.h +++ b/alphaplot/src/analysis/SigmoidalFit.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/SmoothCurveDialog.cpp b/alphaplot/src/analysis/SmoothCurveDialog.cpp index b9cd1c52..fa3ad8d2 100644 --- a/alphaplot/src/analysis/SmoothCurveDialog.cpp +++ b/alphaplot/src/analysis/SmoothCurveDialog.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -112,7 +112,11 @@ SmoothCurveDialog::SmoothCurveDialog(int method, QWidget *parent, connect(btnSmooth, SIGNAL(clicked()), this, SLOT(smooth())); connect(buttonCancel, SIGNAL(clicked()), this, SLOT(reject())); +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + connect(boxName, SIGNAL(textActivated(const QString &)), this, +#else connect(boxName, SIGNAL(activated(const QString &)), this, +#endif SLOT(activateCurve(const QString &))); } diff --git a/alphaplot/src/analysis/SmoothCurveDialog.h b/alphaplot/src/analysis/SmoothCurveDialog.h index cfd95eab..2393dc56 100644 --- a/alphaplot/src/analysis/SmoothCurveDialog.h +++ b/alphaplot/src/analysis/SmoothCurveDialog.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/SmoothFilter.cpp b/alphaplot/src/analysis/SmoothFilter.cpp index 005b0e53..7c3d3561 100644 --- a/alphaplot/src/analysis/SmoothFilter.cpp +++ b/alphaplot/src/analysis/SmoothFilter.cpp @@ -14,7 +14,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -345,7 +346,7 @@ void SmoothFilter::smoothSavGol(double *, double *y_inout) { gsl_matrix_free(h); // write result into *y_inout - qCopy(result.begin(), result.end(), y_inout); + std::copy(result.begin(), result.end(), y_inout); } /** @@ -436,7 +437,7 @@ void SmoothFilter::smoothModifiedSavGol(double *x_in, double *y_inout) { gsl_matrix_free(vandermonde); // write result into *y_inout - qCopy(result.begin(), result.end(), y_inout); + std::copy(result.begin(), result.end(), y_inout); } void SmoothFilter::setSmoothPoints(int points, int left_points) { diff --git a/alphaplot/src/analysis/SmoothFilter.h b/alphaplot/src/analysis/SmoothFilter.h index 034bc367..e0002c8e 100644 --- a/alphaplot/src/analysis/SmoothFilter.h +++ b/alphaplot/src/analysis/SmoothFilter.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/analysis/fit_gsl.cpp b/alphaplot/src/analysis/fit_gsl.cpp index 31130aec..c5e13261 100644 --- a/alphaplot/src/analysis/fit_gsl.cpp +++ b/alphaplot/src/analysis/fit_gsl.cpp @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * As a special exception, you may omit the above copyright notice when * diff --git a/alphaplot/src/analysis/fit_gsl.h b/alphaplot/src/analysis/fit_gsl.h index c7489190..e80bf1e4 100644 --- a/alphaplot/src/analysis/fit_gsl.h +++ b/alphaplot/src/analysis/fit_gsl.h @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * As a special exception, you may omit the above copyright notice when * diff --git a/alphaplot/src/core/AprojHandler.cpp b/alphaplot/src/core/AprojHandler.cpp index 0b228a60..4fe862e6 100644 --- a/alphaplot/src/core/AprojHandler.cpp +++ b/alphaplot/src/core/AprojHandler.cpp @@ -369,10 +369,10 @@ Folder *AprojHandler::readxmlstream(ApplicationWindow *app, QFile *file, if (ok) { table->setBirthDate( QDateTime::fromString(time, "yyyy-dd-MM hh:mm:ss:zzz") - .toString(Qt::LocalDate)); + .toString(Qt::ISODate)); // Using ISODate instead of LocalDate for proj files if appropriate, or QLocale().toString() } else { table->setBirthDate( - QDateTime::currentDateTime().toString(Qt::LocalDate)); + QLocale().toString(QDateTime::currentDateTime(), QLocale::ShortFormat)); xmlreader->raiseWarning( tr("Invalid creation time. Using current time insted.")); } @@ -481,8 +481,6 @@ bool AprojHandler::saveproject(const QString &filename, Folder *folder) { std::unique_ptr(new XmlStreamWriter(bytearray.get())); } - xmlwriter->setCodec("UTF-8"); - xmlwriter->setAutoFormatting(false); Folder *root = folder; xmlwriter->writeStartDocument(); @@ -576,7 +574,6 @@ bool AprojHandler::saveTemplate(const QString &filename, MyWidget *mywidget) { } std::unique_ptr xmlwriter = std::unique_ptr(new XmlStreamWriter(file.get())); - xmlwriter->setCodec("UTF-8"); xmlwriter->setAutoFormatting(false); xmlwriter->writeStartDocument(); diff --git a/alphaplot/src/core/Utilities.cpp b/alphaplot/src/core/Utilities.cpp index bc0390b1..e9da7367 100644 --- a/alphaplot/src/core/Utilities.cpp +++ b/alphaplot/src/core/Utilities.cpp @@ -47,74 +47,7 @@ int Utilities::getWordSizeApp() { #endif } -QString Utilities::getOperatingSystem() { -#if defined(Q_OS_WIN32) - switch (QSysInfo::windowsVersion()) { - case QSysInfo::WV_NT: - return QString("Windows NT"); - case QSysInfo::WV_2000: - return QString("Windows 2000"); - case QSysInfo::WV_XP: - return QString("Windows XP"); - case QSysInfo::WV_2003: - return QString("Windows Server 2003"); - case QSysInfo::WV_VISTA: - return QString("Windows Vista"); - case QSysInfo::WV_WINDOWS7: - return QString("Windows 7"); - case QSysInfo::WV_WINDOWS8: - return QString("Windows 8"); - case QSysInfo::WV_WINDOWS8_1: - return QString("Windows 8.1"); - case QSysInfo::WV_WINDOWS10: - return QString("Windows 10"); - default: - return QString("Windows"); - } -#elif defined(Q_OS_MAC) - switch (QSysInfo::MacVersion()) { - case QSysInfo::MV_10_3: - return QString("Mac OS X 10.3"); - case QSysInfo::MV_10_4: - return QString("Mac OS X 10.4"); - case QSysInfo::MV_10_5: - return QString("Mac OS X 10.5"); - case QSysInfo::MV_10_6: - return QString("Mac OS X 10.6"); - case QSysInfo::MV_10_7: - return QString("Mac OS X 10.7"); - case QSysInfo::MV_10_8: - return QString("Mac OS X 10.8"); - case QSysInfo::MV_10_9: - return QString("Mac OS X 10.9"); - case QSysInfo::MV_10_10: - return QString("Mac OS X 10.10"); - // case QSysInfo::MV_10_11: (mot available in qt4) - // return QString("Mac OS X 10.11"); - default: - return QString("Mac OS X"); - } -#elif defined(Q_OS_LINUX) - QString exe("lsb_release"); - QStringList args; - args << "-ds"; - QProcess proc; - proc.setEnvironment(QProcess::systemEnvironment()); - proc.start(exe, args); - if (proc.waitForStarted() && proc.waitForFinished()) { - QByteArray info = proc.readAll(); - info.replace('\n', ""); - info.replace("\"", ""); - return QString(info); - } - - return QString("Linux"); -#elif defined(Q_OS_UNIX) - return QString("UNIX"); -#else - return QString("Unknown"); -#endif -} +QString Utilities::getOperatingSystem() { return QSysInfo::prettyProductName(); } int Utilities::getWordSizeOfOS() { #if defined(Q_OS_WIN64) diff --git a/alphaplot/src/core/Utilities.h b/alphaplot/src/core/Utilities.h index e9ce2be7..d908d12b 100644 --- a/alphaplot/src/core/Utilities.h +++ b/alphaplot/src/core/Utilities.h @@ -19,6 +19,7 @@ #include #include #include +#include class Utilities { public: diff --git a/alphaplot/src/core/propertybrowser/CustomWidgets.cpp b/alphaplot/src/core/propertybrowser/CustomWidgets.cpp index ac6ec642..51bcfbfc 100644 --- a/alphaplot/src/core/propertybrowser/CustomWidgets.cpp +++ b/alphaplot/src/core/propertybrowser/CustomWidgets.cpp @@ -81,7 +81,7 @@ void FontWidget::setValue(const QFont &value) { void FontWidget::paintEvent(QPaintEvent *) { QStyleOption opt; - opt.init(this); + opt.initFrom(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } @@ -222,7 +222,7 @@ QString ColorWidget::colorValueText(const QColor &c) { void ColorWidget::paintEvent(QPaintEvent *) { QStyleOption opt; - opt.init(this); + opt.initFrom(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } diff --git a/alphaplot/src/core/propertybrowser/ObjectBrowserTreeItemModel.cpp b/alphaplot/src/core/propertybrowser/ObjectBrowserTreeItemModel.cpp index 4b8f3f7c..aff4bd13 100644 --- a/alphaplot/src/core/propertybrowser/ObjectBrowserTreeItemModel.cpp +++ b/alphaplot/src/core/propertybrowser/ObjectBrowserTreeItemModel.cpp @@ -186,6 +186,7 @@ bool ObjectBrowserTreeItemModel::setHeaderData(int section, const QVariant &value, int role) { emit headerDataChanged(orientation, section, section); + return true; } void ObjectBrowserTreeItemModel::buildUpNone() { diff --git a/alphaplot/src/core/propertybrowser/PropertyItem.cpp b/alphaplot/src/core/propertybrowser/PropertyItem.cpp index 3f5b254f..248b723d 100644 --- a/alphaplot/src/core/propertybrowser/PropertyItem.cpp +++ b/alphaplot/src/core/propertybrowser/PropertyItem.cpp @@ -30,6 +30,7 @@ #include "3Dplot/Layout3D.h" #include "3Dplot/Scatter3D.h" #include "3Dplot/Surface3D.h" +#include "3Dplot/DataManager3D.h" #include "ApplicationWindow.h" #include "CustomWidgets.h" #include "Matrix.h" @@ -136,6 +137,13 @@ PropertyItem::PropertyItem(PropertyItem *parent, ObjectBrowserTreeItem *item, case PropertyItem::Property::Plot3DAxisVal_Label_Separator: case PropertyItem::Property::Plot3DAxisCat_Base_Separator: case PropertyItem::Property::Plot3DAxisCat_Label_Separator: + case PropertyItem::Property::Plot3DScatter_Base_Separator: + case PropertyItem::Property::Plot3DScatterDB_Base_Separator: + case PropertyItem::Property::Plot3DBar_Base_Separator: + case PropertyItem::Property::Plot3DBar_Spacing_Separator: + case PropertyItem::Property::Plot3DBarDB_Base_Separator: + case PropertyItem::Property::Plot3DSurface_Base_Separator: + case PropertyItem::Property::Plot3DSurfaceDB_Base_Separator: propertytype_ = PropertyItem::PropertyType::Separator; break; case PropertyItem::Property::None: @@ -297,6 +305,16 @@ PropertyItem::PropertyItem(PropertyItem *parent, ObjectBrowserTreeItem *item, case PropertyItem::Property::Plot3DAxisCat_TickLabel_Rotation: case PropertyItem::Property::Plot3DAxisCat_From: case PropertyItem::Property::Plot3DAxisCat_To: + case PropertyItem::Property::Plot3DScatter_AspectRatio: + case PropertyItem::Property::Plot3DScatter_HorizontalAspectRatio: + case PropertyItem::Property::Plot3DScatterDB_Size: + case PropertyItem::Property::Plot3DBar_AspectRatio: + case PropertyItem::Property::Plot3DBar_HorizontalAspectRatio: + case PropertyItem::Property::Plot3DBar_SpacingX: + case PropertyItem::Property::Plot3DBar_SpacingY: + case PropertyItem::Property::Plot3DBar_Thickness: + case PropertyItem::Property::Plot3DSurface_AspectRatio: + case PropertyItem::Property::Plot3DSurface_HorizontalAspectRatio: propertytype_ = PropertyItem::PropertyType::Double; break; case PropertyItem::Property::Plot2DAxis_From_Double: @@ -373,6 +391,21 @@ PropertyItem::PropertyItem(PropertyItem *parent, ObjectBrowserTreeItem *item, case PropertyItem::Property::Plot3DAxisCat_Inverted: case PropertyItem::Property::Plot3DAxisCat_Label_Visible: case PropertyItem::Property::Plot3DAxisCat_Label_Fixed: + case PropertyItem::Property::Plot3DScatter_OrthoProjection: + case PropertyItem::Property::Plot3DScatter_Polar: + case PropertyItem::Property::Plot3DScatterDB_Visible: + case PropertyItem::Property::Plot3DScatterDB_MeshSmooth: + case PropertyItem::Property::Plot3DBar_OrthoProjection: + case PropertyItem::Property::Plot3DBar_Polar: + case PropertyItem::Property::Plot3DBar_RelativeSpacing: + case PropertyItem::Property::Plot3DBarDB_Visible: + case PropertyItem::Property::Plot3DBarDB_MeshSmooth: + case PropertyItem::Property::Plot3DSurface_FlipHorizontalGrid: + case PropertyItem::Property::Plot3DSurface_OrthoProjection: + case PropertyItem::Property::Plot3DSurface_Polar: + case PropertyItem::Property::Plot3DSurfaceDB_Visible: + case PropertyItem::Property::Plot3DSurfaceDB_FlatShading: + case PropertyItem::Property::Plot3DSurfaceDB_MeshSmooth: propertytype_ = PropertyItem::PropertyType::Bool; break; case PropertyItem::Property::Plot2DLayout_FillStyle: @@ -466,6 +499,16 @@ PropertyItem::PropertyItem(PropertyItem *parent, ObjectBrowserTreeItem *item, case PropertyItem::Property::Plot2DErrBar_Stroke_Style: case PropertyItem::Property::Plot2DErrBar_Fill_Style: case PropertyItem::Property::Plot3DCanvas_Theme: + case PropertyItem::Property::Plot3DScatter_ShadowQuality: + case PropertyItem::Property::Plot3DScatterDB_ColorStyle: + case PropertyItem::Property::Plot3DScatterDB_GradientColor: + case PropertyItem::Property::Plot3DBar_ShadowQuality: + case PropertyItem::Property::Plot3DBarDB_ColorStyle: + case PropertyItem::Property::Plot3DBarDB_GradientColor: + case PropertyItem::Property::Plot3DSurface_ShadowQuality: + case PropertyItem::Property::Plot3DSurfaceDB_DrawMode: + case PropertyItem::Property::Plot3DSurfaceDB_ColorStyle: + case PropertyItem::Property::Plot3DSurfaceDB_GradientColor: propertytype_ = PropertyItem::PropertyType::Enum; break; case PropertyItem::Property::Plot2DCanvas_Background: @@ -529,6 +572,12 @@ PropertyItem::PropertyItem(PropertyItem *parent, ObjectBrowserTreeItem *item, case PropertyItem::Property::Plot3DTheme_Grid_Color: case PropertyItem::Property::Plot3DTheme_Label_Background_Color: case PropertyItem::Property::Plot3DTheme_Label_Color: + case PropertyItem::Property::Plot3DScatterDB_SolidColor: + case PropertyItem::Property::Plot3DScatterDB_HighlightColor: + case PropertyItem::Property::Plot3DBarDB_SolidColor: + case PropertyItem::Property::Plot3DBarDB_HighlightColor: + case PropertyItem::Property::Plot3DSurfaceDB_SolidColor: + case PropertyItem::Property::Plot3DSurfaceDB_HighlightColor: propertytype_ = PropertyItem::PropertyType::Color; break; case PropertyItem::Property::Plot2DLegend_Font: @@ -2806,7 +2855,282 @@ PropertyItem::Pair PropertyItem::value() const { break; } } break; + // Plot3D Axis Value (QValue3DAxis) + case ObjectBrowserTreeItem::ObjectType::Plot3DAxisValue: { + QValue3DAxis *axis = item_->getObjectTreeItem(&status); + if (!status) break; + switch (property_) { + case PropertyItem::Property::Plot3DAxisVal_Base_Separator: + return Pair(tr("Base"), QString()); + break; + case PropertyItem::Property::Plot3DAxisVal_AutoRange: + return Pair(tr("Auto Range"), axis->isAutoAdjustRange()); + break; + case PropertyItem::Property::Plot3DAxisVal_From: + return Pair(tr("From"), static_cast(axis->min())); + break; + case PropertyItem::Property::Plot3DAxisVal_To: + return Pair(tr("To"), static_cast(axis->max())); + break; + case PropertyItem::Property::Plot3DAxisVal_Inverted: + return Pair(tr("Inverted"), axis->reversed()); + break; + case PropertyItem::Property::Plot3DAxisVal_Tick_Count: + return Pair(tr("Tick Count"), axis->segmentCount()); + break; + case PropertyItem::Property::Plot3DAxisVal_SubTick_Count: + return Pair(tr("Sub-Tick Count"), axis->subSegmentCount()); + break; + case PropertyItem::Property::Plot3DAxisVal_Tick_Separator: + return Pair(tr("Tick Label"), QString()); + break; + case PropertyItem::Property::Plot3DAxisVal_TickLabel_Format: + return Pair(tr("Format"), axis->labelFormat()); + break; + case PropertyItem::Property::Plot3DAxisVal_TickLabel_Rotation: + return Pair(tr("Rotation"), + static_cast(axis->labelAutoRotation())); + break; + case PropertyItem::Property::Plot3DAxisVal_Label_Separator: + return Pair(tr("Title"), QString()); + break; + case PropertyItem::Property::Plot3DAxisVal_Label_Visible: + return Pair(tr("Title Visible"), axis->isTitleVisible()); + break; + case PropertyItem::Property::Plot3DAxisVal_Label_Fixed: + return Pair(tr("Title Fixed"), axis->isTitleFixed()); + break; + case PropertyItem::Property::Plot3DAxisVal_Label_Text: + return Pair(tr("Title Text"), axis->title()); + break; + default: + break; + } + } break; + // Plot3D Axis Category (QCategory3DAxis) + case ObjectBrowserTreeItem::ObjectType::Plot3DAxisCatagory: { + QCategory3DAxis *axis = + item_->getObjectTreeItem(&status); + if (!status) break; + switch (property_) { + case PropertyItem::Property::Plot3DAxisCat_Base_Separator: + return Pair(tr("Base"), QString()); + break; + case PropertyItem::Property::Plot3DAxisCat_AutoRange: + return Pair(tr("Auto Range"), axis->isAutoAdjustRange()); + break; + case PropertyItem::Property::Plot3DAxisCat_From: + return Pair(tr("From"), static_cast(axis->min())); + break; + case PropertyItem::Property::Plot3DAxisCat_To: + return Pair(tr("To"), static_cast(axis->max())); + break; + case PropertyItem::Property::Plot3DAxisCat_TickLabel_Rotation: + return Pair(tr("Rotation"), + static_cast(axis->labelAutoRotation())); + break; + case PropertyItem::Property::Plot3DAxisCat_Label_Separator: + return Pair(tr("Title"), QString()); + break; + case PropertyItem::Property::Plot3DAxisCat_Label_Visible: + return Pair(tr("Title Visible"), axis->isTitleVisible()); + break; + case PropertyItem::Property::Plot3DAxisCat_Label_Fixed: + return Pair(tr("Title Fixed"), axis->isTitleFixed()); + break; + case PropertyItem::Property::Plot3DAxisCat_Label_Text: + return Pair(tr("Title Text"), axis->title()); + break; + default: + break; + } + } break; + // Plot3D Scatter + case ObjectBrowserTreeItem::ObjectType::Plot3DScatter: { + Scatter3D *scatter = item_->getObjectTreeItem(&status); + if (!status) break; + QAbstract3DGraph *graph = scatter->getGraph(); + switch (property_) { + case PropertyItem::Property::Plot3DScatter_Base_Separator: + return Pair(tr("Scatter"), QString()); + case PropertyItem::Property::Plot3DScatter_AspectRatio: + return Pair(tr("Aspect Ratio"), + static_cast(graph->aspectRatio())); + case PropertyItem::Property::Plot3DScatter_HorizontalAspectRatio: + return Pair(tr("Horizontal Aspect Ratio"), + static_cast(graph->horizontalAspectRatio())); + case PropertyItem::Property::Plot3DScatter_ShadowQuality: + return Pair(tr("Shadow Quality"), + static_cast(graph->shadowQuality())); + case PropertyItem::Property::Plot3DScatter_OrthoProjection: + return Pair(tr("Ortho Projection"), graph->isOrthoProjection()); + case PropertyItem::Property::Plot3DScatter_Polar: + return Pair(tr("Polar Coords"), graph->isPolar()); + default: + break; + } + } break; + // Plot3D Scatter DataBlock + case ObjectBrowserTreeItem::ObjectType::Plot3DScatterDataBlock: { + DataBlockScatter3D *block = + item_->getObjectTreeItem(&status); + if (!status) break; + QScatter3DSeries *series = block->getdataseries(); + switch (property_) { + case PropertyItem::Property::Plot3DScatterDB_Base_Separator: + return Pair(tr("Series"), QString()); + case PropertyItem::Property::Plot3DScatterDB_Visible: + return Pair(tr("Visible"), series->isVisible()); + case PropertyItem::Property::Plot3DScatterDB_Size: + return Pair(tr("Size"), static_cast(series->itemSize())); + case PropertyItem::Property::Plot3DScatterDB_MeshSmooth: + return Pair(tr("Mesh Smooth"), series->isMeshSmooth()); + case PropertyItem::Property::Plot3DScatterDB_ColorStyle: + return Pair(tr("Color Style"), + static_cast(series->colorStyle())); + case PropertyItem::Property::Plot3DScatterDB_SolidColor: + return Pair(tr("Color"), series->baseColor()); + case PropertyItem::Property::Plot3DScatterDB_GradientColor: + return Pair(tr("Gradient Color"), + static_cast(block->getgradient())); + case PropertyItem::Property::Plot3DScatterDB_HighlightColor: + return Pair(tr("Highlight Color"), series->singleHighlightColor()); + default: + break; + } + } break; + // Plot3D Bar + case ObjectBrowserTreeItem::ObjectType::Plot3DBar: { + Bar3D *bar = item_->getObjectTreeItem(&status); + if (!status) break; + Q3DBars *graph = bar->getGraph(); + switch (property_) { + case PropertyItem::Property::Plot3DBar_Base_Separator: + return Pair(tr("Bar"), QString()); + case PropertyItem::Property::Plot3DBar_AspectRatio: + return Pair(tr("Aspect Ratio"), + static_cast(graph->aspectRatio())); + case PropertyItem::Property::Plot3DBar_HorizontalAspectRatio: + return Pair(tr("Horizontal Aspect Ratio"), + static_cast(graph->horizontalAspectRatio())); + case PropertyItem::Property::Plot3DBar_ShadowQuality: + return Pair(tr("Shadow Quality"), + static_cast(graph->shadowQuality())); + case PropertyItem::Property::Plot3DBar_OrthoProjection: + return Pair(tr("Ortho Projection"), graph->isOrthoProjection()); + case PropertyItem::Property::Plot3DBar_Polar: + return Pair(tr("Polar Coords"), graph->isPolar()); + case PropertyItem::Property::Plot3DBar_Spacing_Separator: + return Pair(tr("Spacing"), QString()); + case PropertyItem::Property::Plot3DBar_RelativeSpacing: + return Pair(tr("Relative Spacing"), graph->isBarSpacingRelative()); + case PropertyItem::Property::Plot3DBar_SpacingX: + return Pair(tr("Spacing X"), + static_cast(graph->barSpacing().width())); + case PropertyItem::Property::Plot3DBar_SpacingY: + return Pair(tr("Spacing Y"), + static_cast(graph->barSpacing().height())); + case PropertyItem::Property::Plot3DBar_Thickness: + return Pair(tr("Bar Thickness"), + static_cast(graph->barThickness())); + default: + break; + } + } break; + // Plot3D Bar DataBlock + case ObjectBrowserTreeItem::ObjectType::Plot3DBarDataBlock: { + DataBlockBar3D *block = + item_->getObjectTreeItem(&status); + if (!status) break; + QBar3DSeries *series = block->getdataseries(); + switch (property_) { + case PropertyItem::Property::Plot3DBarDB_Base_Separator: + return Pair(tr("Series"), QString()); + case PropertyItem::Property::Plot3DBarDB_Visible: + return Pair(tr("Visible"), series->isVisible()); + case PropertyItem::Property::Plot3DBarDB_MeshSmooth: + return Pair(tr("Mesh Smooth"), series->isMeshSmooth()); + case PropertyItem::Property::Plot3DBarDB_ColorStyle: + return Pair(tr("Color Style"), + static_cast(series->colorStyle())); + case PropertyItem::Property::Plot3DBarDB_SolidColor: + return Pair(tr("Color"), series->baseColor()); + case PropertyItem::Property::Plot3DBarDB_GradientColor: + return Pair(tr("Gradient Color"), + static_cast(block->getgradient())); + case PropertyItem::Property::Plot3DBarDB_HighlightColor: + return Pair(tr("Highlight Color"), series->singleHighlightColor()); + default: + break; + } + } break; + // Plot3D Surface + case ObjectBrowserTreeItem::ObjectType::Plot3DSurface: { + Surface3D *surface = item_->getObjectTreeItem(&status); + if (!status) break; + Q3DSurface *graph = surface->getGraph(); + switch (property_) { + case PropertyItem::Property::Plot3DSurface_Base_Separator: + return Pair(tr("Surface"), QString()); + case PropertyItem::Property::Plot3DSurface_AspectRatio: + return Pair(tr("Aspect Ratio"), + static_cast(graph->aspectRatio())); + case PropertyItem::Property::Plot3DSurface_HorizontalAspectRatio: + return Pair(tr("Horizontal Aspect Ratio"), + static_cast(graph->horizontalAspectRatio())); + case PropertyItem::Property::Plot3DSurface_ShadowQuality: + return Pair(tr("Shadow Quality"), + static_cast(graph->shadowQuality())); + case PropertyItem::Property::Plot3DSurface_FlipHorizontalGrid: + return Pair(tr("Flip Horizontal Grid"), + graph->flipHorizontalGrid()); + case PropertyItem::Property::Plot3DSurface_OrthoProjection: + return Pair(tr("Ortho Projection"), graph->isOrthoProjection()); + case PropertyItem::Property::Plot3DSurface_Polar: + return Pair(tr("Polar Coords"), graph->isPolar()); + default: + break; + } + } break; + // Plot3D Surface DataBlock + case ObjectBrowserTreeItem::ObjectType::Plot3DSurfaceDataBlock: { + DataBlockSurface3D *block = + item_->getObjectTreeItem(&status); + if (!status) break; + QSurface3DSeries *series = block->getdataseries(); + switch (property_) { + case PropertyItem::Property::Plot3DSurfaceDB_Base_Separator: + return Pair(tr("Series"), QString()); + case PropertyItem::Property::Plot3DSurfaceDB_Visible: + return Pair(tr("Visible"), series->isVisible()); + case PropertyItem::Property::Plot3DSurfaceDB_FlatShading: + return Pair(tr("Flat Shading"), series->isFlatShadingEnabled()); + case PropertyItem::Property::Plot3DSurfaceDB_DrawMode: { + int mode = 0; + auto dm = series->drawMode(); + if (dm == QSurface3DSeries::DrawSurface) mode = 0; + else if (dm == QSurface3DSeries::DrawWireframe) mode = 1; + else mode = 2; + return Pair(tr("Draw Mode"), mode); + } + case PropertyItem::Property::Plot3DSurfaceDB_MeshSmooth: + return Pair(tr("Mesh Smooth"), series->isMeshSmooth()); + case PropertyItem::Property::Plot3DSurfaceDB_ColorStyle: + return Pair(tr("Color Style"), + static_cast(series->colorStyle())); + case PropertyItem::Property::Plot3DSurfaceDB_SolidColor: + return Pair(tr("Color"), series->baseColor()); + case PropertyItem::Property::Plot3DSurfaceDB_GradientColor: + return Pair(tr("Gradient Color"), + static_cast(block->getgradient())); + case PropertyItem::Property::Plot3DSurfaceDB_HighlightColor: + return Pair(tr("Highlight Color"), series->singleHighlightColor()); + default: + break; + } + } break; } + return Pair(QString(), QVariant()); } @@ -2969,6 +3293,26 @@ void PropertyItem::setStringValue(const QString &val) { cm->getcolormapscale_colormap()->axis()->layer()->replot(); } } break; + // Plot3D Axis Value (QValue3DAxis) + case PropertyItem::Property::Plot3DAxisVal_Label_Text: { + QValue3DAxis *axis = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) { + axis->setTitle(val); + } + } break; + case PropertyItem::Property::Plot3DAxisVal_TickLabel_Format: { + QValue3DAxis *axis = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) { + axis->setLabelFormat(val); + } + } break; + // Plot3D Axis Category (QCategory3DAxis) + case PropertyItem::Property::Plot3DAxisCat_Label_Text: { + QCategory3DAxis *axis = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) { + axis->setTitle(val); + } + } break; default: break; } @@ -3364,6 +3708,19 @@ void PropertyItem::setIntValue(const int &val) { if (status) widget->resize(widget->size() + sizediff); } } break; + // Plot3D Axis Value + case PropertyItem::Property::Plot3DAxisVal_Tick_Count: { + QValue3DAxis *axis = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) { + axis->setSegmentCount(val); + } + } break; + case PropertyItem::Property::Plot3DAxisVal_SubTick_Count: { + QValue3DAxis *axis = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) { + axis->setSubSegmentCount(val); + } + } break; default: break; } @@ -4016,6 +4373,90 @@ void PropertyItem::setDoubleValue(const double &val) { if (!Utilities::isSameDouble(val, PropertyData()) && status) theme->setAmbientLightStrength(val); } break; + // Plot3D Axis Value + case PropertyItem::Property::Plot3DAxisVal_TickLabel_Rotation: { + QValue3DAxis *axis = item_->getObjectTreeItem(&status); + if (!Utilities::isSameDouble(val, PropertyData()) && status) { + axis->setLabelAutoRotation(static_cast(val)); + } + } break; + // Plot3D Axis Category + case PropertyItem::Property::Plot3DAxisCat_TickLabel_Rotation: { + QCategory3DAxis *axis = item_->getObjectTreeItem(&status); + if (!Utilities::isSameDouble(val, PropertyData()) && status) { + axis->setLabelAutoRotation(static_cast(val)); + } + } break; + case PropertyItem::Property::Plot3DAxisCat_From: { + QCategory3DAxis *axis = item_->getObjectTreeItem(&status); + if (!Utilities::isSameDouble(val, PropertyData()) && status) { + if (val < axis->max()) axis->setMin(val); + } + } break; + case PropertyItem::Property::Plot3DAxisCat_To: { + QCategory3DAxis *axis = item_->getObjectTreeItem(&status); + if (!Utilities::isSameDouble(val, PropertyData()) && status) { + if (val > axis->min()) axis->setMax(val); + } + } break; + // Plot3D Scatter graph + case PropertyItem::Property::Plot3DScatter_AspectRatio: { + Scatter3D *scatter = item_->getObjectTreeItem(&status); + if (!Utilities::isSameDouble(val, PropertyData()) && status) + scatter->getGraph()->setAspectRatio(val); + } break; + case PropertyItem::Property::Plot3DScatter_HorizontalAspectRatio: { + Scatter3D *scatter = item_->getObjectTreeItem(&status); + if (!Utilities::isSameDouble(val, PropertyData()) && status) + scatter->getGraph()->setHorizontalAspectRatio(val); + } break; + case PropertyItem::Property::Plot3DScatterDB_Size: { + DataBlockScatter3D *block = + item_->getObjectTreeItem(&status); + if (!Utilities::isSameDouble(val, PropertyData()) && status) + block->getdataseries()->setItemSize(static_cast(val)); + } break; + // Plot3D Bar graph + case PropertyItem::Property::Plot3DBar_AspectRatio: { + Bar3D *bar = item_->getObjectTreeItem(&status); + if (!Utilities::isSameDouble(val, PropertyData()) && status) + bar->getGraph()->setAspectRatio(val); + } break; + case PropertyItem::Property::Plot3DBar_HorizontalAspectRatio: { + Bar3D *bar = item_->getObjectTreeItem(&status); + if (!Utilities::isSameDouble(val, PropertyData()) && status) + bar->getGraph()->setHorizontalAspectRatio(val); + } break; + case PropertyItem::Property::Plot3DBar_SpacingX: { + Bar3D *bar = item_->getObjectTreeItem(&status); + if (!Utilities::isSameDouble(val, PropertyData()) && status) { + QSizeF sp = bar->getGraph()->barSpacing(); + bar->getGraph()->setBarSpacing(QSizeF(val, sp.height())); + } + } break; + case PropertyItem::Property::Plot3DBar_SpacingY: { + Bar3D *bar = item_->getObjectTreeItem(&status); + if (!Utilities::isSameDouble(val, PropertyData()) && status) { + QSizeF sp = bar->getGraph()->barSpacing(); + bar->getGraph()->setBarSpacing(QSizeF(sp.width(), val)); + } + } break; + case PropertyItem::Property::Plot3DBar_Thickness: { + Bar3D *bar = item_->getObjectTreeItem(&status); + if (!Utilities::isSameDouble(val, PropertyData()) && status) + bar->getGraph()->setBarThickness(static_cast(val)); + } break; + // Plot3D Surface graph + case PropertyItem::Property::Plot3DSurface_AspectRatio: { + Surface3D *surface = item_->getObjectTreeItem(&status); + if (!Utilities::isSameDouble(val, PropertyData()) && status) + surface->getGraph()->setAspectRatio(val); + } break; + case PropertyItem::Property::Plot3DSurface_HorizontalAspectRatio: { + Surface3D *surface = item_->getObjectTreeItem(&status); + if (!Utilities::isSameDouble(val, PropertyData()) && status) + surface->getGraph()->setHorizontalAspectRatio(val); + } break; default: break; } @@ -4086,6 +4527,19 @@ void PropertyItem::setScientificDoubleValue(const double &val) { } } } break; + // Plot3D Axis Value + case PropertyItem::Property::Plot3DAxisVal_From: { + QValue3DAxis *axis = item_->getObjectTreeItem(&status); + if (!Utilities::isSameDouble(val, PropertyData()) && status) { + if (val < axis->max()) axis->setMin(static_cast(val)); + } + } break; + case PropertyItem::Property::Plot3DAxisVal_To: { + QValue3DAxis *axis = item_->getObjectTreeItem(&status); + if (!Utilities::isSameDouble(val, PropertyData()) && status) { + if (val > axis->min()) axis->setMax(static_cast(val)); + } + } break; default: break; } @@ -4496,6 +4950,118 @@ void PropertyItem::setBoolValue(const bool &val) { if (val != PropertyData() && status) theme->setLabelBorderEnabled(val); } break; + // Plot3D Axis Value + case PropertyItem::Property::Plot3DAxisVal_AutoRange: { + QValue3DAxis *axis = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) axis->setAutoAdjustRange(val); + } break; + case PropertyItem::Property::Plot3DAxisVal_Inverted: { + QValue3DAxis *axis = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) axis->setReversed(val); + } break; + case PropertyItem::Property::Plot3DAxisVal_Label_Visible: { + QValue3DAxis *axis = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) axis->setTitleVisible(val); + } break; + case PropertyItem::Property::Plot3DAxisVal_Label_Fixed: { + QValue3DAxis *axis = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) axis->setTitleFixed(val); + } break; + // Plot3D Axis Category + case PropertyItem::Property::Plot3DAxisCat_AutoRange: { + QCategory3DAxis *axis = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) axis->setAutoAdjustRange(val); + } break; + case PropertyItem::Property::Plot3DAxisCat_Label_Visible: { + QCategory3DAxis *axis = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) axis->setTitleVisible(val); + } break; + case PropertyItem::Property::Plot3DAxisCat_Label_Fixed: { + QCategory3DAxis *axis = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) axis->setTitleFixed(val); + } break; + // Plot3D Scatter + case PropertyItem::Property::Plot3DScatter_OrthoProjection: { + Scatter3D *scatter = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + scatter->getGraph()->setOrthoProjection(val); + } break; + case PropertyItem::Property::Plot3DScatter_Polar: { + Scatter3D *scatter = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + scatter->getGraph()->setPolar(val); + } break; + case PropertyItem::Property::Plot3DScatterDB_Visible: { + DataBlockScatter3D *block = + item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + block->getdataseries()->setVisible(val); + } break; + case PropertyItem::Property::Plot3DScatterDB_MeshSmooth: { + DataBlockScatter3D *block = + item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + block->getdataseries()->setMeshSmooth(val); + } break; + // Plot3D Bar + case PropertyItem::Property::Plot3DBar_OrthoProjection: { + Bar3D *bar = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + bar->getGraph()->setOrthoProjection(val); + } break; + case PropertyItem::Property::Plot3DBar_Polar: { + Bar3D *bar = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) bar->getGraph()->setPolar(val); + } break; + case PropertyItem::Property::Plot3DBar_RelativeSpacing: { + Bar3D *bar = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + bar->getGraph()->setBarSpacingRelative(val); + } break; + case PropertyItem::Property::Plot3DBarDB_Visible: { + DataBlockBar3D *block = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + block->getdataseries()->setVisible(val); + } break; + case PropertyItem::Property::Plot3DBarDB_MeshSmooth: { + DataBlockBar3D *block = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + block->getdataseries()->setMeshSmooth(val); + } break; + // Plot3D Surface + case PropertyItem::Property::Plot3DSurface_FlipHorizontalGrid: { + Surface3D *surface = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + surface->getGraph()->setFlipHorizontalGrid(val); + } break; + case PropertyItem::Property::Plot3DSurface_OrthoProjection: { + Surface3D *surface = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + surface->getGraph()->setOrthoProjection(val); + } break; + case PropertyItem::Property::Plot3DSurface_Polar: { + Surface3D *surface = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + surface->getGraph()->setPolar(val); + } break; + case PropertyItem::Property::Plot3DSurfaceDB_Visible: { + DataBlockSurface3D *block = + item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + block->getdataseries()->setVisible(val); + } break; + case PropertyItem::Property::Plot3DSurfaceDB_FlatShading: { + DataBlockSurface3D *block = + item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + block->getdataseries()->setFlatShadingEnabled(val); + } break; + case PropertyItem::Property::Plot3DSurfaceDB_MeshSmooth: { + DataBlockSurface3D *block = + item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + block->getdataseries()->setMeshSmooth(val); + } break; default: break; } @@ -5326,6 +5892,80 @@ void PropertyItem::setEnumValue(const int &val) { plot->activeTheme()->setType(static_cast(val)); } } break; + // Plot3D Scatter + case PropertyItem::Property::Plot3DScatter_ShadowQuality: { + Scatter3D *scatter = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + scatter->getGraph()->setShadowQuality( + static_cast(val)); + } break; + case PropertyItem::Property::Plot3DScatterDB_ColorStyle: { + DataBlockScatter3D *block = + item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + block->getdataseries()->setColorStyle( + static_cast(val)); + } break; + case PropertyItem::Property::Plot3DScatterDB_GradientColor: { + DataBlockScatter3D *block = + item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + block->setgradient(block->getdataseries(), + static_cast(val)); + } break; + // Plot3D Bar + case PropertyItem::Property::Plot3DBar_ShadowQuality: { + Bar3D *bar = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + bar->getGraph()->setShadowQuality( + static_cast(val)); + } break; + case PropertyItem::Property::Plot3DBarDB_ColorStyle: { + DataBlockBar3D *block = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + block->getdataseries()->setColorStyle( + static_cast(val)); + } break; + case PropertyItem::Property::Plot3DBarDB_GradientColor: { + DataBlockBar3D *block = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + block->setgradient(block->getdataseries(), + static_cast(val)); + } break; + // Plot3D Surface + case PropertyItem::Property::Plot3DSurface_ShadowQuality: { + Surface3D *surface = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + surface->getGraph()->setShadowQuality( + static_cast(val)); + } break; + case PropertyItem::Property::Plot3DSurfaceDB_DrawMode: { + DataBlockSurface3D *block = + item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) { + if (val == 0) + block->getdataseries()->setDrawMode(QSurface3DSeries::DrawSurface); + else if (val == 1) + block->getdataseries()->setDrawMode(QSurface3DSeries::DrawWireframe); + else + block->getdataseries()->setDrawMode( + QSurface3DSeries::DrawSurfaceAndWireframe); + } + } break; + case PropertyItem::Property::Plot3DSurfaceDB_ColorStyle: { + DataBlockSurface3D *block = + item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + block->getdataseries()->setColorStyle( + static_cast(val)); + } break; + case PropertyItem::Property::Plot3DSurfaceDB_GradientColor: { + DataBlockSurface3D *block = + item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + block->setgradient(block->getdataseries(), + static_cast(val)); + } break; default: break; } @@ -5797,6 +6437,43 @@ void PropertyItem::setColorValue(const QColor &val) { if (val != PropertyData() && status) theme->setLabelTextColor(val); } break; + // Plot3D Scatter + case PropertyItem::Property::Plot3DScatterDB_SolidColor: { + DataBlockScatter3D *block = + item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + block->getdataseries()->setBaseColor(val); + } break; + case PropertyItem::Property::Plot3DScatterDB_HighlightColor: { + DataBlockScatter3D *block = + item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + block->getdataseries()->setSingleHighlightColor(val); + } break; + // Plot3D Bar + case PropertyItem::Property::Plot3DBarDB_SolidColor: { + DataBlockBar3D *block = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + block->getdataseries()->setBaseColor(val); + } break; + case PropertyItem::Property::Plot3DBarDB_HighlightColor: { + DataBlockBar3D *block = item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + block->getdataseries()->setSingleHighlightColor(val); + } break; + // Plot3D Surface + case PropertyItem::Property::Plot3DSurfaceDB_SolidColor: { + DataBlockSurface3D *block = + item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + block->getdataseries()->setBaseColor(val); + } break; + case PropertyItem::Property::Plot3DSurfaceDB_HighlightColor: { + DataBlockSurface3D *block = + item_->getObjectTreeItem(&status); + if (val != PropertyData() && status) + block->getdataseries()->setSingleHighlightColor(val); + } break; default: break; } diff --git a/alphaplot/src/core/propertybrowser/PropertyItem.h b/alphaplot/src/core/propertybrowser/PropertyItem.h index faea71ae..013affd3 100644 --- a/alphaplot/src/core/propertybrowser/PropertyItem.h +++ b/alphaplot/src/core/propertybrowser/PropertyItem.h @@ -514,6 +514,60 @@ class PropertyItem : public QObject { Plot3DAxisCat_Label_Visible, Plot3DAxisCat_Label_Fixed, Plot3DAxisCat_Label_Text, + // Plot3D Scatter (graph-level) + Plot3DScatter_Base_Separator, + Plot3DScatter_AspectRatio, + Plot3DScatter_HorizontalAspectRatio, + Plot3DScatter_ShadowQuality, + Plot3DScatter_OrthoProjection, + Plot3DScatter_Polar, + // Plot3D Scatter DataBlock (series-level) + Plot3DScatterDB_Base_Separator, + Plot3DScatterDB_Visible, + Plot3DScatterDB_Size, + Plot3DScatterDB_MeshSmooth, + Plot3DScatterDB_ColorStyle, + Plot3DScatterDB_SolidColor, + Plot3DScatterDB_GradientColor, + Plot3DScatterDB_HighlightColor, + // Plot3D Bar (graph-level) + Plot3DBar_Base_Separator, + Plot3DBar_AspectRatio, + Plot3DBar_HorizontalAspectRatio, + Plot3DBar_ShadowQuality, + Plot3DBar_OrthoProjection, + Plot3DBar_Polar, + Plot3DBar_Spacing_Separator, + Plot3DBar_RelativeSpacing, + Plot3DBar_SpacingX, + Plot3DBar_SpacingY, + Plot3DBar_Thickness, + // Plot3D Bar DataBlock (series-level) + Plot3DBarDB_Base_Separator, + Plot3DBarDB_Visible, + Plot3DBarDB_MeshSmooth, + Plot3DBarDB_ColorStyle, + Plot3DBarDB_SolidColor, + Plot3DBarDB_GradientColor, + Plot3DBarDB_HighlightColor, + // Plot3D Surface (graph-level) + Plot3DSurface_Base_Separator, + Plot3DSurface_AspectRatio, + Plot3DSurface_HorizontalAspectRatio, + Plot3DSurface_ShadowQuality, + Plot3DSurface_FlipHorizontalGrid, + Plot3DSurface_OrthoProjection, + Plot3DSurface_Polar, + // Plot3D Surface DataBlock (series-level) + Plot3DSurfaceDB_Base_Separator, + Plot3DSurfaceDB_Visible, + Plot3DSurfaceDB_FlatShading, + Plot3DSurfaceDB_DrawMode, + Plot3DSurfaceDB_MeshSmooth, + Plot3DSurfaceDB_ColorStyle, + Plot3DSurfaceDB_SolidColor, + Plot3DSurfaceDB_GradientColor, + Plot3DSurfaceDB_HighlightColor, }; enum class PropertyType { diff --git a/alphaplot/src/core/propertybrowser/PropertyItemDelegate.cpp b/alphaplot/src/core/propertybrowser/PropertyItemDelegate.cpp index bf004902..88bf802e 100644 --- a/alphaplot/src/core/propertybrowser/PropertyItemDelegate.cpp +++ b/alphaplot/src/core/propertybrowser/PropertyItemDelegate.cpp @@ -21,7 +21,10 @@ PropertyItemDelegate::~PropertyItemDelegate() {} QSize PropertyItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const { QSize size = QStyledItemDelegate::sizeHint(option, index); - // size += QSize(0, 5); + // Enforce a minimum line height to ensure text (e.g. True/False) is fully visible + // across all themes like Fusion or Windows. + int minHeight = qMax(26, option.fontMetrics.height() + 8); + size.setHeight(qMax(size.height(), minHeight)); return size; } @@ -33,7 +36,9 @@ void PropertyItemDelegate::paint(QPainter* painter, PropertyItem* property = static_cast(index.internalPointer()); if (property->propertyType() == PropertyItem::PropertyType::Separator) { - QColor color = option.palette.color(QPalette::Text); + QColor color; + (IconLoader::lumen_ > 100) ? color = option.palette.light().color() + : color = option.palette.dark().color(); QObject* par = parent(); if (par) { QVariant value = par->property("groupTextColor"); @@ -41,7 +46,7 @@ void PropertyItemDelegate::paint(QPainter* painter, } option.palette.setColor(QPalette::Text, color); option.font.setBold(true); - option.state &= ~QStyle::State_Selected; + option.state &= ~(QStyle::State_Selected | QStyle::State_MouseOver); } if (index.column() == 1) { @@ -57,7 +62,7 @@ void PropertyItemDelegate::paint(QPainter* painter, : brush = option.palette.light(); pal.setColor(QPalette::Base, brush.color()); pal.setColor(QPalette::AlternateBase, brush.color()); - pal.setColor(QPalette::Background, brush.color()); + pal.setColor(QPalette::Window, brush.color()); QObject* par = parent(); if (par) { QVariant value = par->property("groupBackground"); @@ -94,6 +99,10 @@ void PropertyItemDelegate::paint(QPainter* painter, // Grid Lines QColor color = static_cast(QApplication::style()->styleHint( QStyle::SH_Table_GridLineColor, &opt, qobject_cast(parent()))); + if (property->propertyType() == PropertyItem::PropertyType::Separator) { + color = Qt::transparent; + } + painter->setPen(QPen(color)); if (index.column() == 1 && property->propertyType() != PropertyItem::PropertyType::Separator) { @@ -135,9 +144,11 @@ void PropertyItemDelegate::paintBoolProperty( &buttonOption); // Only used to get size of native checkbox widget. buttonOption.text = property->toString(); buttonOption.palette = option.palette; - buttonOption.rect = - QStyle::alignedRect(option.direction, Qt::AlignLeft, checkBoxRect.size(), - option.rect); // Our checkbox rect. + buttonOption.rect = option.rect; // Use the full cell rect so the text doesn't get clipped + int margin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin, &option) + 1; + buttonOption.rect.adjust(margin, 0, 0, 0); // Align with standard text margin + + QApplication::style()->drawControl(QStyle::CE_CheckBox, &buttonOption, painter); } diff --git a/alphaplot/src/core/propertybrowser/PropertyItemModel.cpp b/alphaplot/src/core/propertybrowser/PropertyItemModel.cpp index 1c3b012b..67a0a1e0 100644 --- a/alphaplot/src/core/propertybrowser/PropertyItemModel.cpp +++ b/alphaplot/src/core/propertybrowser/PropertyItemModel.cpp @@ -1994,8 +1994,318 @@ void PropertyItemModel::buildUp(ObjectBrowserTreeItem *item) { rootItem_, item, PropertyItem::Property::Plot3DTheme_Label_Border_Visible); } break; + // Plot3D Axis Value (QValue3DAxis) + case ObjectBrowserTreeItem::ObjectType::Plot3DAxisValue: { + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DAxisVal_Base_Separator); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DAxisVal_AutoRange); + auto pfrom = PropertyItem::create( + rootItem_, item, PropertyItem::Property::Plot3DAxisVal_From); + pfrom->setPrecision(precision); + pfrom->setLowerLimitDouble(-1e+308); + pfrom->setUpperLimitDouble(1e+308); + auto pto = PropertyItem::create( + rootItem_, item, PropertyItem::Property::Plot3DAxisVal_To); + pto->setPrecision(precision); + pto->setLowerLimitDouble(-1e+308); + pto->setUpperLimitDouble(1e+308); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DAxisVal_Inverted); + auto tickcount = PropertyItem::create( + rootItem_, item, PropertyItem::Property::Plot3DAxisVal_Tick_Count); + tickcount->setLowerLimitInt(1); + auto subtickcount = PropertyItem::create( + rootItem_, item, PropertyItem::Property::Plot3DAxisVal_SubTick_Count); + subtickcount->setLowerLimitInt(0); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DAxisVal_Tick_Separator); + PropertyItem::create( + rootItem_, item, + PropertyItem::Property::Plot3DAxisVal_TickLabel_Format); + auto tickrot = PropertyItem::create( + rootItem_, item, + PropertyItem::Property::Plot3DAxisVal_TickLabel_Rotation); + tickrot->setPrecision(2); + tickrot->setLowerLimitDouble(0); + tickrot->setUpperLimitDouble(90); + tickrot->setSuffix(tr(" °")); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DAxisVal_Label_Separator); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DAxisVal_Label_Visible); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DAxisVal_Label_Fixed); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DAxisVal_Label_Text); + } break; + // Plot3D Axis Category (QCategory3DAxis) + case ObjectBrowserTreeItem::ObjectType::Plot3DAxisCatagory: { + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DAxisCat_Base_Separator); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DAxisCat_AutoRange); + auto catfrom = PropertyItem::create( + rootItem_, item, PropertyItem::Property::Plot3DAxisCat_From); + catfrom->setPrecision(2); + auto catto = PropertyItem::create( + rootItem_, item, PropertyItem::Property::Plot3DAxisCat_To); + catto->setPrecision(2); + auto catticklabelrot = PropertyItem::create( + rootItem_, item, + PropertyItem::Property::Plot3DAxisCat_TickLabel_Rotation); + catticklabelrot->setPrecision(2); + catticklabelrot->setLowerLimitDouble(0); + catticklabelrot->setUpperLimitDouble(90); + catticklabelrot->setSuffix(tr(" °")); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DAxisCat_Label_Separator); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DAxisCat_Label_Visible); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DAxisCat_Label_Fixed); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DAxisCat_Label_Text); + } break; + // Plot3D Scatter + case ObjectBrowserTreeItem::ObjectType::Plot3DScatter: { + QList> shadowquality; + shadowquality << QPair(QIcon(), tr("None")) + << QPair(QIcon(), tr("Low")) + << QPair(QIcon(), tr("Medium")) + << QPair(QIcon(), tr("High")) + << QPair(QIcon(), tr("Soft Low")) + << QPair(QIcon(), tr("Soft Medium")) + << QPair(QIcon(), tr("Soft High")); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DScatter_Base_Separator); + auto ar = PropertyItem::create( + rootItem_, item, PropertyItem::Property::Plot3DScatter_AspectRatio); + ar->setPrecision(4); + ar->setLowerLimitDouble(0.1); + auto har = PropertyItem::create( + rootItem_, item, + PropertyItem::Property::Plot3DScatter_HorizontalAspectRatio); + har->setPrecision(4); + har->setLowerLimitDouble(0); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DScatter_ShadowQuality, + shadowquality); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DScatter_OrthoProjection); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DScatter_Polar); + } break; + // Plot3D Scatter DataBlock + case ObjectBrowserTreeItem::ObjectType::Plot3DScatterDataBlock: { + QList> colorstyle; + colorstyle << QPair(QIcon(), tr("Uniform")) + << QPair(QIcon(), tr("Range Gradient")) + << QPair(QIcon(), tr("Object Gradient")); + QList> gradients; + gradients << QPair(QIcon(), tr("Grayscale")) + << QPair(QIcon(), tr("Hot")) + << QPair(QIcon(), tr("Cold")) + << QPair(QIcon(), tr("Night")) + << QPair(QIcon(), tr("Candy")) + << QPair(QIcon(), tr("Geography")) + << QPair(QIcon(), tr("Ion")) + << QPair(QIcon(), tr("Thermal")) + << QPair(QIcon(), tr("Polar")) + << QPair(QIcon(), tr("Spectrum")) + << QPair(QIcon(), tr("Jet")) + << QPair(QIcon(), tr("Hues")) + << QPair(QIcon(), tr("BBRY")) + << QPair(QIcon(), tr("GYRD")); + PropertyItem::create( + rootItem_, item, + PropertyItem::Property::Plot3DScatterDB_Base_Separator); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DScatterDB_Visible); + auto sz = PropertyItem::create( + rootItem_, item, PropertyItem::Property::Plot3DScatterDB_Size); + sz->setPrecision(4); + sz->setLowerLimitDouble(0); + sz->setUpperLimitDouble(1); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DScatterDB_MeshSmooth); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DScatterDB_ColorStyle, + colorstyle); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DScatterDB_SolidColor); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DScatterDB_GradientColor, + gradients); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DScatterDB_HighlightColor); + } break; + // Plot3D Bar + case ObjectBrowserTreeItem::ObjectType::Plot3DBar: { + QList> shadowquality; + shadowquality << QPair(QIcon(), tr("None")) + << QPair(QIcon(), tr("Low")) + << QPair(QIcon(), tr("Medium")) + << QPair(QIcon(), tr("High")) + << QPair(QIcon(), tr("Soft Low")) + << QPair(QIcon(), tr("Soft Medium")) + << QPair(QIcon(), tr("Soft High")); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DBar_Base_Separator); + auto ar = PropertyItem::create( + rootItem_, item, PropertyItem::Property::Plot3DBar_AspectRatio); + ar->setPrecision(4); + ar->setLowerLimitDouble(0.1); + auto har = PropertyItem::create( + rootItem_, item, + PropertyItem::Property::Plot3DBar_HorizontalAspectRatio); + har->setPrecision(4); + har->setLowerLimitDouble(0); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DBar_ShadowQuality, + shadowquality); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DBar_OrthoProjection); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DBar_Polar); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DBar_Spacing_Separator); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DBar_RelativeSpacing); + auto sx = PropertyItem::create( + rootItem_, item, PropertyItem::Property::Plot3DBar_SpacingX); + sx->setPrecision(4); + sx->setLowerLimitDouble(0); + auto sy = PropertyItem::create( + rootItem_, item, PropertyItem::Property::Plot3DBar_SpacingY); + sy->setPrecision(4); + sy->setLowerLimitDouble(0); + auto th = PropertyItem::create( + rootItem_, item, PropertyItem::Property::Plot3DBar_Thickness); + th->setPrecision(4); + th->setLowerLimitDouble(0); + th->setUpperLimitDouble(1); + } break; + // Plot3D Bar DataBlock + case ObjectBrowserTreeItem::ObjectType::Plot3DBarDataBlock: { + QList> colorstyle; + colorstyle << QPair(QIcon(), tr("Uniform")) + << QPair(QIcon(), tr("Range Gradient")) + << QPair(QIcon(), tr("Object Gradient")); + QList> gradients; + gradients << QPair(QIcon(), tr("Grayscale")) + << QPair(QIcon(), tr("Hot")) + << QPair(QIcon(), tr("Cold")) + << QPair(QIcon(), tr("Night")) + << QPair(QIcon(), tr("Candy")) + << QPair(QIcon(), tr("Geography")) + << QPair(QIcon(), tr("Ion")) + << QPair(QIcon(), tr("Thermal")) + << QPair(QIcon(), tr("Polar")) + << QPair(QIcon(), tr("Spectrum")) + << QPair(QIcon(), tr("Jet")) + << QPair(QIcon(), tr("Hues")) + << QPair(QIcon(), tr("BBRY")) + << QPair(QIcon(), tr("GYRD")); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DBarDB_Base_Separator); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DBarDB_Visible); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DBarDB_MeshSmooth); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DBarDB_ColorStyle, + colorstyle); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DBarDB_SolidColor); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DBarDB_GradientColor, + gradients); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DBarDB_HighlightColor); + } break; + // Plot3D Surface + case ObjectBrowserTreeItem::ObjectType::Plot3DSurface: { + QList> shadowquality; + shadowquality << QPair(QIcon(), tr("None")) + << QPair(QIcon(), tr("Low")) + << QPair(QIcon(), tr("Medium")) + << QPair(QIcon(), tr("High")) + << QPair(QIcon(), tr("Soft Low")) + << QPair(QIcon(), tr("Soft Medium")) + << QPair(QIcon(), tr("Soft High")); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DSurface_Base_Separator); + auto ar = PropertyItem::create( + rootItem_, item, PropertyItem::Property::Plot3DSurface_AspectRatio); + ar->setPrecision(4); + ar->setLowerLimitDouble(0.1); + auto har = PropertyItem::create( + rootItem_, item, + PropertyItem::Property::Plot3DSurface_HorizontalAspectRatio); + har->setPrecision(4); + har->setLowerLimitDouble(0); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DSurface_ShadowQuality, + shadowquality); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DSurface_FlipHorizontalGrid); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DSurface_OrthoProjection); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DSurface_Polar); + } break; + // Plot3D Surface DataBlock + case ObjectBrowserTreeItem::ObjectType::Plot3DSurfaceDataBlock: { + QList> colorstyle; + colorstyle << QPair(QIcon(), tr("Uniform")) + << QPair(QIcon(), tr("Range Gradient")) + << QPair(QIcon(), tr("Object Gradient")); + QList> gradients; + gradients << QPair(QIcon(), tr("Grayscale")) + << QPair(QIcon(), tr("Hot")) + << QPair(QIcon(), tr("Cold")) + << QPair(QIcon(), tr("Night")) + << QPair(QIcon(), tr("Candy")) + << QPair(QIcon(), tr("Geography")) + << QPair(QIcon(), tr("Ion")) + << QPair(QIcon(), tr("Thermal")) + << QPair(QIcon(), tr("Polar")) + << QPair(QIcon(), tr("Spectrum")) + << QPair(QIcon(), tr("Jet")) + << QPair(QIcon(), tr("Hues")) + << QPair(QIcon(), tr("BBRY")) + << QPair(QIcon(), tr("GYRD")); + QList> drawmode; + drawmode << QPair(QIcon(), tr("Surface")) + << QPair(QIcon(), tr("Wireframe")) + << QPair(QIcon(), tr("Surface & Wireframe")); + PropertyItem::create( + rootItem_, item, + PropertyItem::Property::Plot3DSurfaceDB_Base_Separator); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DSurfaceDB_Visible); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DSurfaceDB_FlatShading); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DSurfaceDB_DrawMode, + drawmode); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DSurfaceDB_MeshSmooth); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DSurfaceDB_ColorStyle, + colorstyle); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DSurfaceDB_SolidColor); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DSurfaceDB_GradientColor, + gradients); + PropertyItem::create(rootItem_, item, + PropertyItem::Property::Plot3DSurfaceDB_HighlightColor); + } break; } + endResetModel(); emit modelResetComplete(); } diff --git a/alphaplot/src/core/propertybrowser/PropertyView.cpp b/alphaplot/src/core/propertybrowser/PropertyView.cpp index bbb6df7f..b6218971 100644 --- a/alphaplot/src/core/propertybrowser/PropertyView.cpp +++ b/alphaplot/src/core/propertybrowser/PropertyView.cpp @@ -11,7 +11,8 @@ void PropertyView::drawBranches(QPainter *painter, const QRect &rect, const QModelIndex &index) const { QTreeView::drawBranches(painter, rect, index); - QStyleOptionViewItem option = viewOptions(); + QStyleOptionViewItem option; + initViewItemOption(&option); QBrush brush = QBrush(); (IconLoader::lumen_ > 100) ? brush = option.palette.dark() : brush = option.palette.light(); @@ -22,3 +23,14 @@ void PropertyView::drawBranches(QPainter *painter, const QRect &rect, painter->fillRect(rect, brush); } } + +QItemSelectionModel::SelectionFlags PropertyView::selectionCommand(const QModelIndex & index, + const QEvent * event) const { + if (index.isValid()) { + PropertyItem * item = static_cast < PropertyItem * > (index.internalPointer()); + if (item && item -> propertyType() == PropertyItem::PropertyType::Separator) { + return QItemSelectionModel::NoUpdate; + } + } + return QTreeView::selectionCommand(index, event); +} diff --git a/alphaplot/src/core/propertybrowser/PropertyView.h b/alphaplot/src/core/propertybrowser/PropertyView.h index eaeb89b8..66e88586 100644 --- a/alphaplot/src/core/propertybrowser/PropertyView.h +++ b/alphaplot/src/core/propertybrowser/PropertyView.h @@ -10,7 +10,9 @@ class PropertyView : public QTreeView { protected: virtual void drawBranches(QPainter *painter, const QRect &rect, - const QModelIndex &index) const; + const QModelIndex &index) const override; + QItemSelectionModel::SelectionFlags selectionCommand(const QModelIndex &index, + const QEvent *event = nullptr) const override; signals: }; diff --git a/alphaplot/src/future/core/AbstractAspect.cpp b/alphaplot/src/future/core/AbstractAspect.cpp index 6b4f70d5..73917609 100644 --- a/alphaplot/src/future/core/AbstractAspect.cpp +++ b/alphaplot/src/future/core/AbstractAspect.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/AbstractAspect.h b/alphaplot/src/future/core/AbstractAspect.h index 592d8d7e..83027c3b 100644 --- a/alphaplot/src/future/core/AbstractAspect.h +++ b/alphaplot/src/future/core/AbstractAspect.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -282,7 +282,7 @@ class AbstractAspect : public QObject { public: void importV0x0001XXCreationTime(const QString &str) { - setCreationTime(QDateTime::fromString(str, Qt::LocalDate)); + setCreationTime(QLocale().toDateTime(str, QLocale::ShortFormat)); } signals: diff --git a/alphaplot/src/future/core/AbstractColumn.h b/alphaplot/src/future/core/AbstractColumn.h index c3f8d720..924d69c9 100644 --- a/alphaplot/src/future/core/AbstractColumn.h +++ b/alphaplot/src/future/core/AbstractColumn.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -42,7 +42,7 @@ class Column; class AbstractSimpleFilter; -class QStringList; +#include //! Interface definition for data with column logic /** diff --git a/alphaplot/src/future/core/AbstractFilter.cpp b/alphaplot/src/future/core/AbstractFilter.cpp index 79e7abf0..6519b22a 100644 --- a/alphaplot/src/future/core/AbstractFilter.cpp +++ b/alphaplot/src/future/core/AbstractFilter.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/AbstractFilter.h b/alphaplot/src/future/core/AbstractFilter.h index 54d00f8f..83003624 100644 --- a/alphaplot/src/future/core/AbstractFilter.h +++ b/alphaplot/src/future/core/AbstractFilter.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/AbstractImportFilter.h b/alphaplot/src/future/core/AbstractImportFilter.h index 49ab24b1..844ab4a9 100644 --- a/alphaplot/src/future/core/AbstractImportFilter.h +++ b/alphaplot/src/future/core/AbstractImportFilter.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/AbstractPart.cpp b/alphaplot/src/future/core/AbstractPart.cpp index e6650c41..de9eeb08 100644 --- a/alphaplot/src/future/core/AbstractPart.cpp +++ b/alphaplot/src/future/core/AbstractPart.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/AbstractPart.h b/alphaplot/src/future/core/AbstractPart.h index 11b5f334..e0eed352 100644 --- a/alphaplot/src/future/core/AbstractPart.h +++ b/alphaplot/src/future/core/AbstractPart.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/AbstractSimpleFilter.cpp b/alphaplot/src/future/core/AbstractSimpleFilter.cpp index 80134556..4be1a29e 100644 --- a/alphaplot/src/future/core/AbstractSimpleFilter.cpp +++ b/alphaplot/src/future/core/AbstractSimpleFilter.cpp @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/AbstractSimpleFilter.h b/alphaplot/src/future/core/AbstractSimpleFilter.h index d60f417d..29d55acf 100644 --- a/alphaplot/src/future/core/AbstractSimpleFilter.h +++ b/alphaplot/src/future/core/AbstractSimpleFilter.h @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/AspectPrivate.cpp b/alphaplot/src/future/core/AspectPrivate.cpp index 1410e343..9c77d197 100644 --- a/alphaplot/src/future/core/AspectPrivate.cpp +++ b/alphaplot/src/future/core/AspectPrivate.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -27,8 +27,7 @@ * * ***************************************************************************/ #include "AspectPrivate.h" - -#include +#include #include #include "AbstractAspect.h" @@ -145,12 +144,14 @@ int AbstractAspect::Private::indexOfMatchingBrace(const QString &str, QString AbstractAspect::Private::caption() const { QString result = d_caption_spec; - QRegExp magic("%(.)"); - for (int pos = magic.indexIn(result, 0); pos >= 0; - pos = magic.indexIn(result, pos)) { - QString replacement = QString(); - int length = 0; - switch (magic.cap(1).at(0).toLatin1()) { + QRegularExpression magic("%(.)"); + int pos = 0; + QRegularExpressionMatch m = magic.match(result, pos); + while (m.hasMatch()) { + pos = m.capturedStart(); + QString replacement; + int length; + switch (m.captured(1).at(0).toLatin1()) { case '%': replacement = "%"; length = 2; @@ -172,9 +173,13 @@ QString AbstractAspect::Private::caption() const { replacement = d_comment.isEmpty() ? "" : result.mid(pos + 3, length - 4); break; + default: + length = 2; + break; } result.replace(pos, length, replacement); pos += replacement.size(); + m = magic.match(result, pos); } return result; } @@ -202,7 +207,7 @@ QString AbstractAspect::Private::uniqueNameFor( base[last_non_digit].category() != QChar::Separator_Space) base.append(" "); - int new_nr = current_name.rightRef(current_name.size() - base.size()).toInt(); + int new_nr = current_name.right(current_name.size() - base.size()).toInt(); QString new_name; do new_name = base + QString::number(++new_nr); while (child_names.contains(new_name)); diff --git a/alphaplot/src/future/core/AspectPrivate.h b/alphaplot/src/future/core/AspectPrivate.h index 5f8247f5..5f41aa97 100644 --- a/alphaplot/src/future/core/AspectPrivate.h +++ b/alphaplot/src/future/core/AspectPrivate.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/PartMdiView.cpp b/alphaplot/src/future/core/PartMdiView.cpp index c45029d9..df7aa39f 100644 --- a/alphaplot/src/future/core/PartMdiView.cpp +++ b/alphaplot/src/future/core/PartMdiView.cpp @@ -14,7 +14,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/PartMdiView.h b/alphaplot/src/future/core/PartMdiView.h index 1ba9cef1..c9b1b176 100644 --- a/alphaplot/src/future/core/PartMdiView.h +++ b/alphaplot/src/future/core/PartMdiView.h @@ -14,7 +14,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/Project.cpp b/alphaplot/src/future/core/Project.cpp index cfaa93b8..14abf7cf 100644 --- a/alphaplot/src/future/core/Project.cpp +++ b/alphaplot/src/future/core/Project.cpp @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/Project.h b/alphaplot/src/future/core/Project.h index 30be7c1b..4d910574 100644 --- a/alphaplot/src/future/core/Project.h +++ b/alphaplot/src/future/core/Project.h @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/ProjectConfigPage.cpp b/alphaplot/src/future/core/ProjectConfigPage.cpp index 00d68abb..fdc2c929 100644 --- a/alphaplot/src/future/core/ProjectConfigPage.cpp +++ b/alphaplot/src/future/core/ProjectConfigPage.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/ProjectConfigPage.h b/alphaplot/src/future/core/ProjectConfigPage.h index 2385d6c5..4260d2b0 100644 --- a/alphaplot/src/future/core/ProjectConfigPage.h +++ b/alphaplot/src/future/core/ProjectConfigPage.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/aspectcommands.h b/alphaplot/src/future/core/aspectcommands.h index b50c5a3e..87dc8d42 100644 --- a/alphaplot/src/future/core/aspectcommands.h +++ b/alphaplot/src/future/core/aspectcommands.h @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/column/Column.cpp b/alphaplot/src/future/core/column/Column.cpp index 5e161976..fab2eae0 100644 --- a/alphaplot/src/future/core/column/Column.cpp +++ b/alphaplot/src/future/core/column/Column.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/column/Column.h b/alphaplot/src/future/core/column/Column.h index 97af6d54..c9d9de13 100644 --- a/alphaplot/src/future/core/column/Column.h +++ b/alphaplot/src/future/core/column/Column.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/column/ColumnPrivate.cpp b/alphaplot/src/future/core/column/ColumnPrivate.cpp index 4dcdf41e..45443a35 100644 --- a/alphaplot/src/future/core/column/ColumnPrivate.cpp +++ b/alphaplot/src/future/core/column/ColumnPrivate.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/column/ColumnPrivate.h b/alphaplot/src/future/core/column/ColumnPrivate.h index 0a0cbc0f..9cf1dd7b 100644 --- a/alphaplot/src/future/core/column/ColumnPrivate.h +++ b/alphaplot/src/future/core/column/ColumnPrivate.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/column/columncommands.cpp b/alphaplot/src/future/core/column/columncommands.cpp index 1c14a0f6..6e235876 100644 --- a/alphaplot/src/future/core/column/columncommands.cpp +++ b/alphaplot/src/future/core/column/columncommands.cpp @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/column/columncommands.h b/alphaplot/src/future/core/column/columncommands.h index 95b53d94..5521d722 100644 --- a/alphaplot/src/future/core/column/columncommands.h +++ b/alphaplot/src/future/core/column/columncommands.h @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/datatypes/DateTime2DoubleFilter.h b/alphaplot/src/future/core/datatypes/DateTime2DoubleFilter.h index 89b841cf..9f0291f8 100644 --- a/alphaplot/src/future/core/datatypes/DateTime2DoubleFilter.h +++ b/alphaplot/src/future/core/datatypes/DateTime2DoubleFilter.h @@ -14,7 +14,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/datatypes/DateTime2StringFilter.cpp b/alphaplot/src/future/core/datatypes/DateTime2StringFilter.cpp index f1aa29ce..b8be6e9d 100644 --- a/alphaplot/src/future/core/datatypes/DateTime2StringFilter.cpp +++ b/alphaplot/src/future/core/datatypes/DateTime2StringFilter.cpp @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/datatypes/DateTime2StringFilter.h b/alphaplot/src/future/core/datatypes/DateTime2StringFilter.h index 11de1e98..e3981b76 100644 --- a/alphaplot/src/future/core/datatypes/DateTime2StringFilter.h +++ b/alphaplot/src/future/core/datatypes/DateTime2StringFilter.h @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -31,7 +31,7 @@ #define DATE_TIME2STRING_FILTER_H #include -#include +#include #include "core/AbstractSimpleFilter.h" diff --git a/alphaplot/src/future/core/datatypes/DayOfWeek2DoubleFilter.h b/alphaplot/src/future/core/datatypes/DayOfWeek2DoubleFilter.h index 9058eb5d..77f5083a 100644 --- a/alphaplot/src/future/core/datatypes/DayOfWeek2DoubleFilter.h +++ b/alphaplot/src/future/core/datatypes/DayOfWeek2DoubleFilter.h @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/datatypes/Double2DateTimeFilter.cpp b/alphaplot/src/future/core/datatypes/Double2DateTimeFilter.cpp index ddd4b0d4..772679a2 100644 --- a/alphaplot/src/future/core/datatypes/Double2DateTimeFilter.cpp +++ b/alphaplot/src/future/core/datatypes/Double2DateTimeFilter.cpp @@ -11,7 +11,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/datatypes/Double2DateTimeFilter.h b/alphaplot/src/future/core/datatypes/Double2DateTimeFilter.h index 49255415..da4f301a 100644 --- a/alphaplot/src/future/core/datatypes/Double2DateTimeFilter.h +++ b/alphaplot/src/future/core/datatypes/Double2DateTimeFilter.h @@ -11,7 +11,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/datatypes/Double2DayOfWeekFilter.h b/alphaplot/src/future/core/datatypes/Double2DayOfWeekFilter.h index 06923484..c8003030 100644 --- a/alphaplot/src/future/core/datatypes/Double2DayOfWeekFilter.h +++ b/alphaplot/src/future/core/datatypes/Double2DayOfWeekFilter.h @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/datatypes/Double2MonthFilter.h b/alphaplot/src/future/core/datatypes/Double2MonthFilter.h index 0f89517d..b89bb2cc 100644 --- a/alphaplot/src/future/core/datatypes/Double2MonthFilter.h +++ b/alphaplot/src/future/core/datatypes/Double2MonthFilter.h @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/datatypes/Double2StringFilter.cpp b/alphaplot/src/future/core/datatypes/Double2StringFilter.cpp index f8ec7c95..263b2f42 100644 --- a/alphaplot/src/future/core/datatypes/Double2StringFilter.cpp +++ b/alphaplot/src/future/core/datatypes/Double2StringFilter.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/datatypes/Double2StringFilter.h b/alphaplot/src/future/core/datatypes/Double2StringFilter.h index cae06490..f74aab53 100644 --- a/alphaplot/src/future/core/datatypes/Double2StringFilter.h +++ b/alphaplot/src/future/core/datatypes/Double2StringFilter.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/datatypes/Month2DoubleFilter.h b/alphaplot/src/future/core/datatypes/Month2DoubleFilter.h index e6903e12..b5e099e5 100644 --- a/alphaplot/src/future/core/datatypes/Month2DoubleFilter.h +++ b/alphaplot/src/future/core/datatypes/Month2DoubleFilter.h @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/datatypes/NumericDateTimeBaseFilter.cpp b/alphaplot/src/future/core/datatypes/NumericDateTimeBaseFilter.cpp index 3158fbeb..99e92f18 100644 --- a/alphaplot/src/future/core/datatypes/NumericDateTimeBaseFilter.cpp +++ b/alphaplot/src/future/core/datatypes/NumericDateTimeBaseFilter.cpp @@ -11,7 +11,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/datatypes/NumericDateTimeBaseFilter.h b/alphaplot/src/future/core/datatypes/NumericDateTimeBaseFilter.h index 9c940fd8..4bfc5e47 100644 --- a/alphaplot/src/future/core/datatypes/NumericDateTimeBaseFilter.h +++ b/alphaplot/src/future/core/datatypes/NumericDateTimeBaseFilter.h @@ -11,7 +11,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/datatypes/SimpleCopyThroughFilter.h b/alphaplot/src/future/core/datatypes/SimpleCopyThroughFilter.h index caac6622..3e9b2540 100644 --- a/alphaplot/src/future/core/datatypes/SimpleCopyThroughFilter.h +++ b/alphaplot/src/future/core/datatypes/SimpleCopyThroughFilter.h @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/datatypes/String2DateTimeFilter.cpp b/alphaplot/src/future/core/datatypes/String2DateTimeFilter.cpp index 5b7e76e6..1faf2f51 100644 --- a/alphaplot/src/future/core/datatypes/String2DateTimeFilter.cpp +++ b/alphaplot/src/future/core/datatypes/String2DateTimeFilter.cpp @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -67,9 +67,9 @@ QDateTime String2DateTimeFilter::dateTimeAt(int row) const { strings = strings.at(0).split(" ", Qt::SkipEmptyParts); #else QStringList strings = - input_value.simplified().split(",", QString::SkipEmptyParts); + input_value.simplified().split(",", Qt::SkipEmptyParts); if (strings.size() == 1) - strings = strings.at(0).split(" ", QString::SkipEmptyParts); + strings = strings.at(0).split(" ", Qt::SkipEmptyParts); #endif if (strings.size() < 1) diff --git a/alphaplot/src/future/core/datatypes/String2DateTimeFilter.h b/alphaplot/src/future/core/datatypes/String2DateTimeFilter.h index a1ad8d7a..a43ce33d 100644 --- a/alphaplot/src/future/core/datatypes/String2DateTimeFilter.h +++ b/alphaplot/src/future/core/datatypes/String2DateTimeFilter.h @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/datatypes/String2DayOfWeekFilter.h b/alphaplot/src/future/core/datatypes/String2DayOfWeekFilter.h index b8933dc0..3bff7684 100644 --- a/alphaplot/src/future/core/datatypes/String2DayOfWeekFilter.h +++ b/alphaplot/src/future/core/datatypes/String2DayOfWeekFilter.h @@ -14,7 +14,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/datatypes/String2DoubleFilter.h b/alphaplot/src/future/core/datatypes/String2DoubleFilter.h index ead1fd46..8e5540d1 100644 --- a/alphaplot/src/future/core/datatypes/String2DoubleFilter.h +++ b/alphaplot/src/future/core/datatypes/String2DoubleFilter.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -116,7 +116,7 @@ class String2DoubleFilter : public AbstractSimpleFilter { auto tstr = QString(str); if (accept_any_decimal_separator) { QChar decimalSeparator = - locale.decimalPoint(); // get the decimal separator for this locale + locale.decimalPoint().at(0); // get the decimal separator for this locale QChar foreignSeparator = decimalSeparator; // safeguard initialization just in case // there are other decimal separators. diff --git a/alphaplot/src/future/core/datatypes/String2MonthFilter.h b/alphaplot/src/future/core/datatypes/String2MonthFilter.h index 138924f0..a8f94ff0 100644 --- a/alphaplot/src/future/core/datatypes/String2MonthFilter.h +++ b/alphaplot/src/future/core/datatypes/String2MonthFilter.h @@ -14,7 +14,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/future_Folder.cpp b/alphaplot/src/future/core/future_Folder.cpp index 30576376..a784e219 100644 --- a/alphaplot/src/future/core/future_Folder.cpp +++ b/alphaplot/src/future/core/future_Folder.cpp @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/future_Folder.h b/alphaplot/src/future/core/future_Folder.h index a66b78d5..baf4694f 100644 --- a/alphaplot/src/future/core/future_Folder.h +++ b/alphaplot/src/future/core/future_Folder.h @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/core/interfaces.h b/alphaplot/src/future/core/interfaces.h index 9f974c7b..9b4f258a 100644 --- a/alphaplot/src/future/core/interfaces.h +++ b/alphaplot/src/future/core/interfaces.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/lib/ActionManager.cpp b/alphaplot/src/future/lib/ActionManager.cpp index dd36680c..50dbb7a6 100644 --- a/alphaplot/src/future/lib/ActionManager.cpp +++ b/alphaplot/src/future/lib/ActionManager.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/lib/ActionManager.h b/alphaplot/src/future/lib/ActionManager.h index 203ecf18..e44dc7df 100644 --- a/alphaplot/src/future/lib/ActionManager.h +++ b/alphaplot/src/future/lib/ActionManager.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/lib/ConfigPageWidget.cpp b/alphaplot/src/future/lib/ConfigPageWidget.cpp index 0e792f68..5bd63e44 100644 --- a/alphaplot/src/future/lib/ConfigPageWidget.cpp +++ b/alphaplot/src/future/lib/ConfigPageWidget.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/lib/ConfigPageWidget.h b/alphaplot/src/future/lib/ConfigPageWidget.h index b4fe3352..c6157996 100644 --- a/alphaplot/src/future/lib/ConfigPageWidget.h +++ b/alphaplot/src/future/lib/ConfigPageWidget.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/lib/Interval.h b/alphaplot/src/future/lib/Interval.h index c267a03f..3244fbae 100644 --- a/alphaplot/src/future/lib/Interval.h +++ b/alphaplot/src/future/lib/Interval.h @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/lib/IntervalAttribute.h b/alphaplot/src/future/lib/IntervalAttribute.h index cddef5c8..db73a072 100644 --- a/alphaplot/src/future/lib/IntervalAttribute.h +++ b/alphaplot/src/future/lib/IntervalAttribute.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/lib/XmlStreamReader.cpp b/alphaplot/src/future/lib/XmlStreamReader.cpp index 71553929..9733f659 100644 --- a/alphaplot/src/future/lib/XmlStreamReader.cpp +++ b/alphaplot/src/future/lib/XmlStreamReader.cpp @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -183,7 +183,7 @@ QPair XmlStreamReader::readFont(bool* ok) { // size int weight = readAttributeInt("weight", ok); if (ok) - pair.first.setWeight(weight); + pair.first.setWeight(static_cast(weight)); else raiseWarning("QFont weight property setting error"); // bold diff --git a/alphaplot/src/future/lib/XmlStreamReader.h b/alphaplot/src/future/lib/XmlStreamReader.h index a7fec425..02988905 100644 --- a/alphaplot/src/future/lib/XmlStreamReader.h +++ b/alphaplot/src/future/lib/XmlStreamReader.h @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/lib/macros.h b/alphaplot/src/future/lib/macros.h index 92195f92..8f72efba 100644 --- a/alphaplot/src/future/lib/macros.h +++ b/alphaplot/src/future/lib/macros.h @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/matrix/MatrixModel.cpp b/alphaplot/src/future/matrix/MatrixModel.cpp index 8f80bb41..5bae9fd8 100644 --- a/alphaplot/src/future/matrix/MatrixModel.cpp +++ b/alphaplot/src/future/matrix/MatrixModel.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/matrix/MatrixModel.h b/alphaplot/src/future/matrix/MatrixModel.h index 196c449c..c4e81d23 100644 --- a/alphaplot/src/future/matrix/MatrixModel.h +++ b/alphaplot/src/future/matrix/MatrixModel.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/matrix/MatrixView.cpp b/alphaplot/src/future/matrix/MatrixView.cpp index 39bd120c..edfa557d 100644 --- a/alphaplot/src/future/matrix/MatrixView.cpp +++ b/alphaplot/src/future/matrix/MatrixView.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/matrix/MatrixView.h b/alphaplot/src/future/matrix/MatrixView.h index 8c0cba38..23cf6fe7 100644 --- a/alphaplot/src/future/matrix/MatrixView.h +++ b/alphaplot/src/future/matrix/MatrixView.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/matrix/future_Matrix.cpp b/alphaplot/src/future/matrix/future_Matrix.cpp index 551859d7..1c4bd437 100644 --- a/alphaplot/src/future/matrix/future_Matrix.cpp +++ b/alphaplot/src/future/matrix/future_Matrix.cpp @@ -15,7 +15,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -264,7 +264,7 @@ void Matrix::pasteIntoSelection() { if (mimeData->hasText()) { QString input_str = QString(clipboard->text()); QList cell_texts; - QStringList input_rows(input_str.split(QRegExp("\\n|\\r\\n|\\r"))); + QStringList input_rows(input_str.split(QRegularExpression("\\n|\\r\\n|\\r"))); input_row_count = input_rows.count(); input_col_count = 0; for (int i = 0; i < input_row_count; i++) { @@ -792,7 +792,8 @@ void Matrix::copy(Matrix *other) { setDisplayedDigits(other->displayedDigits()); setFormula(other->formula()); d_matrix_private->blockChangeSignals(false); - emit dataChanged(0, 0, rows - 1, columns - 1); + if (rows > 0 && columns > 0) + emit dataChanged(0, 0, rows - 1, columns - 1); if (d_view) d_view->rereadSectionSizes(); endMacro(); RESET_CURSOR; diff --git a/alphaplot/src/future/matrix/future_Matrix.h b/alphaplot/src/future/matrix/future_Matrix.h index f22d75c6..599fa890 100644 --- a/alphaplot/src/future/matrix/future_Matrix.h +++ b/alphaplot/src/future/matrix/future_Matrix.h @@ -15,7 +15,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/matrix/matrixcommands.cpp b/alphaplot/src/future/matrix/matrixcommands.cpp index 7b2b3407..5c52c8b7 100644 --- a/alphaplot/src/future/matrix/matrixcommands.cpp +++ b/alphaplot/src/future/matrix/matrixcommands.cpp @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/matrix/matrixcommands.h b/alphaplot/src/future/matrix/matrixcommands.h index fa496457..0e4378a5 100644 --- a/alphaplot/src/future/matrix/matrixcommands.h +++ b/alphaplot/src/future/matrix/matrixcommands.h @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/table/AsciiTableImportFilter.cpp b/alphaplot/src/future/table/AsciiTableImportFilter.cpp index 0603603b..3fec4fc5 100644 --- a/alphaplot/src/future/table/AsciiTableImportFilter.cpp +++ b/alphaplot/src/future/table/AsciiTableImportFilter.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/table/AsciiTableImportFilter.h b/alphaplot/src/future/table/AsciiTableImportFilter.h index 30d80824..9c60897c 100644 --- a/alphaplot/src/future/table/AsciiTableImportFilter.h +++ b/alphaplot/src/future/table/AsciiTableImportFilter.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/table/TableCommentsHeaderModel.cpp b/alphaplot/src/future/table/TableCommentsHeaderModel.cpp index 8c0dc683..533ced4a 100644 --- a/alphaplot/src/future/table/TableCommentsHeaderModel.cpp +++ b/alphaplot/src/future/table/TableCommentsHeaderModel.cpp @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/table/TableCommentsHeaderModel.h b/alphaplot/src/future/table/TableCommentsHeaderModel.h index c74cdbc3..323320ae 100644 --- a/alphaplot/src/future/table/TableCommentsHeaderModel.h +++ b/alphaplot/src/future/table/TableCommentsHeaderModel.h @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/table/TableDoubleHeaderView.cpp b/alphaplot/src/future/table/TableDoubleHeaderView.cpp index 975fa951..83f75184 100644 --- a/alphaplot/src/future/table/TableDoubleHeaderView.cpp +++ b/alphaplot/src/future/table/TableDoubleHeaderView.cpp @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -141,14 +141,20 @@ void TableDoubleHeaderView::showComments(bool on) { void TableDoubleHeaderView::refresh() { // adjust geometry and repaint header (still looking for a more elegant // solution) + bool slaveSignalsBlocked = d_slave->blockSignals(true); d_slave->setStretchLastSection( true); // ugly hack (flaw in Qt? Does anyone know a better way?) d_slave->updateGeometry(); d_slave->setStretchLastSection(false); // ugly hack part 2 + d_slave->blockSignals(slaveSignalsBlocked); + + bool masterSignalsBlocked = blockSignals(true); setStretchLastSection( true); // ugly hack (flaw in Qt? Does anyone know a better way?) updateGeometry(); setStretchLastSection(false); // ugly hack part 2 + blockSignals(masterSignalsBlocked); + update(); } diff --git a/alphaplot/src/future/table/TableDoubleHeaderView.h b/alphaplot/src/future/table/TableDoubleHeaderView.h index 7a7aa9c9..4a4b9c5f 100644 --- a/alphaplot/src/future/table/TableDoubleHeaderView.h +++ b/alphaplot/src/future/table/TableDoubleHeaderView.h @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/table/TableItemDelegate.cpp b/alphaplot/src/future/table/TableItemDelegate.cpp index 93c45f1c..89c8c8ab 100644 --- a/alphaplot/src/future/table/TableItemDelegate.cpp +++ b/alphaplot/src/future/table/TableItemDelegate.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/table/TableItemDelegate.h b/alphaplot/src/future/table/TableItemDelegate.h index 6c747ca8..f8447888 100644 --- a/alphaplot/src/future/table/TableItemDelegate.h +++ b/alphaplot/src/future/table/TableItemDelegate.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/table/TableModel.cpp b/alphaplot/src/future/table/TableModel.cpp index c004d102..81a33a8c 100644 --- a/alphaplot/src/future/table/TableModel.cpp +++ b/alphaplot/src/future/table/TableModel.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/table/TableModel.h b/alphaplot/src/future/table/TableModel.h index a123c7c7..872df382 100644 --- a/alphaplot/src/future/table/TableModel.h +++ b/alphaplot/src/future/table/TableModel.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/table/TableView.cpp b/alphaplot/src/future/table/TableView.cpp index 4cdab16a..0550e305 100644 --- a/alphaplot/src/future/table/TableView.cpp +++ b/alphaplot/src/future/table/TableView.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -752,6 +752,8 @@ void TableView::handleHeaderDataChanged(Qt::Orientation orientation, int first, int last) { if (orientation != Qt::Horizontal) return; + rereadSectionSizes(); + QItemSelectionModel *sel_model = d_view_widget->selectionModel(); int col = sel_model->currentIndex().column(); @@ -997,10 +999,12 @@ void TableViewWidget::updateHeaderGeometry(Qt::Orientation o, int first, Q_UNUSED(first) Q_UNUSED(last) if (o != Qt::Horizontal) return; + bool signalsBlocked = horizontalHeader()->blockSignals(true); horizontalHeader()->setStretchLastSection( true); // ugly hack (flaw in Qt? Does anyone know a better way?) horizontalHeader()->updateGeometry(); horizontalHeader()->setStretchLastSection(false); // ugly hack part 2 + horizontalHeader()->blockSignals(signalsBlocked); } void TableViewWidget::keyPressEvent(QKeyEvent *event) { @@ -1078,7 +1082,7 @@ void TableView::drawSpikinessData(QPainter *painter, QRect &rect, double yDeltaDiff = rect.height() / static_cast(yMax - yMin); // set pen - QColor color = palette().color(QPalette::Foreground); + QColor color = palette().color(QPalette::WindowText); color.setAlpha(40); painter->setPen(QPen(color, 0, Qt::SolidLine)); painter->setBrush(QBrush(color)); diff --git a/alphaplot/src/future/table/TableView.h b/alphaplot/src/future/table/TableView.h index 6b9b43b8..1d13fdec 100644 --- a/alphaplot/src/future/table/TableView.h +++ b/alphaplot/src/future/table/TableView.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/table/future_SortDialog.cpp b/alphaplot/src/future/table/future_SortDialog.cpp index a22f3447..eb2fa4c8 100644 --- a/alphaplot/src/future/table/future_SortDialog.cpp +++ b/alphaplot/src/future/table/future_SortDialog.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/table/future_SortDialog.h b/alphaplot/src/future/table/future_SortDialog.h index 46ae4e52..d7289188 100644 --- a/alphaplot/src/future/table/future_SortDialog.h +++ b/alphaplot/src/future/table/future_SortDialog.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/table/future_Table.cpp b/alphaplot/src/future/table/future_Table.cpp index c8248a7d..063cf9b6 100644 --- a/alphaplot/src/future/table/future_Table.cpp +++ b/alphaplot/src/future/table/future_Table.cpp @@ -15,7 +15,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -414,11 +415,11 @@ void Table::pasteIntoSelection() { if (mimeData->hasText()) { QString input_str = clipboard->text().trimmed(); QList cell_texts; - QStringList input_rows(input_str.split(QRegExp("\\n|\\r\\n|\\r"))); + QStringList input_rows(input_str.split(QRegularExpression("\\n|\\r\\n|\\r"))); input_row_count = input_rows.count(); input_col_count = 0; for (int i = 0; i < input_row_count; i++) { - cell_texts.append(input_rows.at(i).trimmed().split(QRegExp("\\s+"))); + cell_texts.append(input_rows.at(i).trimmed().split(QRegularExpression("\\s+"))); if (cell_texts.at(i).count() > input_col_count) input_col_count = cell_texts.at(i).count(); } @@ -587,7 +588,7 @@ void Table::fillSelectedCellsWithRandomNumbers() { switch (col_ptr->columnMode()) { case AlphaPlot::Numeric: { QVector results(last - first + 1); - for (int row = first; row <= last; row++) + for (int row = first; row <= last; row++) if (d_view->isCellSelected(row, col)) results[row - first] = #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) @@ -2135,7 +2136,8 @@ void Table::handleDataChange(const AbstractColumn *col) { int index = columnIndex(static_cast(col)); if (index != -1) { if (col->rowCount() > rowCount()) setRowCount(col->rowCount()); - emit dataChanged(0, index, col->rowCount() - 1, index); + if (col->rowCount() > 0) + emit dataChanged(0, index, col->rowCount() - 1, index); } } @@ -2149,7 +2151,7 @@ void Table::handleRowsInserted(const AbstractColumn *col, int before, int count) { Q_UNUSED(count); int index = columnIndex(static_cast(col)); - if (index != -1 && before <= col->rowCount()) + if (index != -1 && before < col->rowCount() && col->rowCount() > 0) emit dataChanged(before, index, col->rowCount() - 1, index); } @@ -2163,7 +2165,8 @@ void Table::handleRowsAboutToBeRemoved(const AbstractColumn *col, int first, void Table::handleRowsRemoved(const AbstractColumn *col, int first, int count) { Q_UNUSED(count); int index = columnIndex(static_cast(col)); - if (index != -1) emit dataChanged(first, index, col->rowCount() - 1, index); + if (index != -1 && first < col->rowCount() && col->rowCount() > 0) + emit dataChanged(first, index, col->rowCount() - 1, index); } void Table::connectColumn(const Column *col) { diff --git a/alphaplot/src/future/table/future_Table.h b/alphaplot/src/future/table/future_Table.h index 6d264db4..d9cf7dff 100644 --- a/alphaplot/src/future/table/future_Table.h +++ b/alphaplot/src/future/table/future_Table.h @@ -15,7 +15,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/table/tablecommands.cpp b/alphaplot/src/future/table/tablecommands.cpp index 54ed06f9..b679c89a 100644 --- a/alphaplot/src/future/table/tablecommands.cpp +++ b/alphaplot/src/future/table/tablecommands.cpp @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/future/table/tablecommands.h b/alphaplot/src/future/table/tablecommands.h index 23840dc6..30f05459 100644 --- a/alphaplot/src/future/table/tablecommands.h +++ b/alphaplot/src/future/table/tablecommands.h @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/globals.cpp b/alphaplot/src/globals.cpp index 87bfb1d4..749fe2db 100644 --- a/alphaplot/src/globals.cpp +++ b/alphaplot/src/globals.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -37,11 +37,11 @@ #include #include -const int AlphaPlot::AlphaPlot_versionNo = 1022022; -const char* AlphaPlot::AlphaPlot_version = "1.02"; +const int AlphaPlot::AlphaPlot_versionNo = 1030000; +const char* AlphaPlot::AlphaPlot_version = "1.3.0"; const char* AlphaPlot::extra_version = "stable"; const QDate AlphaPlot::release_date = - QDate::fromString(QString("18-01-2022"), "dd-MM-yyyy"); + QDate::fromString(QString("28-03-2026"), "dd-MM-yyyy"); const char* AlphaPlot::homepage_Uri = "https://alphaplot.sourceforge.io/"; const char* AlphaPlot::wiki_Uri = "https://alphaplot.sourceforge.io/wiki"; const char* AlphaPlot::forum_Uri = diff --git a/alphaplot/src/globals.h b/alphaplot/src/globals.h index 7488b5ae..3c462ed3 100644 --- a/alphaplot/src/globals.h +++ b/alphaplot/src/globals.h @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/main.cpp b/alphaplot/src/main.cpp index b1d12794..bfec5e5e 100644 --- a/alphaplot/src/main.cpp +++ b/alphaplot/src/main.cpp @@ -17,11 +17,16 @@ Description : AlphaPlot main function */ -#include #include +#include #include +#include +#include #include -#include +#include +#include +#include +#include #include #include "ApplicationWindow.h" @@ -55,10 +60,6 @@ General format used through out the project should be Google style(clang format) with a line wrap of 80 characters. */ -class Delay : public QThread { - public: - static void sleep(unsigned long secs) { QThread::sleep(secs); } -}; struct Application : public QApplication { Application(int& argc, char** argv); @@ -121,6 +122,12 @@ void logOutput(QtMsgType type, const QMessageLogContext& context, int main(int argc, char** argv) { qInstallMessageHandler(logOutput); + +#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) + // Force X11 (xcb) on Linux to avoid Wayland QtDataVisualization bugs + qputenv("QT_QPA_PLATFORM", "xcb"); +#endif + #ifdef Q_OS_WIN // solves high density dpi scaling in windows // https://vicrucann.github.io/tutorials/osg-qt-high-dpi/ @@ -129,7 +136,6 @@ int main(int argc, char** argv) { #endif // Q_OS_WIN // https://vicrucann.github.io/tutorials/osg-qt-high-dpi/ - QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); Application* app = new Application(argc, argv); // icon initiation (mandatory) @@ -149,13 +155,17 @@ int main(int argc, char** argv) { QPixmap pixmap(":splash/splash.png"); QSplashScreen* splash = new QSplashScreen(pixmap); if (args.count() == 0) { + // Close splashscreen after 2 seconds splash->show(); - // Close splashscreen after 3 sec - Delay::sleep(3); + QElapsedTimer splashTimer; + splashTimer.start(); + while (splashTimer.elapsed() < 2000) { + app->processEvents(); + QThread::msleep(10); + } } ApplicationWindow* mw = new ApplicationWindow(); - // Process more events here before starting app. mw->applyUserSettings(); mw->newTable(); mw->savedProject(); diff --git a/alphaplot/src/plotcommon/widgets/ImageExportDialog.cpp b/alphaplot/src/plotcommon/widgets/ImageExportDialog.cpp index 4f888371..8cca9f31 100644 --- a/alphaplot/src/plotcommon/widgets/ImageExportDialog.cpp +++ b/alphaplot/src/plotcommon/widgets/ImageExportDialog.cpp @@ -14,7 +14,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/plotcommon/widgets/ImageExportDialog.h b/alphaplot/src/plotcommon/widgets/ImageExportDialog.h index 7ed9e8db..3868c20f 100644 --- a/alphaplot/src/plotcommon/widgets/ImageExportDialog.h +++ b/alphaplot/src/plotcommon/widgets/ImageExportDialog.h @@ -14,7 +14,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/scripting/MuParserScript.cpp b/alphaplot/src/scripting/MuParserScript.cpp index 5d915276..a48e8e06 100644 --- a/alphaplot/src/scripting/MuParserScript.cpp +++ b/alphaplot/src/scripting/MuParserScript.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -38,8 +38,7 @@ #include "Folder.h" #include #include -#include -#include +#include /** * \class MuParserScript @@ -207,15 +206,15 @@ MuParserScript::MuParserScript(ScriptingEnv *environment, const QString &code, : (localestring == QLocale(QLocale::French).name()) ? locale = QLocale(QLocale::French) : locale = QLocale::system(); - QChar decimalseperator = locale.decimalPoint(); - QChar groupseperator = locale.groupSeparator(); + QChar decimalseperator = locale.decimalPoint().at(0); + QChar groupseperator = locale.groupSeparator().at(0); QChar argseperator = QChar(','); if(decimalseperator != QChar(',') && groupseperator != QChar(',')) argseperator = QChar(','); else if(decimalseperator != QChar(';') && groupseperator != QChar(';')) argseperator = QChar(';'); - m_parser.SetDecSep(locale.decimalPoint().toLatin1()); - m_parser.SetThousandsSep(locale.groupSeparator().toLatin1()); + m_parser.SetDecSep(locale.decimalPoint().at(0).toLatin1()); + m_parser.SetThousandsSep(locale.groupSeparator().at(0).toLatin1()); // redefine characters for operators to include ";" static const char opChars[] = @@ -515,7 +514,7 @@ Column *MuParserScript::resolveColumnPath(const QString &path) { // Split path into components. // While escape handling would be possible using a regular expression, it // would require - // lookbehind assertions, which are currently not supported by QRegExp. Thus, + // lookbehind assertions, which are currently not supported by QRegularExpression. Thus, // we can't simply // use QString::split() and have to explicitly loop over the characters in // path. @@ -618,18 +617,19 @@ Column *MuParserScript::resolveColumnPath(const QString &path) { * argument of the new column() and cell() functions (see resolveColumnPath()). */ bool MuParserScript::translateLegacyFunctions(QString &input) { - QRegExp legacyFunction("(\\W||^)(col|tablecol|cell)\\s*\\("); + QRegularExpression legacyFunction("(\\W|^)(col|tablecol|cell)\\s*\\("); - int functionStart = legacyFunction.indexIn(input, 0); - while (functionStart != -1) { + QRegularExpressionMatch match = legacyFunction.match(input); + while (match.hasMatch()) { + int functionStart = match.capturedStart(); QStringList arguments; int functionEnd = functionStart; // initialization is a failsafe QString replacement; // parse arguments of function QString currentArgument; - for (int i = functionStart + legacyFunction.matchedLength(), - parenthesisLevel = 1; + int parenthesisLevel = 1; + for (int i = functionStart + match.capturedLength(); parenthesisLevel > 0 && i < input.size(); i++) { switch (input.at(i).toLatin1()) { case '"': @@ -673,7 +673,7 @@ bool MuParserScript::translateLegacyFunctions(QString &input) { // select replacement function call Table *table = qobject_cast
(Context); - if (legacyFunction.cap(2) == "col") { + if (match.captured(2) == "col") { QString columnArgument; bool numericColumn = false; if (arguments.at(0).startsWith("\"")) { @@ -704,7 +704,7 @@ bool MuParserScript::translateLegacyFunctions(QString &input) { } else replacement = QString("column") + (numericColumn ? "_" : "") + "(" + columnArgument + ")"; - } else if (legacyFunction.cap(2) == "tablecol") { + } else if (match.captured(2) == "tablecol") { // assert number of arguments == 2 if (arguments.size() != 2) { emit_error(tr("tablecol: wrong number of arguments (need 2, got %1)") @@ -734,7 +734,7 @@ bool MuParserScript::translateLegacyFunctions(QString &input) { replacement = QString("column__(") + arguments.at(0) + "," + rowArgument + ")"; } - } else { // legacyFunction.cap(2) == "cell" + } else { // match.captured(2) == "cell" // assert number of arguments == 2 if (arguments.size() != 2) { emit_error(tr("cell: wrong number of arguments (need 2, got %1)") @@ -761,7 +761,7 @@ bool MuParserScript::translateLegacyFunctions(QString &input) { } // do replacement - if (legacyFunction.cap(1).isEmpty()) + if (match.captured(1).isEmpty()) // matched with ^, not \W (lookbehind assertion would be darn handy...) input.replace(functionStart, functionEnd - functionStart + 1, replacement); @@ -770,9 +770,8 @@ bool MuParserScript::translateLegacyFunctions(QString &input) { input.replace(functionStart + 1, functionEnd - functionStart, replacement); // search for next match, starting at the end of the replaced text - functionStart = - legacyFunction.indexIn(input, functionStart + replacement.length()); - } // while (functionStart != -1) + match = legacyFunction.match(input, functionStart + replacement.length()); + } // while (match.hasMatch()) return true; } @@ -812,7 +811,7 @@ bool MuParserScript::compile(bool asFunction) { intermediate.remove(commentStart, intermediate.size() - commentStart); // simplify statement separators - intermediate.replace(QRegExp("([;\\n]\\s*)+"), ", "); + intermediate.replace(QRegularExpression("([;\\n]\\s*)+"), ", "); // recursively translate legacy functions col(), tablecol() and cell() if (Context && Context->inherits("Table")) diff --git a/alphaplot/src/scripting/MuParserScript.h b/alphaplot/src/scripting/MuParserScript.h index 1522f1d2..951f8145 100644 --- a/alphaplot/src/scripting/MuParserScript.h +++ b/alphaplot/src/scripting/MuParserScript.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/scripting/MuParserScripting.cpp b/alphaplot/src/scripting/MuParserScripting.cpp index f0c64b74..faf0d08c 100644 --- a/alphaplot/src/scripting/MuParserScripting.cpp +++ b/alphaplot/src/scripting/MuParserScripting.cpp @@ -16,7 +16,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/scripting/MuParserScripting.h b/alphaplot/src/scripting/MuParserScripting.h index 56f8a8ae..68f2ba87 100644 --- a/alphaplot/src/scripting/MuParserScripting.h +++ b/alphaplot/src/scripting/MuParserScripting.h @@ -16,7 +16,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/scripting/MyParser.cpp b/alphaplot/src/scripting/MyParser.cpp index 4a98bd8d..3280876e 100644 --- a/alphaplot/src/scripting/MyParser.cpp +++ b/alphaplot/src/scripting/MyParser.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/scripting/MyParser.h b/alphaplot/src/scripting/MyParser.h index 733844cc..484b870c 100644 --- a/alphaplot/src/scripting/MyParser.h +++ b/alphaplot/src/scripting/MyParser.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/scripting/PythonScript.cpp b/alphaplot/src/scripting/PythonScript.cpp index d21252c8..5836cfe6 100644 --- a/alphaplot/src/scripting/PythonScript.cpp +++ b/alphaplot/src/scripting/PythonScript.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/scripting/PythonScript.h b/alphaplot/src/scripting/PythonScript.h index 09477198..6f2008f7 100644 --- a/alphaplot/src/scripting/PythonScript.h +++ b/alphaplot/src/scripting/PythonScript.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/scripting/PythonScripting.cpp b/alphaplot/src/scripting/PythonScripting.cpp index d0938551..7b54b2ff 100644 --- a/alphaplot/src/scripting/PythonScripting.cpp +++ b/alphaplot/src/scripting/PythonScripting.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/scripting/PythonScripting.h b/alphaplot/src/scripting/PythonScripting.h index 68a89fd2..63e7aa4e 100644 --- a/alphaplot/src/scripting/PythonScripting.h +++ b/alphaplot/src/scripting/PythonScripting.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/scripting/Script.cpp b/alphaplot/src/scripting/Script.cpp index 4795b1fa..814cbc9a 100644 --- a/alphaplot/src/scripting/Script.cpp +++ b/alphaplot/src/scripting/Script.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/scripting/Script.h b/alphaplot/src/scripting/Script.h index 60eb26c2..e39a6f0a 100644 --- a/alphaplot/src/scripting/Script.h +++ b/alphaplot/src/scripting/Script.h @@ -14,7 +14,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/scripting/ScriptEdit.cpp b/alphaplot/src/scripting/ScriptEdit.cpp index 970733ba..e1a4a607 100644 --- a/alphaplot/src/scripting/ScriptEdit.cpp +++ b/alphaplot/src/scripting/ScriptEdit.cpp @@ -15,7 +15,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -329,7 +329,9 @@ QString ScriptEdit::importASCII(const QString &filename) { return QString(); } QTextStream s(&file); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) s.setCodec(QTextCodec::codecForName("UTF-8")); +#endif while (!s.atEnd()) insertPlainText(s.readLine() + "\n"); file.close(); return f; @@ -370,7 +372,9 @@ QString ScriptEdit::exportASCII(const QString &filename) { } QTextStream t(&f); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) t.setCodec(QTextCodec::codecForName("UTF-8")); +#endif t << toPlainText(); f.close(); } diff --git a/alphaplot/src/scripting/ScriptEdit.h b/alphaplot/src/scripting/ScriptEdit.h index 2df48112..7129fe01 100644 --- a/alphaplot/src/scripting/ScriptEdit.h +++ b/alphaplot/src/scripting/ScriptEdit.h @@ -14,7 +14,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/scripting/ScriptingEnv.cpp b/alphaplot/src/scripting/ScriptingEnv.cpp index 06216085..356f80fb 100644 --- a/alphaplot/src/scripting/ScriptingEnv.cpp +++ b/alphaplot/src/scripting/ScriptingEnv.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/scripting/ScriptingEnv.h b/alphaplot/src/scripting/ScriptingEnv.h index 1cb59c99..336b5d33 100644 --- a/alphaplot/src/scripting/ScriptingEnv.h +++ b/alphaplot/src/scripting/ScriptingEnv.h @@ -14,7 +14,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/scripting/ScriptingFunctions.cpp b/alphaplot/src/scripting/ScriptingFunctions.cpp index 8e73bc7c..baff167b 100644 --- a/alphaplot/src/scripting/ScriptingFunctions.cpp +++ b/alphaplot/src/scripting/ScriptingFunctions.cpp @@ -1,5 +1,4 @@ -#include -#include +#include #include #include #include @@ -11,102 +10,75 @@ #include "ScriptingFunctions.h" // ScriptingConsole print() function reimplimentation -QScriptValue print(QScriptContext *context, QScriptEngine *egne) { - if (context->argumentCount() == 0) { - context->throwError( - QObject::tr("print() should have atleast one argument")); +QJSValue print(QJSEngine *engine, QJSValue thisObject, QJSValue arguments) { + int argCount = arguments.property("length").toInt(); + if (argCount == 0) { + return engine->evaluate("Error('print() should have atleast one argument')"); } - QScriptValue result; - for (int i = 0; i < context->argumentCount(); i++) { - result = result.toString() + " " + context->argument(i).toString(); - if (context->state() == QScriptContext::ExceptionState) { - result = result.toString() + " Unhandled Exception"; - break; - } + QString result; + for (int i = 0; i < argCount; i++) { + result += " " + arguments.property(i).toString(); } - QScriptValue calleeData = context->callee().data(); - Console *console = qobject_cast(calleeData.toQObject()); + + // In QJSEngine, we set the console object via property on the function object or similar. + // We'll use the 'this' object which should be the console if we set it up that way. + Console *console = qobject_cast(thisObject.toQObject()); if (console) { - console->append(result.toString()); + console->append(result); } else { qDebug() << "Scripting console print() unable to access Console object"; return false; } - return egne->undefinedValue(); + return QJSValue(QJSValue::UndefinedValue); } // ScriptingConsole clear() function -QScriptValue clear(QScriptContext *context, QScriptEngine *egne) { - if (context->argumentCount() != 0) { - context->throwError(QObject::tr("clear() take no arguments!")); - } - QScriptValue calleeData = context->callee().data(); - Console *console = qobject_cast(calleeData.toQObject()); +QJSValue clear(QJSEngine *engine, QJSValue thisObject, QJSValue arguments) { + Q_UNUSED(arguments); + Console *console = qobject_cast(thisObject.toQObject()); if (console) { console->clearConsole(); } else { qDebug() << "Scripting console clear() unable to access Console object"; return false; } - return egne->undefinedValue(); + return QJSValue(QJSValue::UndefinedValue); } // ScriptingConsole openAproj() function -QScriptValue openProj(QScriptContext *context, QScriptEngine *egne) { - if (context->argumentCount() > 1) { - context->throwError(QObject::tr("openAproj(string) take one argument!")); - } - QScriptValue calleeData = context->callee().data(); +QJSValue openProj(QJSEngine *engine, QJSValue thisObject, QJSValue arguments) { + int argCount = arguments.property("length").toInt(); ApplicationWindow *app = - qobject_cast(calleeData.toQObject()); + qobject_cast(thisObject.toQObject()); if (app) { - if (context->argumentCount() == 0) { + if (argCount == 0) { app->openAproj(); } else { - QFileInfo fileInfo(context->argument(0).toString()); + QFileInfo fileInfo(arguments.property(0).toString()); if (fileInfo.exists()) { app->openAproj(fileInfo.absoluteFilePath()); } else { - context->throwError(QString(fileInfo.absoluteFilePath()) + - QObject::tr(" file not found!")); + return engine->evaluate(QString("Error('%1 file not found!')").arg(fileInfo.absoluteFilePath())); } } } else { - qDebug() << "Scripting console clear() unable to access Console object"; + qDebug() << "Scripting console openProj() unable to access ApplicationWindow object"; return false; } - return egne->undefinedValue(); + return QJSValue(QJSValue::UndefinedValue); } -QScriptValue collectGarbage(QScriptContext *context, QScriptEngine *egne) { - if (context->argumentCount() != 0) { - context->throwError(QObject::tr("collectGarbage() take no arguments!")); - } - egne->collectGarbage(); - return egne->undefinedValue(); +QJSValue collectGarbage(QJSEngine *engine, QJSValue thisObject, QJSValue arguments) { + Q_UNUSED(thisObject); + Q_UNUSED(arguments); + engine->collectGarbage(); + return QJSValue(QJSValue::UndefinedValue); } -QScriptValue attachDebugger(QScriptContext *context, QScriptEngine *egne) { - if (context->argumentCount() != 1) { - context->throwError(QObject::tr("attachDebugger(bool) take one argument!")); - } - if (!context->argument(0).isBool()) { - context->throwError( - QObject::tr("argument should be a bool attachDebugger(bool)")); - } - QScriptValue calleeData = context->callee().data(); - ConsoleWidget *consoleWidget = - qobject_cast(calleeData.toQObject()); - if (consoleWidget) { - if (context->argument(0).toBool()) { - consoleWidget->debugger->attachTo(egne); - } else { - consoleWidget->debugger->detach(); - } - } else { - qDebug() << "Scripting console attachDebugger(bool) unable to access " - "Console object"; - return false; - } - return egne->undefinedValue(); +QJSValue attachDebugger(QJSEngine *engine, QJSValue thisObject, QJSValue arguments) { + Q_UNUSED(engine); + Q_UNUSED(thisObject); + Q_UNUSED(arguments); + qDebug() << "Scripting console attachDebugger(bool) is no longer available in Qt 6 (QJSEngine)"; + return QJSValue(QJSValue::UndefinedValue); } diff --git a/alphaplot/src/scripting/ScriptingFunctions.h b/alphaplot/src/scripting/ScriptingFunctions.h index 16094b6f..cafe9f22 100644 --- a/alphaplot/src/scripting/ScriptingFunctions.h +++ b/alphaplot/src/scripting/ScriptingFunctions.h @@ -1,13 +1,13 @@ #ifndef SCRIPTINGFUNCTIONS_H #define SCRIPTINGFUNCTIONS_H -#include -#include -#include -#include -#include +#include +#include <../Table.h> +#include <../Note.h> +#include <../Matrix.h> +#include <../future/core/column/Column.h> -class QScriptEngine; +class QJSEngine; class Table; // Register types @@ -22,47 +22,46 @@ Q_DECLARE_METATYPE(QVector) // Registered type to from conversion template -QScriptValue tableObjectToScriptValue(QScriptEngine *engine, +QJSValue tableObjectToScriptValue(QJSEngine *engine, const AlphaWindowObject &in) { return engine->newQObject(in); } template -void tableObjectFromScriptValue(const QScriptValue &object, +void tableObjectFromScriptValue(const QJSValue &object, AlphaWindowObject &out) { out = qobject_cast(object.toQObject()); } // Register QVector<> template -QScriptValue toScriptValue(QScriptEngine *eng, const Container &cont) +QJSValue toScriptValue(QJSEngine *eng, const Container &cont) { - QScriptValue a = eng->newArray(); - typename Container::const_iterator begin = cont.begin(); - typename Container::const_iterator end = cont.end(); + QJSValue a = eng->newArray(cont.size()); typename Container::const_iterator it; - for (it = begin; it != end; ++it) - a.setProperty(quint32(it - begin), qScriptValueFromValue(eng, *it)); + int i = 0; + for (it = cont.begin(); it != cont.end(); ++it, ++i) + a.setProperty(i, eng->toScriptValue(*it)); return a; } template -void fromScriptValue(const QScriptValue &value, Container &cont) +void fromScriptValue(const QJSValue &value, Container &cont) { - quint32 len = value.property("length").toUInt32(); + quint32 len = value.property("length").toUInt(); for (quint32 i = 0; i < len; ++i) { - QScriptValue item = value.property(i); + QJSValue item = value.property(i); typedef typename Container::value_type ContainerValue; - cont.push_back(qscriptvalue_cast(item)); + cont.push_back(item.toVariant().value()); } } // Console Basic Functions -QScriptValue print(QScriptContext *context, QScriptEngine *egne); -QScriptValue clear(QScriptContext *context, QScriptEngine *egne); -QScriptValue collectGarbage(QScriptContext *context, QScriptEngine *egne); -QScriptValue attachDebugger(QScriptContext *context, QScriptEngine *egne); +QJSValue print(QJSEngine *engine, QJSValue thisObject, QJSValue arguments); +QJSValue clear(QJSEngine *engine, QJSValue thisObject, QJSValue arguments); +QJSValue collectGarbage(QJSEngine *engine, QJSValue thisObject, QJSValue arguments); +QJSValue attachDebugger(QJSEngine *engine, QJSValue thisObject, QJSValue arguments); // Core functions -QScriptValue openProj(QScriptContext *context, QScriptEngine *egne); +QJSValue openProj(QJSEngine *engine, QJSValue thisObject, QJSValue arguments); #endif // SCRIPTINGFUNCTIONS_H diff --git a/alphaplot/src/scripting/ScriptingLangDialog.cpp b/alphaplot/src/scripting/ScriptingLangDialog.cpp index 6c2d25ba..2f5e28f7 100644 --- a/alphaplot/src/scripting/ScriptingLangDialog.cpp +++ b/alphaplot/src/scripting/ScriptingLangDialog.cpp @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/scripting/ScriptingLangDialog.h b/alphaplot/src/scripting/ScriptingLangDialog.h index 665c534c..ee93e795 100644 --- a/alphaplot/src/scripting/ScriptingLangDialog.h +++ b/alphaplot/src/scripting/ScriptingLangDialog.h @@ -13,7 +13,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/scripting/SyntaxHighlighter.cpp b/alphaplot/src/scripting/SyntaxHighlighter.cpp index 38c2871c..53b8da04 100644 --- a/alphaplot/src/scripting/SyntaxHighlighter.cpp +++ b/alphaplot/src/scripting/SyntaxHighlighter.cpp @@ -51,7 +51,7 @@ SyntaxHighlighter::SyntaxHighlighter(QTextDocument *parent) << "in" << "instanceof" << "new" - << "returm" + << "return" << "switch" << "throw" << "try" @@ -69,29 +69,29 @@ SyntaxHighlighter::SyntaxHighlighter(QTextDocument *parent) << "super"; foreach (const QString &pattern, keywords) { - rule.pattern = QRegExp("\\b" + pattern + "\\b"); + rule.pattern = QRegularExpression("\\b" + pattern + "\\b"); rule.format = keywordFormat; highlightingRules.append(rule); } classFormat.setForeground(Qt::darkMagenta); - rule.pattern = QRegExp("\\bMath\\b"); + rule.pattern = QRegularExpression("\\bMath\\b"); rule.format = classFormat; highlightingRules.append(rule); QTextCharFormat trueFalseFormat; trueFalseFormat.setForeground(QColor(174, 129, 255)); - rule.pattern = QRegExp("\\b(true|false|this)\\b"); + rule.pattern = QRegularExpression("\\b(true|false|this)\\b"); rule.format = trueFalseFormat; highlightingRules.append(rule); quotationFormat.setForeground(Qt::darkGreen); - rule.pattern = QRegExp("\".*\""); + rule.pattern = QRegularExpression("\".*\""); rule.format = quotationFormat; highlightingRules.append(rule); singleQuotationFormat.setForeground(Qt::darkGreen); - rule.pattern = QRegExp("'.*'"); + rule.pattern = QRegularExpression("'.*'"); rule.format = singleQuotationFormat; highlightingRules.append(rule); @@ -106,51 +106,54 @@ SyntaxHighlighter::SyntaxHighlighter(QTextDocument *parent) : keywordExcludePatterns.append(QString("|%1").arg(pattern)); } - rule.pattern = QRegExp( + rule.pattern = QRegularExpression( QString("\\b(?!(%1)+[\\s]*[/]?(?=\\())([A-Za-z0-9_]+[\\s]*[/]?(?=\\())") .arg(keywordExcludePatterns)); rule.format = functionFormat; highlightingRules.append(rule); singleLineCommentFormat.setForeground(QColor(128, 128, 128)); - rule.pattern = QRegExp("//[^\n]*"); + rule.pattern = QRegularExpression("//[^\n]*"); rule.format = singleLineCommentFormat; highlightingRules.append(rule); multiLineCommentFormat.setForeground(QColor(128, 128, 128)); - commentStartExpression = QRegExp("/\\*"); - commentEndExpression = QRegExp("\\*/"); + commentStartExpression = QRegularExpression("/\\*"); + commentEndExpression = QRegularExpression("\\*/"); } void SyntaxHighlighter::highlightBlock(const QString &text) { foreach (const HighlightingRule &rule, highlightingRules) { - QRegExp expression(rule.pattern); - int index = expression.indexIn(text); - while (index >= 0) { - int length = expression.matchedLength(); - setFormat(index, length, rule.format); - index = expression.indexIn(text, index + length); + QRegularExpressionMatchIterator matchIterator = + rule.pattern.globalMatch(text); + while (matchIterator.hasNext()) { + QRegularExpressionMatch match = matchIterator.next(); + setFormat(static_cast(match.capturedStart()), static_cast(match.capturedLength()), rule.format); } } setCurrentBlockState(0); int startIndex = 0; - if (previousBlockState() != 1) - startIndex = commentStartExpression.indexIn(text); + if (previousBlockState() != 1) { + QRegularExpressionMatch m = commentStartExpression.match(text); + startIndex = m.hasMatch() ? static_cast(m.capturedStart()) : -1; + } while (startIndex >= 0) { - int endIndex = commentEndExpression.indexIn(text, startIndex); + QRegularExpressionMatch endMatch = + commentEndExpression.match(text, startIndex); int commentLength; - if (endIndex == -1) { + if (!endMatch.hasMatch()) { setCurrentBlockState(1); commentLength = text.length() - startIndex; } else { commentLength = - endIndex - startIndex + commentEndExpression.matchedLength(); + static_cast(endMatch.capturedStart()) - startIndex + static_cast(endMatch.capturedLength()); } setFormat(startIndex, commentLength, multiLineCommentFormat); - startIndex = - commentStartExpression.indexIn(text, startIndex + commentLength); + QRegularExpressionMatch nextStart = + commentStartExpression.match(text, startIndex + commentLength); + startIndex = nextStart.hasMatch() ? static_cast(nextStart.capturedStart()) : -1; } } diff --git a/alphaplot/src/scripting/SyntaxHighlighter.h b/alphaplot/src/scripting/SyntaxHighlighter.h index b92c4edc..d73dd6d8 100644 --- a/alphaplot/src/scripting/SyntaxHighlighter.h +++ b/alphaplot/src/scripting/SyntaxHighlighter.h @@ -30,6 +30,7 @@ #define SYNTAXHIGHLIGHTER_H #include +#include class SyntaxHighlighter : public QSyntaxHighlighter { Q_OBJECT @@ -41,14 +42,14 @@ class SyntaxHighlighter : public QSyntaxHighlighter { private: struct HighlightingRule { - QRegExp pattern; + QRegularExpression pattern; QTextCharFormat format; }; QVector highlightingRules; - QRegExp commentStartExpression; - QRegExp commentEndExpression; + QRegularExpression commentStartExpression; + QRegularExpression commentEndExpression; QTextCharFormat keywordFormat; QTextCharFormat classFormat; diff --git a/alphaplot/src/scripting/customevents.h b/alphaplot/src/scripting/customevents.h index 81e8a0dc..097b821e 100644 --- a/alphaplot/src/scripting/customevents.h +++ b/alphaplot/src/scripting/customevents.h @@ -19,7 +19,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/scripting/widgets/ConsoleWidget.cpp b/alphaplot/src/scripting/widgets/ConsoleWidget.cpp index ec683335..2fe234aa 100644 --- a/alphaplot/src/scripting/widgets/ConsoleWidget.cpp +++ b/alphaplot/src/scripting/widgets/ConsoleWidget.cpp @@ -20,15 +20,15 @@ #include #include #include +#include +#include "ui_ConsoleWidget.h" -#include "../ScriptingFunctions.h" #include "scripting/widgets/Console.h" #include "ui_ConsoleWidget.h" ConsoleWidget::ConsoleWidget(QWidget *parent) : QDockWidget(parent), - engine(new QScriptEngine(this)), - debugger(new QScriptEngineDebugger(this)), + engine(new QJSEngine(this)), ui_(new Ui_ConsoleWidget), scriptGlobalObjectsModel(new QStandardItemModel(this)) { ui_->setupUi(this); @@ -53,39 +53,52 @@ ConsoleWidget::ConsoleWidget(QWidget *parent) ui_->tableView->setAlternatingRowColors(true); addScriptGlobalsToTableView(); - connect(ui_->console, &Console::command, this, &ConsoleWidget::evaluate); - - engine->setProcessEventsInterval(50); // 1 sec process interval - // Basic console functions - // print() function - QScriptValue consoleObjectValue = engine->newQObject(ui_->console); - QScriptValue consoleWidgetObjectValue = engine->newQObject(this); - QScriptValue printFunction = engine->newFunction(&print); - printFunction.setData(consoleObjectValue); - engine->globalObject().setProperty("print", printFunction); - // clear() function - QScriptValue clearFunction = engine->newFunction(&clear); - clearFunction.setData(consoleObjectValue); - engine->globalObject().setProperty("clear", clearFunction); - // collectGarbage() function - QScriptValue garbageFunction = engine->newFunction(&collectGarbage); - engine->globalObject().setProperty("collectGarbage", garbageFunction); - // attachDebugger(bool) function - QScriptValue debuggerFunction = engine->newFunction(&attachDebugger); - debuggerFunction.setData(consoleWidgetObjectValue); - engine->globalObject().setProperty("attachDebugger", debuggerFunction); + connect(ui_->console, SIGNAL(command(QString)), this, + SLOT(evaluate(QString))); + + // In Qt 6, use newQObject() to expose a QObject's Q_INVOKABLE methods to JS. + // We expose ConsoleWidget itself as the global 'Console' object. + engine->installExtensions(QJSEngine::ConsoleExtension); + QJSValue consoleHelper = engine->newQObject(this); + engine->globalObject().setProperty("Console", consoleHelper); + + // Also expose the UI console widget for direct output access + QJSValue uiConsole = engine->newQObject(ui_->console); + engine->globalObject().setProperty("_console", uiConsole); + + // Inject JS wrapper functions for backward compatibility + engine->evaluate( + "function print() {\n" + " var args = Array.prototype.slice.call(arguments);\n" + " Console.jsPrint(args.join(' '));\n" + "}\n" + "function clear() { Console.jsClear(); }\n" + "function collectGarbage() { Console.jsCollectGarbage(); }\n" + "function attachDebugger(b) { Console.jsAttachDebugger(b); }\n" + ); } ConsoleWidget::~ConsoleWidget() { delete ui_; if (engine) delete engine; - if (debugger) delete debugger; } void ConsoleWidget::printError(QString err) { ui_->console->result("muParser error: " + err, Console::Error); } +void ConsoleWidget::jsPrint(const QString &text) { + ui_->console->append(text); +} + +void ConsoleWidget::jsClear() { + ui_->console->clearConsole(); +} + +void ConsoleWidget::jsCollectGarbage() { + if (engine) engine->collectGarbage(); +} + void ConsoleWidget::setSplitterPosition(QByteArray state) { ui_->splitter->restoreState(state); } @@ -100,36 +113,34 @@ void ConsoleWidget::addScriptGlobalsToTableView() { scriptGlobalObjectsModel->setHorizontalHeaderLabels(QStringList() << "variables" << "values"); - QScriptValueIterator it(engine->globalObject()); + QJSValue globalObj = engine->globalObject(); + QJSValueIterator it(globalObj); while (it.hasNext()) { it.next(); - if (it.value().isArray()) { - // Array variables - rowPair.first = it.name() + QString("[%0]").arg( - it.value().property("length").toString()); + QString name = it.name(); + QJSValue value = it.value(); + + if (value.isArray()) { + rowPair.first = name + QString("[%0]").arg( + value.property("length").toString()); QString arrayValue; - double arrayLength = it.value().property("length").toInteger(); - for (quint32 i = 0; i < 3; i++) { - if (i < arrayLength) - arrayValue += it.value().property(i).toString() + " ,"; - } - if (arrayLength > 3) { - arrayValue += "..."; + int arrayLength = value.property("length").toInt(); + for (int j = 0; j < 3; j++) { + if (j < arrayLength) + arrayValue += value.property(j).toString() + " ,"; } + if (arrayLength > 3) arrayValue += "..."; rowPair.second = arrayValue; appendRowToTableView(rowPair); - - } else if (!it.value().isFunction() && !it.value().isObject()) { - if (it.name() != "NaN" && it.name() != "Infinity" && - it.name() != "undefined") { - // Other variables - rowPair.first = it.name(); - rowPair.second = it.value().toString(); + } else if (!value.isCallable() && !value.isObject()) { + if (name != "NaN" && name != "Infinity" && name != "undefined") { + rowPair.first = name; + rowPair.second = value.toString(); appendRowToTableView(rowPair); } - } else if (it.value().isObject() && !it.value().isFunction()) { - rowPair.first = it.name(); - rowPair.second = it.value().toString(); + } else if (value.isObject() && !value.isCallable()) { + rowPair.first = name; + rowPair.second = value.toString(); appendRowToTableView(rowPair); } } @@ -144,36 +155,32 @@ void ConsoleWidget::appendRowToTableView(QPair rowPair) { void ConsoleWidget::evaluate(QString line) { snippet.append(line); snippet += QLatin1Char('\n'); - if (engine->canEvaluate(snippet)) { - QString syntaxError; - // Check syntax errors - QScriptSyntaxCheckResult error = engine->checkSyntax(snippet); - (error.state() != QScriptSyntaxCheckResult::Valid) - ? syntaxError += error.errorMessage() + " " - : syntaxError = ""; - QScriptValue result = engine->evaluate(snippet, "line", 1); - snippet.clear(); - if (!result.isUndefined()) { - if (!result.isError()) { - ui_->console->result(result.toString(), Console::Success); - } else { - if (engine->hasUncaughtException()) { - QStringList backtrace = engine->uncaughtExceptionBacktrace(); - ui_->console->result( - syntaxError + result.toString() + " | " + backtrace.join("\n"), - Console::Error); - } else { - ui_->console->result(syntaxError + result.toString(), Console::Error); - } + + // QJSEngine doesn't have canEvaluate, we'll try to evaluate and check for errors + // but a partial input logic is harder. For now, let's just evaluate. + QJSValue result = engine->evaluate(snippet, "line", 1); + if (result.isError()) { + // If it's a syntax error that looks like partial input, we might want to continue. + // But QJSEngine makes this hard. + QString msg = result.toString(); + if (msg.contains("SyntaxError") && (msg.contains("Expected") || msg.contains("Unexpected end of input"))) { + // Likely partial input + ui_->console->partialResult(); + return; } + } + snippet.clear(); + if (!result.isUndefined()) { + if (!result.isError()) { + ui_->console->result(result.toString(), Console::Success); } else { - ui_->console->promptWithoutResult(); + ui_->console->result(result.toString(), Console::Error); } - addScriptGlobalsToTableView(); } else { - ui_->console->partialResult(); + ui_->console->promptWithoutResult(); } + addScriptGlobalsToTableView(); } void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, diff --git a/alphaplot/src/scripting/widgets/ConsoleWidget.h b/alphaplot/src/scripting/widgets/ConsoleWidget.h index 25da6b64..a6e34a46 100644 --- a/alphaplot/src/scripting/widgets/ConsoleWidget.h +++ b/alphaplot/src/scripting/widgets/ConsoleWidget.h @@ -19,8 +19,7 @@ #define CONSOLEWIDGET_H #include -#include -#include +#include #include #include @@ -34,14 +33,21 @@ class ConsoleWidget : public QDockWidget { public: explicit ConsoleWidget(QWidget *parent = nullptr); ~ConsoleWidget(); - QScriptEngine *engine; - QScriptEngineDebugger *debugger; + QJSEngine *engine; QWidget *normalTitleWidget; QWidget *hiddenTitleWidget; void printError(QString err); void setSplitterPosition(QByteArray state); QByteArray getSplitterPosition(); + // Q_INVOKABLE methods callable from JavaScript via QJSEngine + Q_INVOKABLE void jsPrint(const QString &text); + Q_INVOKABLE void jsClear(); + Q_INVOKABLE void jsCollectGarbage(); + Q_INVOKABLE void jsAttachDebugger(bool /*attach*/) { + qDebug() << "attachDebugger not available in Qt 6 (QJSEngine)"; + } + signals: void printResult(QString); diff --git a/alphaplot/src/ui/ExportDialog.cpp b/alphaplot/src/ui/ExportDialog.cpp index 5dc4f88d..8c445dbf 100644 --- a/alphaplot/src/ui/ExportDialog.cpp +++ b/alphaplot/src/ui/ExportDialog.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * @@ -140,7 +140,7 @@ void ExportDialog::accept() { sep.replace("\\s", " "); sep.replace("\\t", "\t"); - if (sep.contains(QRegExp("[0-9.eE+-]"))) { + if (sep.contains(QRegularExpression("[0-9.eE+-]"))) { QMessageBox::warning(0, tr("Import options error"), tr("The separator must not contain the following " "characters: 0-9eE.+-")); diff --git a/alphaplot/src/ui/ExportDialog.h b/alphaplot/src/ui/ExportDialog.h index b4a6cb3b..6f404dd0 100644 --- a/alphaplot/src/ui/ExportDialog.h +++ b/alphaplot/src/ui/ExportDialog.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/ui/ExtensibleFileDialog.cpp b/alphaplot/src/ui/ExtensibleFileDialog.cpp index 1486ed97..60ff70cd 100644 --- a/alphaplot/src/ui/ExtensibleFileDialog.cpp +++ b/alphaplot/src/ui/ExtensibleFileDialog.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/ui/ExtensibleFileDialog.h b/alphaplot/src/ui/ExtensibleFileDialog.h index 1ba081e6..44eaf0bb 100644 --- a/alphaplot/src/ui/ExtensibleFileDialog.h +++ b/alphaplot/src/ui/ExtensibleFileDialog.h @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * diff --git a/alphaplot/src/ui/SettingsDialog.cpp b/alphaplot/src/ui/SettingsDialog.cpp index df86e1ab..ff24439f 100644 --- a/alphaplot/src/ui/SettingsDialog.cpp +++ b/alphaplot/src/ui/SettingsDialog.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include "../core/IconLoader.h" #include "../widgets/aSettingsListView.h" diff --git a/alphaplot/src/widgets/CustomCharacterDialog.cpp b/alphaplot/src/widgets/CustomCharacterDialog.cpp index 6ed6b7bd..ea7d7717 100644 --- a/alphaplot/src/widgets/CustomCharacterDialog.cpp +++ b/alphaplot/src/widgets/CustomCharacterDialog.cpp @@ -9,8 +9,8 @@ CustomCharacterDialog::CustomCharacterDialog(QWidget *parent) : QDialog(parent), ui(new Ui_CustomCharacterDialog) { ui->setupUi(this); setWindowTitle("Custom Char"); - QRegExp rxThreeHexAtTheEnd("(?:[0-9a-fA-F]{5})"); - QRegExpValidator *validator = new QRegExpValidator(rxThreeHexAtTheEnd, this); + QRegularExpression rxThreeHexAtTheEnd("(?:[0-9a-fA-F]{5})"); + QRegularExpressionValidator *validator = new QRegularExpressionValidator(rxThreeHexAtTheEnd, this); ui->lineEdit->setValidator(validator); connect(ui->buttonBox, &QDialogButtonBox::accepted, this, [=]() { if (!ui->lineEdit->text().trimmed().isEmpty()) { diff --git a/build/arch/PKGBUILD b/build/arch/PKGBUILD index 3bd5772d..b2a343dc 100644 --- a/build/arch/PKGBUILD +++ b/build/arch/PKGBUILD @@ -6,7 +6,7 @@ pkgrel=1 pkgdesc="Application for Scientific Data Analysis and Visualization, fork of SciDavis / QtiPlot" url='http://alphaplot.sourceforge.net/' arch=('i686' 'x86_64') -license=('GPL2') +license=('GPL3') # make dependancies makedepends=('boost' 'cmake' 'qt5-tools') diff --git a/config.pri b/config.pri index 171b0d7e..f2b0bbfb 100644 --- a/config.pri +++ b/config.pri @@ -15,6 +15,10 @@ unix:isEmpty(PRESET) { # command-line argument to override } } +win32:isEmpty(PRESET) { + PRESET = win32 +} + !contains(PRESET, linux_all_static) { # Linux Desktop integration unix:INSTALLS += desktop_entry mime_package mime_link icons } @@ -78,12 +82,12 @@ contains(PRESET, linux_all_dynamic) { INCLUDEPATH = "$(HOME)/usr/include" $$INCLUDEPATH QMAKE_LIBDIR = "$(HOME)/usr/lib" $$QMAKE_LIBDIR - LIBS += -lGLU -lgsl -lgslcblas + LIBS += -lgsl -lgslcblas } contains(PRESET, linux_static) { ### Link statically and dynamically against rest. - LIBS += -lgsl -lgslcblas -lGLU + LIBS += -lgsl -lgslcblas } contains(PRESET, linux_all_static) { @@ -111,11 +115,16 @@ win32: { ### Static linking mostly. message(Build configuration: Win32) - isEmpty(LIBPATH): LIBPATH = ../3rdparty - - INCLUDEPATH += "$${LIBPATH}/gsl/include" - LIBS += "$${LIBPATH}/gsl/lib/libgsl.a" - LIBS += "$${LIBPATH}/gsl/lib/libgslcblas.a" + GSL_ROOT_PATH = $$clean_path($$(GSL_ROOT)) + !isEmpty(GSL_ROOT_PATH) { + INCLUDEPATH += "$${GSL_ROOT_PATH}/include" + LIBS += "-L$${GSL_ROOT_PATH}/lib" gsl.lib gslcblas.lib opengl32.lib + } else { + isEmpty(LIBPATH): LIBPATH = ../3rdparty + INCLUDEPATH += "$${LIBPATH}/gsl/include" + LIBS += "$${LIBPATH}/gsl/lib/gsl.lib" + LIBS += "$${LIBPATH}/gsl/lib/gslcblas.lib" + } } } @@ -129,8 +138,8 @@ mxe { LIBS += -mwindows -lgsl -lgslcblas # Qt libs specified here to get around a dependency bug in qmake - LIBS += -lQt5OpenGL -lQt5Gui -lQt5Widgets -lQt5Network -lQt5Core -lQt5Svg - LIBS += -lQt5PrintSupport -lQt5Xml -lQt5XmlPatterns -lQt5DataVisualization + LIBS += -lQt6OpenGL -lQt6Gui -lQt6Widgets -lQt6Network -lQt6Core -lQt6Svg + LIBS += -lQt6PrintSupport -lQt6Xml -lQt6DataVisualization LIBS += -lole32 -loleaut32 -limm32 -lcomdlg32 -luuid LIBS += -lwinspool -lssl -lcrypto -lwinmm -lgdi32 -lws2_32 LIBS += -ljpeg -lpng -lmng -ltiff -llzma -llcms2 diff --git a/data/INSTALL.md b/data/INSTALL.md index a9580f8e..a541b827 100644 --- a/data/INSTALL.md +++ b/data/INSTALL.md @@ -234,7 +234,7 @@ If you want to discuss AlphaPlot with other users (or the developers) or if you ### License: -AlphaPlot is distributed under the terms of the [GNU General Public License](http://www.gnu.org/licenses/gpl.html) as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. A copy of this license is provided in the file `gpl.txt`. +AlphaPlot is distributed under the terms of the [GNU General Public License](http://www.gnu.org/licenses/gpl.html) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. A copy of this license is provided in the file `gpl-3.0.txt`. Thus it is ["free software"](http://www.fsf.org/licensing/essays/free-sw.html). "Free software" is a matter of liberty, not price. To understand the concept, you should think of "free" as in "free speech", not as in "free beer". "Free software" is also often called [Open Source, FOSS, or FLOSS](http://en.wikipedia.org/wiki/Alternative_terms_for_free_software). When we say that AlphaPlot is "free", we are talking about diff --git a/data/gpl-3.0.txt b/data/gpl-3.0.txt new file mode 100644 index 00000000..f288702d --- /dev/null +++ b/data/gpl-3.0.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/data/gpl.txt b/data/gpl.txt deleted file mode 100644 index 3912109b..00000000 --- a/data/gpl.txt +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/data/icons/app/alphaplot.svg b/data/icons/app/alphaplot.svg index 9745ae81..b423815a 100644 --- a/data/icons/app/alphaplot.svg +++ b/data/icons/app/alphaplot.svg @@ -2,7 +2,7 @@ + width="486px" height="486px" viewBox="0 0 514 486" enable-background="new 0 0 514 486" xml:space="preserve"> diff --git a/data/license.rtf b/data/license.rtf index b3e16fdf..0917ebd3 100644 --- a/data/license.rtf +++ b/data/license.rtf @@ -32,9 +32,9 @@ {\*\ftnsep}\pgndec\sect\sectd\sectunlocked1\pgwsxn12240\pghsxn15840\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\ltrsect\sbknone\pard\plain \s3\ql\nowidctlpar\sb240\sa120\keepn\ltrpar\cf1\b\kerning1\dbch\af11\langfe1081\dbch\af13\afs28\loch\f5\fs28\lang2057\sb240\sa120{{\*\bkmkstart SEC1}{\*\bkmkend SEC1}\rtlch \ltrch\loch GNU GENERAL PUBLIC LICENSE} \par \pard\plain \s22\sl288\slmult1\ql\nowidctlpar\sb0\sa120\ltrpar\cf1\kerning1\dbch\af11\langfe1081\dbch\af16\afs24\loch\f3\fs24\lang2057{\rtlch \ltrch\loch -Version 2, June 1991 } +Version 3, June 2007 } \par \pard\plain \s27\ql\nowidctlpar\sb0\sa0\ltrpar\cf1\kerning1\dbch\af11\langfe1081\dbch\af16\afs24\loch\f7\fs20\lang2057{\rtlch \ltrch\loch -Copyright (C) 1989, 1991 Free Software Foundation, Inc. } +Copyright (C) 2007 Free Software Foundation, Inc. } \par \pard\plain \s27\ql\nowidctlpar\sb0\sa0\ltrpar\cf1\kerning1\dbch\af11\langfe1081\dbch\af16\afs24\loch\f7\fs20\lang2057{\rtlch \ltrch\loch 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA} \par \pard\plain \s27\ql\nowidctlpar\sb0\sa0\ltrpar\cf1\kerning1\dbch\af11\langfe1081\dbch\af16\afs24\loch\f7\fs20\lang2057\rtlch \ltrch\loch @@ -166,7 +166,7 @@ This program is free software; you can redistribute it and/or} \par \pard\plain \s27\ql\nowidctlpar\sb0\sa0\ltrpar\cf1\kerning1\dbch\af11\langfe1081\dbch\af16\afs24\loch\f7\fs20\lang2057{\rtlch \ltrch\loch modify it under the terms of the GNU General Public License} \par \pard\plain \s27\ql\nowidctlpar\sb0\sa0\ltrpar\cf1\kerning1\dbch\af11\langfe1081\dbch\af16\afs24\loch\f7\fs20\lang2057{\rtlch \ltrch\loch -as published by the Free Software Foundation; either version 2} +as published by the Free Software Foundation; either version 3} \par \pard\plain \s27\ql\nowidctlpar\sb0\sa0\ltrpar\cf1\kerning1\dbch\af11\langfe1081\dbch\af16\afs24\loch\f7\fs20\lang2057{\rtlch \ltrch\loch of the License, or (at your option) any later version.} \par \pard\plain \s27\ql\nowidctlpar\sb0\sa0\ltrpar\cf1\kerning1\dbch\af11\langfe1081\dbch\af16\afs24\loch\f7\fs20\lang2057\rtlch \ltrch\loch diff --git a/data/metainfo.xml b/data/metainfo.xml index 09c05464..832f6a0e 100644 --- a/data/metainfo.xml +++ b/data/metainfo.xml @@ -2,13 +2,14 @@ io.github.narunlifescience.AlphaPlot CC0-1.0 - GPL-2.0 + GPL-3.0 AlphaPlot Arun Narayanankutty https://alphaplot.sourceforge.io/ https://github.com/narunlifescience/AlphaPlot/issues https://www.patreon.com/alphaplot https://alphaplot.sourceforge.io/wiki/index.php + alphaplot.desktop AlphaPlot is a free application for Scientific Data Analysis and Visualization

@@ -21,36 +22,60 @@ https://github.com/narunlifescience/AlphaPlot/raw/master/data/screenshots/alphaplot3.png +

https://github.com/narunlifescience/AlphaPlot/raw/master/data/screenshots/example1.png + https://github.com/narunlifescience/AlphaPlot/raw/master/data/screenshots/example2.png + https://github.com/narunlifescience/AlphaPlot/raw/master/data/screenshots/example3.png + https://github.com/narunlifescience/AlphaPlot/raw/master/data/screenshots/example4.png + https://github.com/narunlifescience/AlphaPlot/raw/master/data/screenshots/example5.png + https://github.com/narunlifescience/AlphaPlot/raw/master/data/screenshots/example6.png + https://github.com/narunlifescience/AlphaPlot/raw/master/data/screenshots/example7.png + https://github.com/narunlifescience/AlphaPlot/raw/master/data/screenshots/example8.png + https://github.com/narunlifescience/AlphaPlot/raw/master/data/screenshots/example9.png + + + +

Overview of changes in AlphaPlot 1.3.0

+
    +
  • full porting to Qt6
  • +
  • update license from GPL-2.0 to GPL-3.0 for Qt6 compatibility
  • +
  • fix last column auto-resize when "Set Column(s) As" is used
  • +
  • add compatibility with Flatpak
  • +
  • use QRandomGenerator class for random number generation
  • +
  • beautify result logs with html styling
  • +
  • change property browser to model view framework
  • +
+
+

Overview of changes in AlphaPlot 1.02

@@ -101,7 +126,7 @@
- +

Overview of changes in AlphaPlot 1.011

    @@ -141,29 +166,6 @@
- - -

Overview of changes in AlphaPlot alpha-test2

-
    -
  • add basic error detection to Qt Script
  • -
  • add a basic Syntax highlighter for scripts and functions
  • -
  • add QtScript with debugging to Alphaplot basic data structures with cell to cell data manipulation ability(Table and Matrix)
  • -
  • add add/remove layer to graph2d window
  • -
  • use default cascade function
  • -
  • fix mxe compile errors
  • -
  • drop QT3 related stuff
  • -
  • use a float button instead of old block one in table and matrix to access control UI
  • -
  • remember normal window state when a user closes a window in maximized state
  • -
  • added c++ 11 Support
  • -
  • remove liborigin and python support for now
  • -
  • make scripting console interactive (rewrite the entire class)
  • -
  • modernize icons and an icon handling class
  • -
  • add a lock-unlock functionality for toolbars and dock widgets
  • -
  • compartmentalize various aspects like scripting, 3d plots, etc. to separate directories
  • -
  • fix old code warnings (replace old C style casting, remove hardcoded colors, use initializer list when possible, Clean up Application window class, give better meaningful names for variables, etc.)
  • -
-
-
Education diff --git a/data/splash/splash.png b/data/splash/splash.png index bdd6008e..03d111f5 100644 Binary files a/data/splash/splash.png and b/data/splash/splash.png differ diff --git a/data/splash/splash02.png b/data/splash/splash02.png new file mode 100644 index 00000000..952b9ec6 Binary files /dev/null and b/data/splash/splash02.png differ diff --git a/data/splash/splash03.png b/data/splash/splash03.png index 952b9ec6..bdd6008e 100644 Binary files a/data/splash/splash03.png and b/data/splash/splash03.png differ diff --git a/fitPlugins/exp_saturation/exp_saturation.c b/fitPlugins/exp_saturation/exp_saturation.c index aa0d8a08..3e741709 100644 --- a/fitPlugins/exp_saturation/exp_saturation.c +++ b/fitPlugins/exp_saturation/exp_saturation.c @@ -11,7 +11,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * As a special exception, you may omit the above copyright notice when * diff --git a/fitPlugins/exp_saturation/exp_saturation.pro b/fitPlugins/exp_saturation/exp_saturation.pro index ac0d1446..8b1d949a 100644 --- a/fitPlugins/exp_saturation/exp_saturation.pro +++ b/fitPlugins/exp_saturation/exp_saturation.pro @@ -10,12 +10,12 @@ CONFIG += release DESTDIR = ../ INSTALLS += target -unix: target.path = /usr/lib$${libsuff}/AlphaPlot/plugins +unix { + contains(CONFIG, flatpak): target.path = /app/lib$${libsuff}/AlphaPlot/plugins + else: target.path = /usr/lib$${libsuff}/AlphaPlot/plugins +} win32: target.path = ../../output/plugins -win32:INCLUDEPATH += ../../3rdparty/gsl/include -win32:LIBS += ../../3rdparty/gsl/lib/libgsl.a -win32:LIBS += ../../3rdparty/gsl/lib/libgslcblas.a unix:LIBS += -L/usr/lib$${libsuff} -lgsl -lgslcblas #unix:LIBS += /usr/lib/libgsl.a /usr/lib/libgslcblas.a diff --git a/fitPlugins/explin/explin.c b/fitPlugins/explin/explin.c index 06dd1fc8..c216cbad 100644 --- a/fitPlugins/explin/explin.c +++ b/fitPlugins/explin/explin.c @@ -11,7 +11,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * As a special exception, you may omit the above copyright notice when * diff --git a/fitPlugins/explin/explin.pro b/fitPlugins/explin/explin.pro index 176d5a55..bab739f7 100644 --- a/fitPlugins/explin/explin.pro +++ b/fitPlugins/explin/explin.pro @@ -10,12 +10,12 @@ CONFIG += release DESTDIR = ../ INSTALLS += target -unix: target.path = /usr/lib$${libsuff}/AlphaPlot/plugins +unix { + contains(CONFIG, flatpak): target.path = /app/lib$${libsuff}/AlphaPlot/plugins + else: target.path = /usr/lib$${libsuff}/AlphaPlot/plugins +} win32: target.path = ../../output/plugins -win32:INCLUDEPATH += ../../3rdparty/gsl/include -win32:LIBS += ../../3rdparty/gsl/lib/libgsl.a -win32:LIBS += ../../3rdparty/gsl/lib/libgslcblas.a unix:LIBS += -L/usr/lib$${libsuff} -lgsl -lgslcblas #unix:LIBS += /usr/lib/libgsl.a /usr/lib/libgslcblas.a diff --git a/fitPlugins/fitRational0/fitRational0.cpp b/fitPlugins/fitRational0/fitRational0.cpp index 885bb015..68dac06f 100644 --- a/fitPlugins/fitRational0/fitRational0.cpp +++ b/fitPlugins/fitRational0/fitRational0.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * As a special exception, you may omit the above copyright notice when * diff --git a/fitPlugins/fitRational0/fitRational0.pro b/fitPlugins/fitRational0/fitRational0.pro index b0adbffd..7c9476a0 100644 --- a/fitPlugins/fitRational0/fitRational0.pro +++ b/fitPlugins/fitRational0/fitRational0.pro @@ -13,12 +13,12 @@ CONFIG += dll DESTDIR = ../ INSTALLS += target -unix:target.path=/usr/lib$${libsuff}/AlphaPlot/plugins +unix { + contains(CONFIG, flatpak): target.path = /app/lib$${libsuff}/AlphaPlot/plugins + else: target.path = /usr/lib$${libsuff}/AlphaPlot/plugins +} win32: target.path = ../../output/plugins -win32:INCLUDEPATH += ../../3rdparty/gsl/include -win32:LIBS += ../../3rdparty/gsl/lib/libgsl.a -win32:LIBS += ../../3rdparty/gsl/lib/libgslcblas.a unix:LIBS += -L/usr/lib$${libsuff} -lgsl -lgslcblas #unix:LIBS += /usr/lib/libgsl.a /usr/lib/libgslcblas.a diff --git a/fitPlugins/fitRational1/fitRational1.cpp b/fitPlugins/fitRational1/fitRational1.cpp index eb9dc94d..7e7be4d5 100644 --- a/fitPlugins/fitRational1/fitRational1.cpp +++ b/fitPlugins/fitRational1/fitRational1.cpp @@ -12,7 +12,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * As a special exception, you may omit the above copyright notice when * diff --git a/fitPlugins/fitRational1/fitRational1.pro b/fitPlugins/fitRational1/fitRational1.pro index 190c2eec..8e3a3867 100644 --- a/fitPlugins/fitRational1/fitRational1.pro +++ b/fitPlugins/fitRational1/fitRational1.pro @@ -14,12 +14,12 @@ DESTDIR = ../ INSTALLS += target # where to install the plugins -unix:target.path=/usr/lib$${libsuff}/AlphaPlot/plugins +unix { + contains(CONFIG, flatpak): target.path = /app/lib$${libsuff}/AlphaPlot/plugins + else: target.path = /usr/lib$${libsuff}/AlphaPlot/plugins +} win32: target.path = ../../output/plugins -win32:INCLUDEPATH += ../../3rdparty/gsl/include -win32:LIBS += ../../3rdparty/gsl/lib/libgsl.a -win32:LIBS += ../../3rdparty/gsl/lib/libgslcblas.a unix:LIBS += -L/usr/lib$${libsuff} -lgsl -lgslcblas #unix:LIBS += /usr/lib/libgsl.a /usr/lib/libgslcblas.a diff --git a/fitPlugins/planck_wavelength/planck_wavelength.c b/fitPlugins/planck_wavelength/planck_wavelength.c index f40a7613..ddb363e0 100644 --- a/fitPlugins/planck_wavelength/planck_wavelength.c +++ b/fitPlugins/planck_wavelength/planck_wavelength.c @@ -11,7 +11,7 @@ * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * + * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * As a special exception, you may omit the above copyright notice when * diff --git a/fitPlugins/planck_wavelength/planck_wavelength.pro b/fitPlugins/planck_wavelength/planck_wavelength.pro index d4e59b7e..e8d05127 100644 --- a/fitPlugins/planck_wavelength/planck_wavelength.pro +++ b/fitPlugins/planck_wavelength/planck_wavelength.pro @@ -10,12 +10,12 @@ CONFIG += release DESTDIR = ../ INSTALLS += target -unix: target.path = /usr/lib$${libsuff}/AlphaPlot/plugins +unix { + contains(CONFIG, flatpak): target.path = /app/lib$${libsuff}/AlphaPlot/plugins + else: target.path = /usr/lib$${libsuff}/AlphaPlot/plugins +} win32: target.path = ../../output/plugins -win32:INCLUDEPATH += ../../3rdparty/gsl/include -win32:LIBS += ../../3rdparty/gsl/lib/libgsl.a -win32:LIBS += ../../3rdparty/gsl/lib/libgslcblas.a unix:LIBS += -L/usr/lib$${libsuff} -lgsl -lgslcblas #unix:LIBS += /usr/lib/libgsl.a /usr/lib/libgslcblas.a diff --git a/test/test.pro b/test/test.pro index ebf13acd..ce45b8ae 100644 --- a/test/test.pro +++ b/test/test.pro @@ -3,7 +3,7 @@ ###################################################################### # enable C++11 support -greaterThan(QT_MAJOR_VERSION, 4){ +greaterThan(QT_MAJOR_VERSION, 4) | greaterThan(QT_VERSION_MAJOR, 4) { CONFIG += c++11 } else { QMAKE_CXXFLAGS += -std=c++0x
Main window Example 1 Example 2 Example 3 Example 4 Example 5 Example 6 Example 7 Example 8 Example 9