From 8c0bdcc612cb63e78c1af70fcdce12fc58779633 Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Tue, 10 Feb 2015 13:39:31 +0200 Subject: [PATCH] Make parser static locale variable local for each parser instance. --HG-- branch : feature --- src/libs/qmuparser/qmuparser.cpp | 4 +-- src/libs/qmuparser/qmuparser.h | 2 +- src/libs/qmuparser/qmuparserbase.cpp | 27 +++++++++++++++------ src/libs/qmuparser/qmuparserbase.h | 5 +++- src/libs/qmuparser/qmuparserdef.h | 2 +- src/libs/qmuparser/qmuparsertest.cpp | 3 ++- src/libs/qmuparser/qmuparsertest.h | 2 +- src/libs/qmuparser/qmuparsertokenreader.cpp | 8 +++--- src/libs/qmuparser/qmuparsertokenreader.h | 4 +-- 9 files changed, 37 insertions(+), 20 deletions(-) diff --git a/src/libs/qmuparser/qmuparser.cpp b/src/libs/qmuparser/qmuparser.cpp index 799c6c8ca..bac0ecf00 100644 --- a/src/libs/qmuparser/qmuparser.cpp +++ b/src/libs/qmuparser/qmuparser.cpp @@ -199,14 +199,14 @@ qreal QmuParser::Max(const qreal *a_afArg, int a_iArgc) * @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 QmuParser::IsVal(const QString &a_szExpr, int *a_iPos, qreal *a_fVal) +int QmuParser::IsVal(const QString &a_szExpr, int *a_iPos, qreal *a_fVal, const std::locale &s_locale) { qreal fVal(0); std::wstring a_szExprStd = a_szExpr.toStdWString(); stringstream_type stream(a_szExprStd); stream.seekg(0); // todo: check if this really is necessary - stream.imbue(QmuParser::s_locale); + stream.imbue(s_locale); stream >> fVal; stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading diff --git a/src/libs/qmuparser/qmuparser.h b/src/libs/qmuparser/qmuparser.h index e65bdfa40..f35f545cc 100644 --- a/src/libs/qmuparser/qmuparser.h +++ b/src/libs/qmuparser/qmuparser.h @@ -54,7 +54,7 @@ namespace qmu virtual void OnDetectVar(const QString &pExpr, int &nStart, int &nEnd); qreal Diff(qreal *a_Var, qreal a_fPos, qreal a_fEpsilon = 0) const; protected: - static int IsVal(const QString &a_szExpr, int *a_iPos, qreal *a_fVal); + static int IsVal(const QString &a_szExpr, int *a_iPos, qreal *a_fVal, const std::locale &s_locale); // Trigonometric functions static qreal Tan2(qreal, qreal); // hyperbolic functions diff --git a/src/libs/qmuparser/qmuparserbase.cpp b/src/libs/qmuparser/qmuparserbase.cpp index c627e1f80..7455d3046 100644 --- a/src/libs/qmuparser/qmuparserbase.cpp +++ b/src/libs/qmuparser/qmuparserbase.cpp @@ -37,7 +37,6 @@ using namespace std; namespace qmu { -std::locale QmuParserBase::s_locale = std::locale(std::locale::classic(), new change_dec_sep('.')); bool QmuParserBase::g_DbgDumpCmdCode = false; bool QmuParserBase::g_DbgDumpStack = false; @@ -57,7 +56,8 @@ const QStringList QmuParserBase::c_DefaultOprt = QStringList()<< "<=" << ">=" << * @brief Constructor. */ QmuParserBase::QmuParserBase() - :m_pParseFormula(&QmuParserBase::ParseString), m_vRPN(), m_vStringBuf(), m_vStringVarBuf(), m_pTokenReader(), + :s_locale(std::locale(std::locale::classic(), new change_dec_sep('.'))), + m_pParseFormula(&QmuParserBase::ParseString), m_vRPN(), m_vStringBuf(), m_vStringVarBuf(), 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), m_Tokens(QMap()), m_Numbers(QMap()), allowSubexpressions(true) @@ -72,10 +72,11 @@ QmuParserBase::QmuParserBase() * Tha parser can be safely copy constructed but the bytecode is reset during copy construction. */ QmuParserBase::QmuParserBase(const QmuParserBase &a_Parser) - :m_pParseFormula(&QmuParserBase::ParseString), m_vRPN(), m_vStringBuf(), m_vStringVarBuf(), 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), m_Tokens(QMap()), m_Numbers(QMap()), allowSubexpressions(true) + :s_locale(a_Parser.getLocale()), m_pParseFormula(&QmuParserBase::ParseString), m_vRPN(), m_vStringBuf(), + m_vStringVarBuf(), 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), m_Tokens(QMap()), + m_Numbers(QMap()), allowSubexpressions(true) { m_pTokenReader.reset(new token_reader_type(this)); Assign(a_Parser); @@ -220,6 +221,18 @@ void QmuParserBase::setAllowSubexpressions(bool value) allowSubexpressions = value; } +//--------------------------------------------------------------------------------------------------------------------- +std::locale QmuParserBase::getLocale() const +{ + return s_locale; +} + +//--------------------------------------------------------------------------------------------------------------------- +void QmuParserBase::setLocale(const std::locale &value) +{ + s_locale = value; +} + //--------------------------------------------------------------------------------------------------------------------- /** * @brief Returns the version of muparser. @@ -1300,7 +1313,7 @@ void QmuParserBase::CreateRPN() const for (;;) { - opt = m_pTokenReader->ReadNextToken(); + opt = m_pTokenReader->ReadNextToken(s_locale); switch (opt.GetCode()) { diff --git a/src/libs/qmuparser/qmuparserbase.h b/src/libs/qmuparser/qmuparserbase.h index 59d8b7c59..dc9a36385 100644 --- a/src/libs/qmuparser/qmuparserbase.h +++ b/src/libs/qmuparser/qmuparserbase.h @@ -122,9 +122,12 @@ public: } void setAllowSubexpressions(bool value); + std::locale getLocale() const; + void setLocale(const std::locale &value); + protected: static const QStringList c_DefaultOprt; - static std::locale s_locale; ///< The locale used by the parser + std::locale s_locale; ///< The locale used by the parser static bool g_DbgDumpCmdCode; static bool g_DbgDumpStack; void Init(); diff --git a/src/libs/qmuparser/qmuparserdef.h b/src/libs/qmuparser/qmuparserdef.h index cf6ce2652..a74d29d00 100644 --- a/src/libs/qmuparser/qmuparserdef.h +++ b/src/libs/qmuparser/qmuparserdef.h @@ -275,7 +275,7 @@ typedef qreal ( *strfun_type2 ) ( const QString &, qreal ); typedef qreal ( *strfun_type3 ) ( const QString &, qreal, qreal ); /** @brief Callback used for functions that identify values in a string. */ -typedef int ( *identfun_type ) ( const QString &sExpr, int *nPos, qreal *fVal ); +typedef int ( *identfun_type ) ( const QString &sExpr, int *nPos, qreal *fVal, const std::locale &s_locale ); /** @brief Callback used for variable creation factory functions. */ typedef qreal* ( *facfun_type ) ( const QString &, void* ); diff --git a/src/libs/qmuparser/qmuparsertest.cpp b/src/libs/qmuparser/qmuparsertest.cpp index 1d11cef83..a5ffb9dac 100644 --- a/src/libs/qmuparser/qmuparsertest.cpp +++ b/src/libs/qmuparser/qmuparsertest.cpp @@ -62,8 +62,9 @@ QmuParserTester::QmuParserTester() } //--------------------------------------------------------------------------------------------------------------------- -int QmuParserTester::IsHexVal ( const QString &a_szExpr, int *a_iPos, qreal *a_fVal ) +int QmuParserTester::IsHexVal ( const QString &a_szExpr, int *a_iPos, qreal *a_fVal, const std::locale &s_locale ) { + Q_UNUSED(s_locale) if ( a_szExpr.data()[1] == 0 || ( a_szExpr.data()[0] != '0' || a_szExpr.data()[1] != 'x' ) ) { return 0; diff --git a/src/libs/qmuparser/qmuparsertest.h b/src/libs/qmuparser/qmuparsertest.h index d2ae906ef..d1ffe91a8 100644 --- a/src/libs/qmuparser/qmuparsertest.h +++ b/src/libs/qmuparser/qmuparsertest.h @@ -276,7 +276,7 @@ private: } // Custom value recognition - static int IsHexVal ( const QString &a_szExpr, int *a_iPos, qreal *a_fVal ); + static int IsHexVal (const QString &a_szExpr, int *a_iPos, qreal *a_fVal , const std::locale &s_locale); // cppcheck-suppress functionStatic int TestNames(); diff --git a/src/libs/qmuparser/qmuparsertokenreader.cpp b/src/libs/qmuparser/qmuparsertokenreader.cpp index 9475308cc..d5515eb94 100644 --- a/src/libs/qmuparser/qmuparsertokenreader.cpp +++ b/src/libs/qmuparser/qmuparsertokenreader.cpp @@ -204,7 +204,7 @@ void QmuParserTokenReader::ReInit() /** * @brief Read the next token from the string. */ -QmuParserTokenReader::token_type QmuParserTokenReader::ReadNextToken() +QmuParserTokenReader::token_type QmuParserTokenReader::ReadNextToken(const std::locale &s_locale) { assert ( m_pParser ); @@ -236,7 +236,7 @@ QmuParserTokenReader::token_type QmuParserTokenReader::ReadNextToken() { return SaveBeforeReturn ( tok ); // Check for function argument separators } - if ( IsValTok ( tok ) ) + if ( IsValTok ( tok, s_locale ) ) { return SaveBeforeReturn ( tok ); // Check for values / constant tokens } @@ -766,7 +766,7 @@ bool QmuParserTokenReader::IsPostOpTok ( token_type &a_Tok ) * @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 QmuParserTokenReader::IsValTok ( token_type &a_Tok ) +bool QmuParserTokenReader::IsValTok ( token_type &a_Tok, const std::locale &s_locale ) { assert ( m_pConstDef ); assert ( m_pParser ); @@ -802,7 +802,7 @@ bool QmuParserTokenReader::IsValTok ( token_type &a_Tok ) for ( item = m_vIdentFun.begin(); item != m_vIdentFun.end(); ++item ) { int iStart = m_iPos; - if ( ( *item ) ( m_strFormula.mid ( m_iPos ), &m_iPos, &fVal ) == 1 ) + if ( ( *item ) ( m_strFormula.mid ( m_iPos ), &m_iPos, &fVal, s_locale ) == 1 ) { // 2013-11-27 Issue 2: https://code.google.com/p/muparser/issues/detail?id=2 strTok = m_strFormula.mid ( iStart, m_iPos-iStart ); diff --git a/src/libs/qmuparser/qmuparsertokenreader.h b/src/libs/qmuparser/qmuparsertokenreader.h index 43d08106e..5a28e5136 100644 --- a/src/libs/qmuparser/qmuparsertokenreader.h +++ b/src/libs/qmuparser/qmuparsertokenreader.h @@ -58,7 +58,7 @@ public: QChar GetArgSep() const; void IgnoreUndefVar(bool bIgnore); void ReInit(); - token_type ReadNextToken(); + token_type ReadNextToken(const std::locale &s_locale); private: /** @@ -103,7 +103,7 @@ private: 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 IsValTok(token_type &a_Tok, const std::locale &s_locale); bool IsVarTok(token_type &a_Tok); bool IsStrVarTok(token_type &a_Tok); bool IsUndefVarTok(token_type &a_Tok);