diff --git a/plugins/libimhex/include/hex/helpers/utils.hpp b/plugins/libimhex/include/hex/helpers/utils.hpp index d2b9f1c94..cdd3fb108 100644 --- a/plugins/libimhex/include/hex/helpers/utils.hpp +++ b/plugins/libimhex/include/hex/helpers/utils.hpp @@ -76,6 +76,7 @@ namespace hex { #define TOKEN_CONCAT_IMPL(x, y) x ## y #define TOKEN_CONCAT(x, y) TOKEN_CONCAT_IMPL(x, y) +#define ANONYMOUS_VARIABLE(prefix) TOKEN_CONCAT(prefix, __COUNTER__) namespace hex { @@ -235,20 +236,32 @@ namespace hex { std::vector getPath(ImHexPath path); - #define SCOPE_EXIT(func) ScopeExit TOKEN_CONCAT(scopeGuard, __COUNTER__)([&] { func }) - class ScopeExit { + #define SCOPE_GUARD ::hex::ScopeGuardOnExit() + [&]() + #define ON_SCOPE_EXIT auto ANONYMOUS_VARIABLE(SCOPE_EXIT_) = SCOPE_GUARD + template + class ScopeGuard { + private: + F m_func; + bool m_active; public: - ScopeExit(const std::function &func) : m_func(func) {} - ~ScopeExit() { if (this->m_func != nullptr) this->m_func(); } + constexpr ScopeGuard(F func) : m_func(std::move(func)), m_active(true) { } + ~ScopeGuard() { if (this->m_active) { this->m_func(); } } + void release() { this->m_active = false; } - void release() { - this->m_func = nullptr; + ScopeGuard(ScopeGuard &&other) noexcept : m_func(std::move(other.m_func)), m_active(other.m_active) { + other.cancel(); } - private: - std::function m_func; + ScopeGuard& operator=(ScopeGuard &&) = delete; }; + enum class ScopeGuardOnExit { }; + + template + constexpr ScopeGuard operator+(ScopeGuardOnExit, F&& f) { + return ScopeGuard(std::forward(f)); + } + struct Region { u64 address; size_t size; diff --git a/plugins/libimhex/include/hex/lang/parser.hpp b/plugins/libimhex/include/hex/lang/parser.hpp index 9c52a6dec..f0d1dc76a 100644 --- a/plugins/libimhex/include/hex/lang/parser.hpp +++ b/plugins/libimhex/include/hex/lang/parser.hpp @@ -91,7 +91,10 @@ namespace hex::lang { std::vector parseTillToken(Token::Type endTokenType, const auto value) { std::vector program; - ScopeExit guard([&]{ for (auto &node : program) delete node; }); + auto guard = SCOPE_GUARD { + for (auto &node : program) + delete node; + }; while (this->m_curr->type != endTokenType || (*this->m_curr) != value) { program.push_back(parseStatement()); diff --git a/plugins/libimhex/source/lang/evaluator.cpp b/plugins/libimhex/source/lang/evaluator.cpp index fc3083c41..3b6b0f7e3 100644 --- a/plugins/libimhex/source/lang/evaluator.cpp +++ b/plugins/libimhex/source/lang/evaluator.cpp @@ -121,10 +121,10 @@ namespace hex::lang { ASTNode* Evaluator::evaluateFunctionCall(ASTNodeFunctionCall *node) { std::vector evaluatedParams; - ScopeExit paramCleanup([&] { + ON_SCOPE_EXIT { for (auto ¶m : evaluatedParams) delete param; - }); + }; for (auto ¶m : node->getParams()) { if (auto numericExpression = dynamic_cast(param); numericExpression != nullptr) @@ -310,7 +310,7 @@ namespace hex::lang { switch (node->getOperator()) { case Token::Operator::TernaryConditional: { auto condition = this->evaluateOperand(node->getFirstOperand()); - SCOPE_EXIT( delete condition; ); + ON_SCOPE_EXIT { delete condition; }; if (std::visit([](auto &&value){ return value != 0; }, condition->getValue())) return this->evaluateOperand(node->getSecondOperand()); @@ -437,7 +437,7 @@ namespace hex::lang { std::vector memberPatterns; this->m_currMembers.push_back(&memberPatterns); - SCOPE_EXIT( this->m_currMembers.pop_back(); ); + ON_SCOPE_EXIT { this->m_currMembers.pop_back(); }; this->m_currRecursionDepth++; if (this->m_currRecursionDepth > this->m_recursionLimit) @@ -457,7 +457,7 @@ namespace hex::lang { std::vector memberPatterns; this->m_currMembers.push_back(&memberPatterns); - SCOPE_EXIT( this->m_currMembers.pop_back(); ); + ON_SCOPE_EXIT { this->m_currMembers.pop_back(); }; auto startOffset = this->m_currOffset; @@ -501,7 +501,7 @@ namespace hex::lang { this->getConsole().abortEvaluation("invalid expression in enum value"); auto valueNode = evaluateMathematicalExpression(expression); - SCOPE_EXIT( delete valueNode; ); + ON_SCOPE_EXIT { delete valueNode; }; entryPatterns.push_back({ Token::castTo(builtinUnderlyingType->getType(), valueNode->getValue()), name }); } @@ -522,7 +522,7 @@ namespace hex::lang { this->getConsole().abortEvaluation("invalid expression in bitfield field size"); auto valueNode = evaluateMathematicalExpression(expression); - SCOPE_EXIT( delete valueNode; ); + ON_SCOPE_EXIT { delete valueNode; }; auto fieldBits = std::visit([this, node, type = valueNode->getType()] (auto &&value) { if (Token::isFloatingPoint(type)) @@ -580,7 +580,7 @@ namespace hex::lang { if (auto offset = dynamic_cast(node->getPlacementOffset()); offset != nullptr) { auto valueNode = evaluateMathematicalExpression(offset); - SCOPE_EXIT( delete valueNode; ); + ON_SCOPE_EXIT { delete valueNode; }; this->m_currOffset = std::visit([this, node, type = valueNode->getType()] (auto &&value) { if (Token::isFloatingPoint(type)) @@ -608,7 +608,7 @@ namespace hex::lang { if (auto offset = dynamic_cast(node->getPlacementOffset()); offset != nullptr) { auto valueNode = evaluateMathematicalExpression(offset); - SCOPE_EXIT( delete valueNode; ); + ON_SCOPE_EXIT { delete valueNode; }; this->m_currOffset = std::visit([this, node, type = valueNode->getType()] (auto &&value) { if (Token::isFloatingPoint(type)) @@ -628,7 +628,7 @@ namespace hex::lang { else this->getConsole().abortEvaluation("array size not a numeric expression"); - SCOPE_EXIT( delete valueNode; ); + ON_SCOPE_EXIT { delete valueNode; }; arraySize = std::visit([this, node, type = valueNode->getType()] (auto &&value) { if (Token::isFloatingPoint(type)) @@ -701,7 +701,7 @@ namespace hex::lang { s128 pointerOffset; if (auto offset = dynamic_cast(node->getPlacementOffset()); offset != nullptr) { auto valueNode = evaluateMathematicalExpression(offset); - SCOPE_EXIT( delete valueNode; ); + ON_SCOPE_EXIT { delete valueNode; }; pointerOffset = std::visit([this, node, type = valueNode->getType()] (auto &&value) { if (Token::isFloatingPoint(type)) diff --git a/plugins/libimhex/source/lang/parser.cpp b/plugins/libimhex/source/lang/parser.cpp index 002f8a57d..7e7b3ada0 100644 --- a/plugins/libimhex/source/lang/parser.cpp +++ b/plugins/libimhex/source/lang/parser.cpp @@ -22,10 +22,10 @@ namespace hex::lang { ASTNode* Parser::parseFunctionCall() { auto functionName = getValue(-2); std::vector params; - ScopeExit paramCleanup([&]{ + auto paramCleanup = SCOPE_GUARD { for (auto ¶m : params) delete param; - }); + }; while (!MATCHES(sequence(SEPARATOR_ROUNDBRACKETCLOSE))) { if (MATCHES(sequence(STRING))) @@ -118,7 +118,7 @@ namespace hex::lang { ASTNode* Parser::parseMultiplicativeExpression() { auto node = this->parseUnaryExpression(); - ScopeExit nodeCleanup([&]{ delete node; }); + auto nodeCleanup = SCOPE_GUARD { delete node; }; while (MATCHES(oneOf(OPERATOR_STAR, OPERATOR_SLASH, OPERATOR_PERCENT))) { auto op = getValue(-1); @@ -134,7 +134,7 @@ namespace hex::lang { ASTNode* Parser::parseAdditiveExpression() { auto node = this->parseMultiplicativeExpression(); - ScopeExit nodeCleanup([&]{ delete node; }); + auto nodeCleanup = SCOPE_GUARD { delete node; }; while (MATCHES(variant(OPERATOR_PLUS, OPERATOR_MINUS))) { auto op = getValue(-1); @@ -150,7 +150,7 @@ namespace hex::lang { ASTNode* Parser::parseShiftExpression() { auto node = this->parseAdditiveExpression(); - ScopeExit nodeCleanup([&]{ delete node; }); + auto nodeCleanup = SCOPE_GUARD { delete node; }; while (MATCHES(variant(OPERATOR_SHIFTLEFT, OPERATOR_SHIFTRIGHT))) { auto op = getValue(-1); @@ -166,7 +166,7 @@ namespace hex::lang { ASTNode* Parser::parseRelationExpression() { auto node = this->parseShiftExpression(); - ScopeExit nodeCleanup([&]{ delete node; }); + auto nodeCleanup = SCOPE_GUARD{ delete node; }; while (MATCHES(sequence(OPERATOR_BOOLGREATERTHAN) || sequence(OPERATOR_BOOLLESSTHAN) || sequence(OPERATOR_BOOLGREATERTHANOREQUALS) || sequence(OPERATOR_BOOLLESSTHANOREQUALS))) { auto op = getValue(-1); @@ -182,7 +182,7 @@ namespace hex::lang { ASTNode* Parser::parseEqualityExpression() { auto node = this->parseRelationExpression(); - ScopeExit nodeCleanup([&]{ delete node; }); + auto nodeCleanup = SCOPE_GUARD { delete node; }; while (MATCHES(sequence(OPERATOR_BOOLEQUALS) || sequence(OPERATOR_BOOLNOTEQUALS))) { auto op = getValue(-1); @@ -198,7 +198,7 @@ namespace hex::lang { ASTNode* Parser::parseBinaryAndExpression() { auto node = this->parseEqualityExpression(); - ScopeExit nodeCleanup([&]{ delete node; }); + auto nodeCleanup = SCOPE_GUARD { delete node; }; while (MATCHES(sequence(OPERATOR_BITAND))) { node = new ASTNodeNumericExpression(node, this->parseEqualityExpression(), Token::Operator::BitAnd); @@ -213,7 +213,7 @@ namespace hex::lang { ASTNode* Parser::parseBinaryXorExpression() { auto node = this->parseBinaryAndExpression(); - ScopeExit nodeCleanup([&]{ delete node; }); + auto nodeCleanup = SCOPE_GUARD { delete node; }; while (MATCHES(sequence(OPERATOR_BITXOR))) { node = new ASTNodeNumericExpression(node, this->parseBinaryAndExpression(), Token::Operator::BitXor); @@ -228,7 +228,7 @@ namespace hex::lang { ASTNode* Parser::parseBinaryOrExpression() { auto node = this->parseBinaryXorExpression(); - ScopeExit nodeCleanup([&]{ delete node; }); + auto nodeCleanup = SCOPE_GUARD { delete node; }; while (MATCHES(sequence(OPERATOR_BITOR))) { node = new ASTNodeNumericExpression(node, this->parseBinaryXorExpression(), Token::Operator::BitOr); @@ -243,7 +243,7 @@ namespace hex::lang { ASTNode* Parser::parseBooleanAnd() { auto node = this->parseBinaryOrExpression(); - ScopeExit nodeCleanup([&]{ delete node; }); + auto nodeCleanup = SCOPE_GUARD { delete node; }; while (MATCHES(sequence(OPERATOR_BOOLAND))) { node = new ASTNodeNumericExpression(node, this->parseBinaryOrExpression(), Token::Operator::BitOr); @@ -258,7 +258,7 @@ namespace hex::lang { ASTNode* Parser::parseBooleanXor() { auto node = this->parseBooleanAnd(); - ScopeExit nodeCleanup([&]{ delete node; }); + auto nodeCleanup = SCOPE_GUARD { delete node; }; while (MATCHES(sequence(OPERATOR_BOOLXOR))) { node = new ASTNodeNumericExpression(node, this->parseBooleanAnd(), Token::Operator::BitOr); @@ -273,7 +273,7 @@ namespace hex::lang { ASTNode* Parser::parseBooleanOr() { auto node = this->parseBooleanXor(); - ScopeExit nodeCleanup([&]{ delete node; }); + auto nodeCleanup = SCOPE_GUARD { delete node; }; while (MATCHES(sequence(OPERATOR_BOOLOR))) { node = new ASTNodeNumericExpression(node, this->parseBooleanXor(), Token::Operator::BitOr); @@ -288,7 +288,7 @@ namespace hex::lang { ASTNode* Parser::parseTernaryConditional() { auto node = this->parseBooleanOr(); - ScopeExit nodeCleanup([&]{ delete node; }); + auto nodeCleanup = SCOPE_GUARD { delete node; }; while (MATCHES(sequence(OPERATOR_TERNARYCONDITIONAL))) { auto second = this->parseBooleanOr(); @@ -341,13 +341,13 @@ namespace hex::lang { auto condition = parseMathematicalExpression(); std::vector trueBody, falseBody; - ScopeExit cleanup([&]{ + auto cleanup = SCOPE_GUARD { delete condition; for (auto &statement : trueBody) delete statement; for (auto &statement : falseBody) delete statement; - }); + }; if (MATCHES(sequence(SEPARATOR_ROUNDBRACKETCLOSE, SEPARATOR_CURLYBRACKETOPEN))) { while (!MATCHES(sequence(SEPARATOR_CURLYBRACKETCLOSE))) { @@ -432,7 +432,7 @@ namespace hex::lang { auto name = getValue(-2); ASTNode *size = nullptr; - ScopeExit sizeCleanup([&]{ delete size; }); + auto sizeCleanup = SCOPE_GUARD { delete size; }; if (!MATCHES(sequence(SEPARATOR_SQUAREBRACKETCLOSE))) { size = parseMathematicalExpression(); @@ -494,7 +494,7 @@ namespace hex::lang { ASTNode* Parser::parseStruct() { const auto structNode = new ASTNodeStruct(); const auto &typeName = getValue(-2); - ScopeExit structGuard([&]{ delete structNode; }); + auto structGuard = SCOPE_GUARD { delete structNode; }; while (!MATCHES(sequence(SEPARATOR_CURLYBRACKETCLOSE))) { structNode->addMember(parseMember()); @@ -509,7 +509,7 @@ namespace hex::lang { ASTNode* Parser::parseUnion() { const auto unionNode = new ASTNodeUnion(); const auto &typeName = getValue(-2); - ScopeExit unionGuard([&]{ delete unionNode; }); + auto unionGuard = SCOPE_GUARD { delete unionNode; }; while (!MATCHES(sequence(SEPARATOR_CURLYBRACKETCLOSE))) { unionNode->addMember(parseMember()); @@ -533,7 +533,7 @@ namespace hex::lang { if (underlyingType->getEndian().has_value()) throwParseError("underlying type may not have an endian specification", -2); const auto enumNode = new ASTNodeEnum(underlyingType); - ScopeExit enumGuard([&]{ delete enumNode; }); + auto enumGuard = SCOPE_GUARD { delete enumNode; }; ASTNode *lastEntry = nullptr; while (!MATCHES(sequence(SEPARATOR_CURLYBRACKETCLOSE))) { @@ -577,7 +577,7 @@ namespace hex::lang { std::string typeName = getValue(-2); const auto bitfieldNode = new ASTNodeBitfield(); - ScopeExit enumGuard([&]{ delete bitfieldNode; }); + auto enumGuard = SCOPE_GUARD { delete bitfieldNode; }; while (!MATCHES(sequence(SEPARATOR_CURLYBRACKETCLOSE))) { if (MATCHES(sequence(IDENTIFIER, OPERATOR_INHERIT))) { @@ -615,7 +615,7 @@ namespace hex::lang { auto name = getValue(-2); ASTNode *size = nullptr; - ScopeExit sizeCleanup([&]{ delete size; }); + auto sizeCleanup = SCOPE_GUARD { delete size; }; if (!MATCHES(sequence(SEPARATOR_SQUAREBRACKETCLOSE))) { size = parseMathematicalExpression(); diff --git a/plugins/libimhex/source/lang/pattern_language.cpp b/plugins/libimhex/source/lang/pattern_language.cpp index 0b7afa0ac..440ffc076 100644 --- a/plugins/libimhex/source/lang/pattern_language.cpp +++ b/plugins/libimhex/source/lang/pattern_language.cpp @@ -81,7 +81,10 @@ namespace hex::lang { return { }; } - SCOPE_EXIT( for(auto &node : ast.value()) delete node; ); + ON_SCOPE_EXIT { + for(auto &node : ast.value()) + delete node; + }; auto validatorResult = this->m_validator->validate(ast.value()); if (!validatorResult) { diff --git a/source/helpers/loader_script_handler.cpp b/source/helpers/loader_script_handler.cpp index b279087c3..f7e19f389 100644 --- a/source/helpers/loader_script_handler.cpp +++ b/source/helpers/loader_script_handler.cpp @@ -79,7 +79,7 @@ namespace hex { return nullptr; } - SCOPE_EXIT( Py_DECREF(instance); ); + ON_SCOPE_EXIT { Py_DECREF(instance); }; if (instance->ob_type->tp_base == nullptr || instance->ob_type->tp_base->tp_name != "ImHexType"s) { PyErr_SetString(PyExc_TypeError, "class type must extend from ImHexType"); @@ -104,7 +104,7 @@ namespace hex { return nullptr; } - SCOPE_EXIT( Py_DECREF(list); ); + ON_SCOPE_EXIT { Py_DECREF(list); }; std::string code = keyword + " " + instance->ob_type->tp_name + " {\n"; diff --git a/source/providers/file_provider.cpp b/source/providers/file_provider.cpp index 2bd9d2f79..dbf73c5bb 100644 --- a/source/providers/file_provider.cpp +++ b/source/providers/file_provider.cpp @@ -42,11 +42,12 @@ namespace hex::prv { this->m_writable = false; } - ScopeExit fileCleanup([this]{ + auto fileCleanup = SCOPE_GUARD { this->m_readable = false; this->m_file = nullptr; CloseHandle(this->m_file); - }); + }; + if (this->m_file == nullptr || this->m_file == INVALID_HANDLE_VALUE) { return; } @@ -56,11 +57,11 @@ namespace hex::prv { return; } - ScopeExit mappingCleanup([this]{ + auto mappingCleanup = SCOPE_GUARD { this->m_readable = false; this->m_mapping = nullptr; CloseHandle(this->m_mapping); - }); + }; this->m_mappedFile = MapViewOfFile(this->m_mapping, FILE_MAP_ALL_ACCESS, 0, 0, this->m_fileSize); if (this->m_mappedFile == nullptr) { diff --git a/source/views/view_yara.cpp b/source/views/view_yara.cpp index bb78db510..3421c2e63 100644 --- a/source/views/view_yara.cpp +++ b/source/views/view_yara.cpp @@ -138,7 +138,7 @@ namespace hex { FILE *file = fopen(this->m_rules[this->m_selectedRule].c_str(), "r"); if (file == nullptr) return; - SCOPE_EXIT( fclose(file); ); + ON_SCOPE_EXIT { fclose(file); }; if (yr_compiler_add_file(compiler, file, nullptr, nullptr) != 0) { this->m_errorMessage.resize(0xFFFF);