diff --git a/src/Helpers/EnumToStringMappings.hpp b/src/Helpers/EnumToStringMappings.hpp new file mode 100644 index 00000000..1a93e144 --- /dev/null +++ b/src/Helpers/EnumToStringMappings.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include + +#include "BiMap.hpp" + +#include "src/Targets/TargetMemory.hpp" + +namespace Bloom +{ + class EnumToStringMappings + { + public: + static const inline BiMap targetMemoryTypes = { + {Targets::TargetMemoryType::RAM, "ram"}, + {Targets::TargetMemoryType::EEPROM, "eeprom"}, + {Targets::TargetMemoryType::FLASH, "flash"}, + {Targets::TargetMemoryType::OTHER, "other"}, + }; + + static const inline BiMap targetMemoryEndianness = { + {Targets::TargetMemoryEndianness::LITTLE, "little"}, + {Targets::TargetMemoryEndianness::BIG, "big"}, + }; + }; +} diff --git a/src/Insight/CMakeLists.txt b/src/Insight/CMakeLists.txt index 420b0922..f9a6c1f0 100755 --- a/src/Insight/CMakeLists.txt +++ b/src/Insight/CMakeLists.txt @@ -75,6 +75,9 @@ target_sources( ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ByteAddressItem.cpp ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/AnnotationItem.cpp ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ValueAnnotationItem.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegion.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/FocusedMemoryRegion.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/ExcludedMemoryRegion.cpp # Memory region manager window ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/MemoryRegionManagerWindow.cpp diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/ExcludedMemoryRegion.cpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/ExcludedMemoryRegion.cpp new file mode 100644 index 00000000..b39b43cd --- /dev/null +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/ExcludedMemoryRegion.cpp @@ -0,0 +1,22 @@ +#include "ExcludedMemoryRegion.hpp" + +#include "src/Exceptions/Exception.hpp" + +namespace Bloom +{ + ExcludedMemoryRegion::ExcludedMemoryRegion( + const QString& name, + Targets::TargetMemoryType memoryType, + const Targets::TargetMemoryAddressRange& addressRange + ) + : MemoryRegion(name, memoryType, MemoryRegionType::EXCLUDED, addressRange) + {} + + ExcludedMemoryRegion::ExcludedMemoryRegion(const QJsonObject& jsonObject) + : MemoryRegion(jsonObject) + { + if (this->type != MemoryRegionType::EXCLUDED) { + throw Exceptions::Exception("Invalid memory region type"); + } + } +} diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/ExcludedMemoryRegion.hpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/ExcludedMemoryRegion.hpp index 4aa7aade..ca6c09a7 100644 --- a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/ExcludedMemoryRegion.hpp +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/ExcludedMemoryRegion.hpp @@ -7,9 +7,12 @@ namespace Bloom class ExcludedMemoryRegion: public MemoryRegion { public: - explicit ExcludedMemoryRegion( + ExcludedMemoryRegion( const QString& name, + Targets::TargetMemoryType memoryType, const Targets::TargetMemoryAddressRange& addressRange - ): MemoryRegion(name, MemoryRegionType::EXCLUDED, addressRange) {}; + ); + + ExcludedMemoryRegion(const QJsonObject& jsonObject); }; } diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/FocusedMemoryRegion.cpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/FocusedMemoryRegion.cpp new file mode 100644 index 00000000..da166814 --- /dev/null +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/FocusedMemoryRegion.cpp @@ -0,0 +1,22 @@ +#include "FocusedMemoryRegion.hpp" + +#include "src/Exceptions/Exception.hpp" + +namespace Bloom +{ + FocusedMemoryRegion::FocusedMemoryRegion( + const QString& name, + Targets::TargetMemoryType memoryType, + const Targets::TargetMemoryAddressRange& addressRange + ) + : MemoryRegion(name, memoryType, MemoryRegionType::FOCUSED, addressRange) + {} + + FocusedMemoryRegion::FocusedMemoryRegion(const QJsonObject& jsonObject) + : MemoryRegion(jsonObject) + { + if (this->type != MemoryRegionType::FOCUSED) { + throw Exceptions::Exception("Invalid memory region type"); + } + } +} diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/FocusedMemoryRegion.hpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/FocusedMemoryRegion.hpp index cd5c7217..7412b205 100644 --- a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/FocusedMemoryRegion.hpp +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/FocusedMemoryRegion.hpp @@ -20,9 +20,12 @@ namespace Bloom MemoryRegionDataType dataType = MemoryRegionDataType::UNKNOWN; Targets::TargetMemoryEndianness endianness = Targets::TargetMemoryEndianness::LITTLE; - explicit FocusedMemoryRegion( + FocusedMemoryRegion( const QString& name, + Targets::TargetMemoryType memoryType, const Targets::TargetMemoryAddressRange& addressRange - ): MemoryRegion(name, MemoryRegionType::FOCUSED, addressRange) {}; + ); + + FocusedMemoryRegion(const QJsonObject& jsonObject); }; } diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegion.cpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegion.cpp new file mode 100644 index 00000000..310f1e7a --- /dev/null +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegion.cpp @@ -0,0 +1,67 @@ +#include "MemoryRegion.hpp" + +#include "src/Helpers/EnumToStringMappings.hpp" +#include "src/Exceptions/Exception.hpp" + +namespace Bloom +{ + MemoryRegion::MemoryRegion( + const QString& name, + Targets::TargetMemoryType memoryType, + MemoryRegionType type, + const Targets::TargetMemoryAddressRange& addressRange + ) + : name(name) + , memoryType(memoryType) + , type(type) + , addressRange(addressRange) + {} + + MemoryRegion::MemoryRegion(const QJsonObject& jsonObject) { + using Exceptions::Exception; + + if ( + !jsonObject.contains("name") + || !jsonObject.contains("memoryType") + || !jsonObject.contains("type") + || !jsonObject.contains("createdTimestamp") + || !jsonObject.contains("addressInputType") + || !jsonObject.contains("addressRange") + ) { + throw Exception("Missing data"); + } + + const auto addressRangeObj = jsonObject.find("addressRange")->toObject(); + if ( + !addressRangeObj.contains("startAddress") + || !addressRangeObj.contains("endAddress") + ) { + throw Exception("Missing address range data"); + } + + this->name = jsonObject.find("name")->toString(); + this->memoryType = EnumToStringMappings::targetMemoryTypes.at(jsonObject.find("memoryType")->toString()); + this->type = MemoryRegion::memoryRegionTypesByName.at(jsonObject.find("type")->toString()); + this->createdDate.setSecsSinceEpoch(jsonObject.find("createdTimestamp")->toInteger()); + this->addressRangeInputType = MemoryRegion::addressTypesByName.at(jsonObject.find("addressInputType")->toString()); + + this->addressRange = { + static_cast(addressRangeObj.find("startAddress")->toInteger()), + static_cast(addressRangeObj.find("endAddress")->toInteger()), + }; + } + + QJsonObject MemoryRegion::toJson() const { + return QJsonObject({ + {"name", this->name}, + {"memoryType", EnumToStringMappings::targetMemoryTypes.at(this->memoryType)}, + {"type", MemoryRegion::memoryRegionTypesByName.at(this->type)}, + {"createdTimestamp", this->createdDate.toSecsSinceEpoch()}, + {"addressInputType", MemoryRegion::addressTypesByName.at(this->addressRangeInputType)}, + {"addressRange", QJsonObject({ + {"startAddress", static_cast(this->addressRange.startAddress)}, + {"endAddress", static_cast(this->addressRange.endAddress)}, + })}, + }); + } +} diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegion.hpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegion.hpp index 15187e9c..5a3a9101 100644 --- a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegion.hpp +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegion.hpp @@ -3,10 +3,12 @@ #include #include #include +#include #include #include "src/Targets/TargetMemory.hpp" #include "src/Helpers/DateTime.hpp" +#include "src/Helpers/BiMap.hpp" #include "AddressType.hpp" namespace Bloom @@ -28,6 +30,7 @@ namespace Bloom public: QString name; QDateTime createdDate = DateTime::currentDateTime(); + Targets::TargetMemoryType memoryType; MemoryRegionType type; /** @@ -50,10 +53,15 @@ namespace Bloom Targets::TargetMemoryAddressRange addressRange; MemoryRegion( - QString name, + const QString& name, + Targets::TargetMemoryType memoryType, MemoryRegionType type, const Targets::TargetMemoryAddressRange& addressRange - ): name(std::move(name)), type(type), addressRange(addressRange) {}; + ); + + MemoryRegion(const QJsonObject& jsonObject); + + virtual QJsonObject toJson() const; virtual ~MemoryRegion() = default; @@ -66,5 +74,16 @@ namespace Bloom [[nodiscard]] bool intersectsWith(const MemoryRegion& other) const { return this->addressRange.intersectsWith(other.addressRange); } + + private: + static const inline BiMap memoryRegionTypesByName = { + {MemoryRegionType::EXCLUDED, "excluded"}, + {MemoryRegionType::FOCUSED, "focused"}, + }; + + static const inline BiMap addressTypesByName = { + {AddressType::ABSOLUTE, "absolute"}, + {AddressType::RELATIVE, "relative"}, + }; }; } diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/MemoryRegionManagerWindow.cpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/MemoryRegionManagerWindow.cpp index be39ef71..880dafe9 100644 --- a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/MemoryRegionManagerWindow.cpp +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/MemoryRegionManagerWindow.cpp @@ -249,6 +249,7 @@ namespace Bloom::Widgets auto* region = this->addFocusedRegion(FocusedMemoryRegion( "Untitled Region", + this->memoryDescriptor.type, TargetMemoryAddressRange( this->memoryDescriptor.addressRange.startAddress, this->memoryDescriptor.addressRange.startAddress + 10 @@ -263,6 +264,7 @@ namespace Bloom::Widgets auto* region = this->addExcludedRegion(ExcludedMemoryRegion( "Untitled Region", + this->memoryDescriptor.type, TargetMemoryAddressRange( this->memoryDescriptor.addressRange.startAddress, this->memoryDescriptor.addressRange.startAddress + 10 diff --git a/src/ProjectSettings.cpp b/src/ProjectSettings.cpp index 31d9045a..3e05fc36 100644 --- a/src/ProjectSettings.cpp +++ b/src/ProjectSettings.cpp @@ -2,6 +2,10 @@ #include +#include "src/Helpers/EnumToStringMappings.hpp" +#include "src/Logger/Logger.hpp" +#include "src/Exceptions/Exception.hpp" + namespace Bloom { ProjectSettings::ProjectSettings(const QJsonObject& jsonObject) { @@ -67,12 +71,12 @@ namespace Bloom const auto settingsObj = settingsIt.value().toObject(); const auto memoryTypeName = settingsIt.key(); - if (!InsightProjectSettings::memoryTypesByName.contains(memoryTypeName)) { + if (!EnumToStringMappings::targetMemoryTypes.contains(memoryTypeName)) { continue; } this->memoryInspectionPaneSettingsByMemoryType.insert(std::pair( - InsightProjectSettings::memoryTypesByName.at(memoryTypeName), + EnumToStringMappings::targetMemoryTypes.at(memoryTypeName), this->memoryInspectionPaneSettingsFromJson(settingsObj) )); } @@ -92,13 +96,13 @@ namespace Bloom auto memoryInspectionPaneSettingsObj = QJsonObject(); for (const auto& [memoryType, inspectionPaneSettings] : this->memoryInspectionPaneSettingsByMemoryType) { - if (!InsightProjectSettings::memoryTypesByName.contains(memoryType)) { + if (!EnumToStringMappings::targetMemoryTypes.contains(memoryType)) { // This is just a precaution - all known memory types should be in the mapping. continue; } memoryInspectionPaneSettingsObj.insert( - InsightProjectSettings::memoryTypesByName.at(memoryType), + EnumToStringMappings::targetMemoryTypes.at(memoryType), this->memoryInspectionPaneSettingsToJson(inspectionPaneSettings) ); } @@ -146,6 +150,8 @@ namespace Bloom Widgets::TargetMemoryInspectionPaneSettings InsightProjectSettings::memoryInspectionPaneSettingsFromJson( const QJsonObject& jsonObject ) const { + using Exceptions::Exception; + auto inspectionPaneSettings = Widgets::TargetMemoryInspectionPaneSettings(); if (jsonObject.contains("refreshOnTargetStop")) { @@ -193,105 +199,34 @@ namespace Bloom } if (jsonObject.contains("focusedRegions")) { - const auto focusedRegions = jsonObject.find("focusedRegions")->toArray(); + for (const auto& regionValue : jsonObject.find("focusedRegions")->toArray()) { + try { + inspectionPaneSettings.focusedMemoryRegions.push_back( + FocusedMemoryRegion(regionValue.toObject()) + ); - for (const auto& regionValue : focusedRegions) { - const auto regionObj = regionValue.toObject(); - - if (!regionObj.contains("name") - || !regionObj.contains("addressRange") - || !regionObj.contains("addressInputType") - || !regionObj.contains("createdTimestamp") - || !regionObj.contains("dataType") - ) { - continue; + } catch (Exception exception) { + Logger::warning( + "Failed to parse focused memory region from project settings file - " + + exception.getMessage() + " - region will be ignored." + ); } - - const auto addressRangeObj = regionObj.find("addressRange")->toObject(); - if (!addressRangeObj.contains("startAddress") - || !addressRangeObj.contains("endAddress") - ) { - continue; - } - - auto region = FocusedMemoryRegion( - regionObj.find("name")->toString(), - { - static_cast(addressRangeObj.find("startAddress")->toInteger()), - static_cast(addressRangeObj.find("endAddress")->toInteger()), - } - ); - - region.createdDate.setSecsSinceEpoch(regionObj.find("createdTimestamp")->toInteger()); - - const auto addressInputType = InsightProjectSettings::addressTypesByName.valueAt( - regionObj.find("addressInputType")->toString() - ); - - if (addressInputType.has_value()) { - region.addressRangeInputType = addressInputType.value(); - } - - const auto dataType = InsightProjectSettings::regionDataTypesByName.valueAt( - regionObj.find("dataType")->toString() - ); - - if (dataType.has_value()) { - region.dataType = dataType.value(); - } - - const auto endianness = InsightProjectSettings::regionEndiannessByName.valueAt( - regionObj.find("endianness")->toString() - ); - - if (endianness.has_value()) { - region.endianness = endianness.value(); - } - - inspectionPaneSettings.focusedMemoryRegions.emplace_back(region); } } if (jsonObject.contains("excludedRegions")) { - const auto excludedRegions = jsonObject.find("excludedRegions")->toArray(); + for (const auto& regionValue : jsonObject.find("excludedRegions")->toArray()) { + try { + inspectionPaneSettings.excludedMemoryRegions.emplace_back( + ExcludedMemoryRegion(regionValue.toObject()) + ); - for (const auto& regionValue : excludedRegions) { - const auto regionObj = regionValue.toObject(); - - if (!regionObj.contains("name") - || !regionObj.contains("addressRange") - || !regionObj.contains("addressInputType") - || !regionObj.contains("createdTimestamp") - ) { - continue; + } catch (Exception exception) { + Logger::warning( + "Failed to parse excluded memory region from project settings file - " + + exception.getMessage() + " - region will be ignored." + ); } - - const auto addressRangeObj = regionObj.find("addressRange")->toObject(); - if (!addressRangeObj.contains("startAddress") - || !addressRangeObj.contains("endAddress") - ) { - continue; - } - - auto region = ExcludedMemoryRegion( - regionObj.find("name")->toString(), - { - static_cast(addressRangeObj.find("startAddress")->toInteger()), - static_cast(addressRangeObj.find("endAddress")->toInteger()), - } - ); - - region.createdDate.setSecsSinceEpoch(regionObj.find("createdTimestamp")->toInteger()); - - const auto addressInputType = InsightProjectSettings::addressTypesByName.valueAt( - regionObj.find("addressInputType")->toString() - ); - - if (addressInputType.has_value()) { - region.addressRangeInputType = addressInputType.value(); - } - - inspectionPaneSettings.excludedMemoryRegions.emplace_back(region); } } @@ -340,8 +275,6 @@ namespace Bloom QJsonObject InsightProjectSettings::memoryInspectionPaneSettingsToJson( const Widgets::TargetMemoryInspectionPaneSettings& inspectionPaneSettings ) const { - const auto& regionDataTypesByName = InsightProjectSettings::regionDataTypesByName; - const auto& regionEndiannessByName = InsightProjectSettings::regionEndiannessByName; const auto& addressTypesByName = InsightProjectSettings::addressTypesByName; auto settingsObj = QJsonObject({ @@ -361,49 +294,12 @@ namespace Bloom auto focusedRegions = QJsonArray(); for (const auto& focusedRegion : inspectionPaneSettings.focusedMemoryRegions) { - if (!regionDataTypesByName.contains(focusedRegion.dataType) - || !regionEndiannessByName.contains(focusedRegion.endianness) - || !addressTypesByName.contains(focusedRegion.addressRangeInputType) - ) { - continue; - } - - const auto addressRangeObj = QJsonObject({ - {"startAddress", static_cast(focusedRegion.addressRange.startAddress)}, - {"endAddress", static_cast(focusedRegion.addressRange.endAddress)}, - }); - - auto regionObj = QJsonObject({ - {"name", focusedRegion.name}, - {"addressRange", addressRangeObj}, - {"createdTimestamp", focusedRegion.createdDate.toSecsSinceEpoch()}, - {"addressInputType", addressTypesByName.at(focusedRegion.addressRangeInputType)}, - {"dataType", regionDataTypesByName.at(focusedRegion.dataType)}, - {"endianness", regionEndiannessByName.at(focusedRegion.endianness)}, - }); - - focusedRegions.push_back(regionObj); + focusedRegions.push_back(focusedRegion.toJson()); } auto excludedRegions = QJsonArray(); for (const auto& excludedRegion : inspectionPaneSettings.excludedMemoryRegions) { - if (!addressTypesByName.contains(excludedRegion.addressRangeInputType)) { - continue; - } - - const auto addressRangeObj = QJsonObject({ - {"startAddress", static_cast(excludedRegion.addressRange.startAddress)}, - {"endAddress", static_cast(excludedRegion.addressRange.endAddress)}, - }); - - auto regionObj = QJsonObject({ - {"name", excludedRegion.name}, - {"addressRange", addressRangeObj}, - {"createdTimestamp", excludedRegion.createdDate.toSecsSinceEpoch()}, - {"addressInputType", addressTypesByName.at(excludedRegion.addressRangeInputType)}, - }); - - excludedRegions.push_back(regionObj); + excludedRegions.push_back(excludedRegion.toJson()); } settingsObj.insert("focusedRegions", focusedRegions); diff --git a/src/ProjectSettings.hpp b/src/ProjectSettings.hpp index 40bc1cc9..e5e94f42 100644 --- a/src/ProjectSettings.hpp +++ b/src/ProjectSettings.hpp @@ -42,18 +42,6 @@ namespace Bloom {Targets::TargetMemoryType::EEPROM, "eeprom"}, }; - static const inline BiMap regionDataTypesByName = { - {MemoryRegionDataType::UNKNOWN, "other"}, - {MemoryRegionDataType::UNSIGNED_INTEGER, "unsigned_int"}, - {MemoryRegionDataType::SIGNED_INTEGER, "signed_int"}, - {MemoryRegionDataType::ASCII_STRING, "ascii_string"}, - }; - - static const inline BiMap regionEndiannessByName = { - {Targets::TargetMemoryEndianness::LITTLE, "little"}, - {Targets::TargetMemoryEndianness::BIG, "big"}, - }; - static const inline BiMap addressTypesByName = { {AddressType::ABSOLUTE, "absolute"}, {AddressType::RELATIVE, "relative"},