From 310b56c936383055c2dd1fd14d56853f576f6038 Mon Sep 17 00:00:00 2001 From: Ingo Berg <2202567+beltoforion@users.noreply.github.com> Date: Sat, 14 Oct 2023 04:27:06 +0200 Subject: [PATCH] fix for #131: save string buffer with bytecode --- include/muParserBytecode.h | 20 ++++++++++++++++++++ samples/example1/example1.cpp | 2 +- src/muParserBase.cpp | 10 +++++++++- src/muParserBytecode.cpp | 9 +++++++-- 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/include/muParserBytecode.h b/include/muParserBytecode.h index a6aff2b..bf84dd7 100644 --- a/include/muParserBytecode.h +++ b/include/muParserBytecode.h @@ -94,9 +94,18 @@ namespace mu /** \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; @@ -142,6 +151,17 @@ namespace mu return &m_vRPN[0]; } + void StoreEnvironment(string_type a_expr, stringbuf_type const& a_strBuf) + { + m_stringBuffer = a_strBuf; + m_expr = a_expr; + } + + std::tuple RestoreEnvironment() const + { + return std::make_tuple(m_expr, m_stringBuffer); + } + void AsciiDump() const; }; diff --git a/samples/example1/example1.cpp b/samples/example1/example1.cpp index 49c3338..5577aa7 100644 --- a/samples/example1/example1.cpp +++ b/samples/example1/example1.cpp @@ -475,7 +475,7 @@ static void Calc() parser.SetVarFactory(AddVariable, &parser); // You can extract the bytecode of a parsed functions and save it for later use. - parser.SetExpr(_T("sin(a)")); + parser.SetExpr(_T("sin(a)+strfun2(sVar1, 1 , 2)")); parser.Eval(); ParserByteCode bytecode1(parser.GetByteCode()); diff --git a/src/muParserBase.cpp b/src/muParserBase.cpp index 8da035f..b42ac91 100644 --- a/src/muParserBase.cpp +++ b/src/muParserBase.cpp @@ -277,7 +277,13 @@ namespace mu /** \brief Restore a previously saved bytecode. */ void ParserBase::SetByteCode(const ParserByteCode& a_ByteCode) { - m_vRPN.Assign(a_ByteCode); + 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; } @@ -1540,12 +1546,14 @@ namespace mu 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)(); } diff --git a/src/muParserBytecode.cpp b/src/muParserBytecode.cpp index a0b7b9e..1bc61c3 100644 --- a/src/muParserBytecode.cpp +++ b/src/muParserBytecode.cpp @@ -49,7 +49,9 @@ namespace mu { /** \brief Bytecode default constructor. */ ParserByteCode::ParserByteCode() - :m_iStackPos(0) + : m_iStackPos(0) + , m_stringBuffer() + , m_expr() , m_iMaxStackSize(0) , m_vRPN() , m_bEnableOptimizer(true) @@ -98,6 +100,9 @@ namespace mu 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; } @@ -595,7 +600,7 @@ namespace mu 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("]"); + 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");