diff --git a/lib/libimhex/include/hex/helpers/utils.hpp b/lib/libimhex/include/hex/helpers/utils.hpp index d8820fc78..ed9a0e72b 100644 --- a/lib/libimhex/include/hex/helpers/utils.hpp +++ b/lib/libimhex/include/hex/helpers/utils.hpp @@ -24,7 +24,7 @@ struct ImVec2; namespace hex { template - std::vector sampleData(const std::vector &data, size_t count) { + [[nodiscard]] std::vector sampleData(const std::vector &data, size_t count) { size_t stride = std::max(1.0, double(data.size()) / count); std::vector result; @@ -37,12 +37,12 @@ namespace hex { return result; } - float operator""_scaled(long double value); - float operator""_scaled(unsigned long long value); - ImVec2 scaled(const ImVec2 &vector); + [[nodiscard]] float operator""_scaled(long double value); + [[nodiscard]] float operator""_scaled(unsigned long long value); + [[nodiscard]] ImVec2 scaled(const ImVec2 &vector); template - std::vector operator|(const std::vector &lhs, const std::vector &rhs) { + [[nodiscard]] std::vector operator|(const std::vector &lhs, const std::vector &rhs) { std::vector result; std::copy(lhs.begin(), lhs.end(), std::back_inserter(result)); @@ -51,18 +51,19 @@ namespace hex { return result; } - std::string to_string(u128 value); - std::string to_string(i128 value); + [[nodiscard]] std::string to_string(u128 value); + [[nodiscard]] std::string to_string(i128 value); - std::optional parseBinaryString(const std::string &string); - std::string toByteString(u64 bytes); - std::string makePrintable(u8 c); + [[nodiscard]] std::vector parseHexString(std::string string); + [[nodiscard]] std::optional parseBinaryString(const std::string &string); + [[nodiscard]] std::string toByteString(u64 bytes); + [[nodiscard]] std::string makePrintable(u8 c); void runCommand(const std::string &command); void openWebpage(std::string url); - std::string encodeByteString(const std::vector &bytes); - std::vector decodeByteString(const std::string &string); + [[nodiscard]] std::string encodeByteString(const std::vector &bytes); + [[nodiscard]] std::vector decodeByteString(const std::string &string); [[nodiscard]] constexpr inline u64 extract(u8 from, u8 to, const std::unsigned_integral auto &value) { if (from < to) std::swap(from, to); @@ -88,13 +89,13 @@ namespace hex { return (value & mask) >> to; } - constexpr inline i128 signExtend(size_t numBits, i128 value) { + [[nodiscard]] constexpr inline i128 signExtend(size_t numBits, i128 value) { i128 mask = 1ULL << (numBits - 1); return (value ^ mask) - mask; } template - constexpr inline T swapBitOrder(size_t numBits, T value) { + [[nodiscard]] constexpr inline T swapBitOrder(size_t numBits, T value) { T result = 0x00; for (size_t bit = 0; bit < numBits; bit++) { @@ -105,7 +106,7 @@ namespace hex { return result; } - constexpr inline size_t strnlen(const char *s, size_t n) { + [[nodiscard]] constexpr inline size_t strnlen(const char *s, size_t n) { size_t i = 0; while (i < n && s[i] != '\x00') i++; @@ -130,7 +131,7 @@ namespace hex { using SizeType = typename SizeTypeImpl::Type; template - constexpr T changeEndianess(const T &value, size_t size, std::endian endian) { + [[nodiscard]] constexpr T changeEndianess(const T &value, size_t size, std::endian endian) { if (endian == std::endian::native) return value; @@ -150,7 +151,7 @@ namespace hex { } template - constexpr T changeEndianess(const T &value, std::endian endian) { + [[nodiscard]] constexpr T changeEndianess(const T &value, std::endian endian) { return changeEndianess(value, sizeof(value), endian); } @@ -159,12 +160,12 @@ namespace hex { } template - constexpr T bit_width(T x) noexcept { + [[nodiscard]] constexpr T bit_width(T x) noexcept { return std::numeric_limits::digits - std::countl_zero(x); } template - constexpr T bit_ceil(T x) noexcept { + [[nodiscard]] constexpr T bit_ceil(T x) noexcept { if (x <= 1u) return T(1); @@ -172,7 +173,7 @@ namespace hex { } template - auto powi(T base, U exp) { + [[nodiscard]] auto powi(T base, U exp) { using ResultType = decltype(T{} * U{}); if (exp < 0) @@ -198,20 +199,20 @@ namespace hex { } template - std::vector moveToVector(T &&first, Args &&...rest) { + [[nodiscard]] std::vector moveToVector(T &&first, Args &&...rest) { std::vector result; moveToVector(result, T(std::move(first)), std::move(rest)...); return result; } - std::vector splitString(const std::string &string, const std::string &delimiter); - std::string combineStrings(const std::vector &strings, const std::string &delimiter = ""); - std::string replaceStrings(std::string string, const std::string &search, const std::string &replace); + [[nodiscard]] std::vector splitString(const std::string &string, const std::string &delimiter); + [[nodiscard]] std::string combineStrings(const std::vector &strings, const std::string &delimiter = ""); + [[nodiscard]] std::string replaceStrings(std::string string, const std::string &search, const std::string &replace); - std::string toEngineeringString(double value); + [[nodiscard]] std::string toEngineeringString(double value); - inline std::vector parseByteString(const std::string &string) { + [[nodiscard]] inline std::vector parseByteString(const std::string &string) { auto byteString = std::string(string); byteString.erase(std::remove(byteString.begin(), byteString.end(), ' '), byteString.end()); @@ -228,7 +229,7 @@ namespace hex { return result; } - inline std::string toBinaryString(std::unsigned_integral auto number) { + [[nodiscard]] inline std::string toBinaryString(std::unsigned_integral auto number) { if (number == 0) return "0"; std::string result; @@ -238,15 +239,15 @@ namespace hex { return result; } - float float16ToFloat32(u16 float16); + [[nodiscard]] float float16ToFloat32(u16 float16); - inline bool equalsIgnoreCase(const std::string &left, const std::string &right) { + [[nodiscard]] inline bool equalsIgnoreCase(const std::string &left, const std::string &right) { return std::equal(left.begin(), left.end(), right.begin(), right.end(), [](char a, char b) { return tolower(a) == tolower(b); }); } - inline bool containsIgnoreCase(const std::string &a, const std::string &b) { + [[nodiscard]] inline bool containsIgnoreCase(const std::string &a, const std::string &b) { auto iter = std::search(a.begin(), a.end(), b.begin(), b.end(), [](char ch1, char ch2) { return std::toupper(ch1) == std::toupper(ch2); }); @@ -255,7 +256,7 @@ namespace hex { } template - T get_or(const std::variant &variant, T alt) { + [[nodiscard]] T get_or(const std::variant &variant, T alt) { const T *value = std::get_if(&variant); if (value == nullptr) return alt; @@ -264,25 +265,25 @@ namespace hex { } template - T alignTo(T value, T alignment) { + [[nodiscard]] T alignTo(T value, T alignment) { T remainder = value % alignment; return remainder != 0 ? value + (alignment - remainder) : value; } - std::optional hexCharToValue(char c); + [[nodiscard]] std::optional hexCharToValue(char c); - bool isProcessElevated(); + [[nodiscard]] bool isProcessElevated(); - std::optional getEnvironmentVariable(const std::string &env); + [[nodiscard]] std::optional getEnvironmentVariable(const std::string &env); - inline std::string limitStringLength(const std::string &string, size_t maxLength) { + [[nodiscard]] inline std::string limitStringLength(const std::string &string, size_t maxLength) { if (string.length() <= maxLength) return string; return string.substr(0, maxLength - 3) + "..."; } - std::optional getInitialFilePath(); + [[nodiscard]] std::optional getInitialFilePath(); } diff --git a/lib/libimhex/source/api/task.cpp b/lib/libimhex/source/api/task.cpp index 3ce4b7f65..ab2684535 100644 --- a/lib/libimhex/source/api/task.cpp +++ b/lib/libimhex/source/api/task.cpp @@ -4,7 +4,6 @@ #include #include -#include namespace hex { diff --git a/lib/libimhex/source/helpers/utils.cpp b/lib/libimhex/source/helpers/utils.cpp index 18c1fa9cc..6f1ea53c2 100644 --- a/lib/libimhex/source/helpers/utils.cpp +++ b/lib/libimhex/source/helpers/utils.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #define IMGUI_DEFINE_MATH_OPERATORS @@ -67,6 +68,34 @@ namespace hex { return { data + index + 1 }; } + std::vector parseHexString(std::string string) { + if (string.empty()) + return { }; + + // Remove common hex prefixes and commas + string = hex::replaceStrings(string, "0x", ""); + string = hex::replaceStrings(string, "0X", ""); + string = hex::replaceStrings(string, ",", ""); + + // Check for non-hex characters + bool isValidHexString = std::find_if(string.begin(), string.end(), [](char c) { + return !std::isxdigit(c) && !std::isspace(c); + }) == string.end(); + + if (!isValidHexString) + return { }; + + // Remove all whitespace + string.erase(std::remove_if(string.begin(), string.end(), [](char c) { return std::isspace(c); }), string.end()); + + // Only parse whole bytes + if (string.length() % 2 != 0) + return { }; + + // Convert hex string to bytes + return crypt::decode16(string); + } + std::optional parseBinaryString(const std::string &string) { if (string.empty()) return std::nullopt; diff --git a/plugins/builtin/source/content/views/view_find.cpp b/plugins/builtin/source/content/views/view_find.cpp index be0a412da..c616365eb 100644 --- a/plugins/builtin/source/content/views/view_find.cpp +++ b/plugins/builtin/source/content/views/view_find.cpp @@ -157,7 +157,7 @@ namespace hex::plugin::builtin { std::memcpy(&value, bytes.data(), bytes.size()); if (std::signed_integral) - hex::signExtend(bytes.size() * 8, value); + value = hex::signExtend(bytes.size() * 8, value); return hex::format("{}", value); } @@ -536,13 +536,12 @@ namespace hex::plugin::builtin { ImGui::BeginDisabled(this->m_replaceBuffer.empty()); if (ImGui::Button("hex.builtin.view.find.context.replace"_lang)) { + auto provider = ImHexApi::Provider::get(); + auto bytes = parseHexString(this->m_replaceBuffer); + for (const auto &occurrence : *this->m_sortedOccurrences) { if (occurrence.selected) { - auto bytes = decodeByteString(this->m_replaceBuffer); - size_t size = std::min(occurrence.region.size, bytes.size()); - - auto provider = ImHexApi::Provider::get(); provider->write(occurrence.region.getStartAddress(), bytes.data(), size); } } @@ -557,12 +556,13 @@ namespace hex::plugin::builtin { ImGui::BeginDisabled(this->m_replaceBuffer.empty()); if (ImGui::Button("hex.builtin.view.find.context.replace"_lang)) { + auto provider = ImHexApi::Provider::get(); + auto bytes = decodeByteString(this->m_replaceBuffer); + for (const auto &occurrence : *this->m_sortedOccurrences) { if (occurrence.selected) { - size_t size = std::min(occurrence.region.size, this->m_replaceBuffer.size()); - - auto provider = ImHexApi::Provider::get(); - provider->write(occurrence.region.getStartAddress(), this->m_replaceBuffer.data(), size); + size_t size = std::min(occurrence.region.size, bytes.size()); + provider->write(occurrence.region.getStartAddress(), bytes.data(), size); } } } diff --git a/plugins/builtin/source/content/views/view_hex_editor.cpp b/plugins/builtin/source/content/views/view_hex_editor.cpp index 54666fdc4..85762629d 100644 --- a/plugins/builtin/source/content/views/view_hex_editor.cpp +++ b/plugins/builtin/source/content/views/view_hex_editor.cpp @@ -654,30 +654,7 @@ namespace hex::plugin::builtin { static void pasteBytes(const Region &selection, bool selectionCheck) { auto provider = ImHexApi::Provider::get(); - std::string clipboard = ImGui::GetClipboardText(); - if (clipboard.empty()) - return; - - // Remove common hex prefixes and commas - hex::replaceStrings(clipboard, "0x", ""); - hex::replaceStrings(clipboard, "0X", ""); - hex::replaceStrings(clipboard, ",", ""); - - // Check for non-hex characters - bool isValidHexString = std::find_if(clipboard.begin(), clipboard.end(), [](char c) { - return !std::isxdigit(c) && !std::isspace(c); - }) == clipboard.end(); - - if (!isValidHexString) return; - - // Remove all whitespace - clipboard.erase(std::remove_if(clipboard.begin(), clipboard.end(), [](char c) { return std::isspace(c); }), clipboard.end()); - - // Only paste whole bytes - if (clipboard.length() % 2 != 0) return; - - // Convert hex string to bytes - std::vector buffer = crypt::decode16(clipboard); + auto buffer = parseHexString(ImGui::GetClipboardText()); if (!selectionCheck) { if (selection.getStartAddress() + buffer.size() >= provider->getActualSize())