From 989eade5d737bd9ff63f5c85677e0c16cea7461c Mon Sep 17 00:00:00 2001 From: WerWolv Date: Sun, 22 Nov 2020 15:32:37 +0100 Subject: [PATCH] Added big and little endian support to inspector --- CMakeLists.txt | 2 +- include/utils.hpp | 26 ++++++++++++ include/views/view_data_inspector.hpp | 3 ++ source/views/view_data_inspector.cpp | 61 ++++++++++++++++++--------- source/views/view_hashes.cpp | 8 +--- 5 files changed, 72 insertions(+), 28 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c1503889..c42d8ba87 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,7 +53,7 @@ add_executable(ImHex ) if (WIN32) - target_link_libraries(ImHex libglfw3.a libgcc.a libstdc++.a libmagic.a libgnurx.a libtre.a libintl.a libiconv.a shlwapi.lib ws2_32.lib libcrypto.a libwinpthread.a) + target_link_libraries(ImHex libglfw3.a libgcc.a libstdc++.a libmagic.a libgnurx.a libtre.a libintl.a libiconv.a shlwapi.lib libcrypto.a libwinpthread.a) endif (WIN32) if (UNIX) diff --git a/include/utils.hpp b/include/utils.hpp index 03606c4fd..0eb420db6 100644 --- a/include/utils.hpp +++ b/include/utils.hpp @@ -9,6 +9,12 @@ #include #include +#ifdef __MINGW32__ +#include +#else +#include +#endif + #include "lang/token.hpp" namespace hex { @@ -80,6 +86,26 @@ namespace hex { return (value & mask) >> to; } + template + struct always_false : std::false_type {}; + + template + constexpr T changeEndianess(T value, std::endian endian) { + if (endian == std::endian::native) + return value; + + if constexpr (sizeof(T) == 1) + return value; + else if constexpr (sizeof(T) == 2) + return __builtin_bswap16(value); + else if constexpr (sizeof(T) == 4) + return __builtin_bswap32(value); + else if constexpr (sizeof(T) == 8) + return __builtin_bswap64(value); + else + static_assert(always_false::value, "Invalid type provided!"); + } + class ScopeExit { public: diff --git a/include/views/view_data_inspector.hpp b/include/views/view_data_inspector.hpp index f19e7dc06..5b43dca6e 100644 --- a/include/views/view_data_inspector.hpp +++ b/include/views/view_data_inspector.hpp @@ -2,6 +2,7 @@ #include "views/view.hpp" +#include #include #include #include @@ -53,6 +54,8 @@ namespace hex { bool m_windowOpen = true; bool m_shouldInvalidate = true; + std::endian m_endianess = std::endian::native; + PreviewData m_previewData = { 0 }; size_t m_validBytes = 0; std::vector> m_cachedData; diff --git a/source/views/view_data_inspector.cpp b/source/views/view_data_inspector.cpp index 7e50e3416..ea802f343 100644 --- a/source/views/view_data_inspector.cpp +++ b/source/views/view_data_inspector.cpp @@ -41,31 +41,36 @@ namespace hex { this->m_cachedData.emplace_back("Binary (8 bit)", binary); } - this->m_cachedData.emplace_back("uint8_t", hex::format("%u", this->m_previewData.unsigned8)); - this->m_cachedData.emplace_back("int8_t", hex::format("%d", this->m_previewData.signed8)); - this->m_cachedData.emplace_back("uint16_t", hex::format("%u", this->m_previewData.unsigned16)); - this->m_cachedData.emplace_back("int16_t", hex::format("%d", this->m_previewData.signed16)); - this->m_cachedData.emplace_back("uint32_t", hex::format("%lu", this->m_previewData.unsigned32)); - this->m_cachedData.emplace_back("int32_t", hex::format("%ld", this->m_previewData.signed32)); - this->m_cachedData.emplace_back("uint64_t", hex::format("%llu", this->m_previewData.unsigned64)); - this->m_cachedData.emplace_back("int64_t", hex::format("%lld", this->m_previewData.signed64)); + this->m_cachedData.emplace_back("uint8_t", hex::format("%u", hex::changeEndianess(this->m_previewData.unsigned8, this->m_endianess))); + this->m_cachedData.emplace_back("int8_t", hex::format("%d", hex::changeEndianess(this->m_previewData.signed8, this->m_endianess))); + this->m_cachedData.emplace_back("uint16_t", hex::format("%u", hex::changeEndianess(this->m_previewData.unsigned16, this->m_endianess))); + this->m_cachedData.emplace_back("int16_t", hex::format("%d", hex::changeEndianess(this->m_previewData.signed16, this->m_endianess))); + this->m_cachedData.emplace_back("uint32_t", hex::format("%lu", hex::changeEndianess(this->m_previewData.unsigned32, this->m_endianess))); + this->m_cachedData.emplace_back("int32_t", hex::format("%ld", hex::changeEndianess(this->m_previewData.signed32, this->m_endianess))); + this->m_cachedData.emplace_back("uint64_t", hex::format("%llu", hex::changeEndianess(this->m_previewData.unsigned64, this->m_endianess))); + this->m_cachedData.emplace_back("int64_t", hex::format("%lld", hex::changeEndianess(this->m_previewData.signed64, this->m_endianess))); - this->m_cachedData.emplace_back("ANSI Character / char8_t", hex::format("%c", this->m_previewData.ansiChar)); - this->m_cachedData.emplace_back("Wide Character / char16_t", hex::format("%lc", this->m_previewData.wideChar)); + this->m_cachedData.emplace_back("ANSI Character / char8_t", hex::format("%c", hex::changeEndianess(this->m_previewData.ansiChar, this->m_endianess))); + this->m_cachedData.emplace_back("Wide Character / char16_t", hex::format("%lc", hex::changeEndianess(this->m_previewData.wideChar, this->m_endianess))); { char buffer[5] = { 0 }; + char codepointString[5] = { 0 }; + u32 codepoint = 0; + u8 codepointSize = ImTextCharFromUtf8(&codepoint, buffer, buffer + 4); + std::memcpy(buffer, &this->m_previewData.utf8Char, 4); - u32 utf8 = 0; - ImTextCharFromUtf8(&utf8, buffer, buffer + 4); - this->m_cachedData.emplace_back("UTF-8 code point", hex::format("U+%08lx", utf8)); + std::memcpy(codepointString, &codepoint, std::min(codepointSize, u8(4))); + + this->m_cachedData.emplace_back("UTF-8 code point", hex::format("'%s' (U+%04lx)", codepoint == 0xFFFD ? "Invalid" : codepointString, codepoint)); } - this->m_cachedData.emplace_back("float (32 bit)", hex::format("%e", this->m_previewData.float32)); - this->m_cachedData.emplace_back("double (64 bit)", hex::format("%e", this->m_previewData.float64)); + this->m_cachedData.emplace_back("float (32 bit)", hex::format("%e", hex::changeEndianess(this->m_previewData.float32, this->m_endianess))); + this->m_cachedData.emplace_back("double (64 bit)", hex::format("%e", hex::changeEndianess(this->m_previewData.float64, this->m_endianess))); #if defined(_WIN64) { - std::tm * ptm = _localtime32(&this->m_previewData.time32); + auto endianAdjustedTime = hex::changeEndianess(this->m_previewData.time32, this->m_endianess); + std::tm * ptm = _localtime32(&endianAdjustedTime); char buffer[32]; if (std::strftime(buffer, 32, "%a, %d.%m.%Y %H:%M:%S", ptm)) this->m_cachedData.emplace_back("__time32_t", buffer); @@ -74,7 +79,8 @@ namespace hex { } { - std::tm * ptm = _localtime64(&this->m_previewData.time64); + auto endianAdjustedTime = hex::changeEndianess(this->m_previewData.time64, this->m_endianess); + std::tm * ptm = _localtime64(&endianAdjustedTime); char buffer[64]; if (std::strftime(buffer, 64, "%a, %d.%m.%Y %H:%M:%S", ptm) != 0) this->m_cachedData.emplace_back("__time64_t", buffer); @@ -83,7 +89,8 @@ namespace hex { } #else { - std::tm * ptm = localtime(&this->m_previewData.time); + auto endianAdjustedTime = hex::changeEndianess(this->m_previewData.time, this->m_endianess); + std::tm * ptm = localtime(&endianAdjustedTime); char buffer[64]; if (std::strftime(buffer, 64, "%a, %d.%m.%Y %H:%M:%S", ptm) != 0) this->m_cachedData.emplace_back("time_t", buffer); @@ -93,7 +100,9 @@ namespace hex { #endif this->m_cachedData.emplace_back("GUID", hex::format("{%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}", - this->m_previewData.guid.data1, this->m_previewData.guid.data2, this->m_previewData.guid.data3, + hex::changeEndianess(this->m_previewData.guid.data1, this->m_endianess), + hex::changeEndianess(this->m_previewData.guid.data2, this->m_endianess), + hex::changeEndianess(this->m_previewData.guid.data3, this->m_endianess), this->m_previewData.guid.data4[0], this->m_previewData.guid.data4[1], this->m_previewData.guid.data4[2], this->m_previewData.guid.data4[3], this->m_previewData.guid.data4[4], this->m_previewData.guid.data4[5], this->m_previewData.guid.data4[6], this->m_previewData.guid.data4[7])); } @@ -101,7 +110,7 @@ namespace hex { if (ImGui::Begin("Data Inspector", &this->m_windowOpen)) { if (this->m_dataProvider != nullptr && this->m_dataProvider->isReadable()) { - if (ImGui::BeginChild("##scrolling")) { + if (ImGui::BeginChild("##scrolling", ImVec2(0, ImGui::GetWindowHeight() - 60))) { if (ImGui::BeginTable("##datainspector", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg)) { ImGui::TableSetupColumn("Name"); ImGui::TableSetupColumn("Value"); @@ -124,7 +133,7 @@ namespace hex { ImGui::TableNextColumn(); ImGui::TextUnformatted("RGBA Color"); ImGui::TableNextColumn(); - ImGui::ColorButton("##nolabel", ImColor(this->m_previewData.unsigned32), + ImGui::ColorButton("##nolabel", ImColor(hex::changeEndianess(this->m_previewData.unsigned32, this->m_endianess)), ImGuiColorEditFlags_None, ImVec2(ImGui::GetColumnWidth(), 15)); ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, ((rowCount % 2) == 0) ? 0xFF101010 : 0xFF303030); @@ -136,6 +145,16 @@ namespace hex { } } ImGui::EndChild(); + + if (ImGui::RadioButton("Little Endian", this->m_endianess == std::endian::little)) { + this->m_endianess = std::endian::little; + this->m_shouldInvalidate = true; + } + ImGui::SameLine(); + if (ImGui::RadioButton("Big Endian", this->m_endianess == std::endian::big)) { + this->m_endianess = std::endian::big; + this->m_shouldInvalidate = true; + } } } ImGui::End(); diff --git a/source/views/view_hashes.cpp b/source/views/view_hashes.cpp index da1000731..8ac9c64b6 100644 --- a/source/views/view_hashes.cpp +++ b/source/views/view_hashes.cpp @@ -6,11 +6,7 @@ #include -#ifdef __MINGW32__ -#include -#else -#include -#endif +#include "utils.hpp" namespace hex { @@ -27,7 +23,7 @@ namespace hex { static void formatBigHexInt(auto dataArray, char *buffer, size_t bufferSize) { for (int i = 0; i < dataArray.size(); i++) - snprintf(buffer + 8 * i, bufferSize - 8 * i, "%08X", htonl(dataArray[i])); + snprintf(buffer + 8 * i, bufferSize - 8 * i, "%08X", hex::changeEndianess(dataArray[i], std::endian::big)); } void ViewHashes::createView() {