Began updating TDF parsing to align with new format.
- Convenience functions for fetching attributes from XML elements - Property groups are now being parsed correctly - Property group lookups (including nested lookups) are working correctly
This commit is contained in:
@@ -6,11 +6,14 @@
|
|||||||
#include "Exceptions/TargetDescriptionParsingFailureException.hpp"
|
#include "Exceptions/TargetDescriptionParsingFailureException.hpp"
|
||||||
#include "src/Logger/Logger.hpp"
|
#include "src/Logger/Logger.hpp"
|
||||||
#include "src/Services/PathService.hpp"
|
#include "src/Services/PathService.hpp"
|
||||||
|
#include "src/Services/StringService.hpp"
|
||||||
|
|
||||||
namespace Targets::TargetDescription
|
namespace Targets::TargetDescription
|
||||||
{
|
{
|
||||||
using namespace Exceptions;
|
using namespace Exceptions;
|
||||||
|
|
||||||
|
using Services::StringService;
|
||||||
|
|
||||||
const std::map<std::string, GeneratedMapping::BriefTargetDescriptor>& TargetDescriptionFile::mapping() {
|
const std::map<std::string, GeneratedMapping::BriefTargetDescriptor>& TargetDescriptionFile::mapping() {
|
||||||
return GeneratedMapping::map;
|
return GeneratedMapping::map;
|
||||||
}
|
}
|
||||||
@@ -42,6 +45,31 @@ namespace Targets::TargetDescription
|
|||||||
return familyIt->second;
|
return familyIt->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<std::reference_wrapper<const PropertyGroup>> TargetDescriptionFile::tryGetPropertyGroup(
|
||||||
|
std::string_view keyStr
|
||||||
|
) const {
|
||||||
|
auto keys = StringService::split(keyStr, '.');
|
||||||
|
|
||||||
|
const auto firstSubGroupIt = this->propertyGroupsMappedByKey.find(*keys.begin());
|
||||||
|
return firstSubGroupIt != this->propertyGroupsMappedByKey.end()
|
||||||
|
? keys.size() > 1
|
||||||
|
? firstSubGroupIt->second.getSubGroup(keys | std::ranges::views::drop(1))
|
||||||
|
: std::optional(std::cref(firstSubGroupIt->second))
|
||||||
|
: std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PropertyGroup& TargetDescriptionFile::getPropertyGroup(std::string_view keyStr) const {
|
||||||
|
const auto propertyGroup = this->tryGetPropertyGroup(keyStr);
|
||||||
|
|
||||||
|
if (!propertyGroup.has_value()) {
|
||||||
|
throw Exception(
|
||||||
|
"Failed to get property group \"" + std::string(keyStr) + "\" from TDF - property group not found"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return propertyGroup->get();
|
||||||
|
}
|
||||||
|
|
||||||
void TargetDescriptionFile::init(const std::string& xmlFilePath) {
|
void TargetDescriptionFile::init(const std::string& xmlFilePath) {
|
||||||
auto file = QFile(QString::fromStdString(xmlFilePath));
|
auto file = QFile(QString::fromStdString(xmlFilePath));
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
@@ -60,12 +88,12 @@ namespace Targets::TargetDescription
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TargetDescriptionFile::init(const QDomDocument& document) {
|
void TargetDescriptionFile::init(const QDomDocument& document) {
|
||||||
const auto device = document.elementsByTagName("device").item(0).toElement();
|
const auto deviceElement = document.documentElement();
|
||||||
if (!device.isElement()) {
|
if (deviceElement.nodeName() != "device") {
|
||||||
throw TargetDescriptionParsingFailureException("Device element not found.");
|
throw TargetDescriptionParsingFailureException("Root \"device\" element not found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto deviceAttributes = device.attributes();
|
const auto deviceAttributes = deviceElement.attributes();
|
||||||
for (auto i = 0; i < deviceAttributes.length(); ++i) {
|
for (auto i = 0; i < deviceAttributes.length(); ++i) {
|
||||||
const auto deviceAttribute = deviceAttributes.item(i);
|
const auto deviceAttribute = deviceAttributes.item(i);
|
||||||
this->deviceAttributesByName.insert(
|
this->deviceAttributesByName.insert(
|
||||||
@@ -76,8 +104,18 @@ namespace Targets::TargetDescription
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (
|
||||||
|
auto element = deviceElement.firstChildElement("property-groups").firstChildElement("property-group");
|
||||||
|
!element.isNull();
|
||||||
|
element = element.nextSiblingElement("property-group")
|
||||||
|
) {
|
||||||
|
auto propertyGroup = TargetDescriptionFile::propertyGroupFromXml(element);
|
||||||
|
this->propertyGroupsMappedByKey.insert(
|
||||||
|
std::pair(propertyGroup.key, std::move(propertyGroup))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
this->loadAddressSpaces(document);
|
this->loadAddressSpaces(document);
|
||||||
this->loadPropertyGroups(document);
|
|
||||||
this->loadModules(document);
|
this->loadModules(document);
|
||||||
this->loadPeripheralModules(document);
|
this->loadPeripheralModules(document);
|
||||||
this->loadVariants(document);
|
this->loadVariants(document);
|
||||||
@@ -85,6 +123,59 @@ namespace Targets::TargetDescription
|
|||||||
this->loadInterfaces(document);
|
this->loadInterfaces(document);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> TargetDescriptionFile::tryGetAttribute(
|
||||||
|
const QDomElement& element,
|
||||||
|
const QString& attributeName
|
||||||
|
) {
|
||||||
|
return element.hasAttribute(attributeName)
|
||||||
|
? std::optional(element.attribute(attributeName).toStdString())
|
||||||
|
: std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string TargetDescriptionFile::getAttribute(const QDomElement& element, const QString& attributeName) {
|
||||||
|
const auto attribute = TargetDescriptionFile::tryGetAttribute(element, attributeName);
|
||||||
|
|
||||||
|
if (!attribute.has_value()) {
|
||||||
|
throw Exception(
|
||||||
|
"Failed to fetch attribute from TDF element \"" + element.nodeName().toStdString()
|
||||||
|
+ "\" - attribute \"" + attributeName.toStdString() + "\" not found"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *attribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyGroup TargetDescriptionFile::propertyGroupFromXml(const QDomElement& xmlElement) {
|
||||||
|
auto output = PropertyGroup(TargetDescriptionFile::getAttribute(xmlElement, "key"), {}, {});
|
||||||
|
|
||||||
|
for (
|
||||||
|
auto element = xmlElement.firstChildElement("property");
|
||||||
|
!element.isNull();
|
||||||
|
element = element.nextSiblingElement("property")
|
||||||
|
) {
|
||||||
|
auto property = TargetDescriptionFile::propertyFromXml(element);
|
||||||
|
output.propertiesMappedByKey.insert(std::pair(property.key, std::move(property)));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (
|
||||||
|
auto element = xmlElement.firstChildElement("property-group");
|
||||||
|
!element.isNull();
|
||||||
|
element = element.nextSiblingElement("property-group")
|
||||||
|
) {
|
||||||
|
auto subGroup = TargetDescriptionFile::propertyGroupFromXml(element);
|
||||||
|
output.subGroupsMappedByKey.insert(std::pair(subGroup.key, std::move(subGroup)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
Property TargetDescriptionFile::propertyFromXml(const QDomElement& xmlElement) {
|
||||||
|
return Property(
|
||||||
|
TargetDescriptionFile::getAttribute(xmlElement, "key"),
|
||||||
|
TargetDescriptionFile::getAttribute(xmlElement, "value")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
AddressSpace TargetDescriptionFile::addressSpaceFromXml(const QDomElement& xmlElement) {
|
AddressSpace TargetDescriptionFile::addressSpaceFromXml(const QDomElement& xmlElement) {
|
||||||
if (
|
if (
|
||||||
!xmlElement.hasAttribute("id")
|
!xmlElement.hasAttribute("id")
|
||||||
@@ -346,38 +437,6 @@ namespace Targets::TargetDescription
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TargetDescriptionFile::loadPropertyGroups(const QDomDocument& document) {
|
|
||||||
const auto deviceElement = document.elementsByTagName("device").item(0).toElement();
|
|
||||||
|
|
||||||
auto propertyGroupNodes = deviceElement.elementsByTagName("property-groups").item(0).toElement()
|
|
||||||
.elementsByTagName("property-group");
|
|
||||||
|
|
||||||
for (int propertyGroupIndex = 0; propertyGroupIndex < propertyGroupNodes.count(); propertyGroupIndex++) {
|
|
||||||
auto propertyGroupElement = propertyGroupNodes.item(propertyGroupIndex).toElement();
|
|
||||||
auto propertyGroupName = propertyGroupElement.attributes().namedItem(
|
|
||||||
"name"
|
|
||||||
).nodeValue().toLower().toStdString();
|
|
||||||
PropertyGroup propertyGroup;
|
|
||||||
propertyGroup.name = propertyGroupName;
|
|
||||||
|
|
||||||
auto propertyNodes = propertyGroupElement.elementsByTagName("property");
|
|
||||||
for (int propertyIndex = 0; propertyIndex < propertyNodes.count(); propertyIndex++) {
|
|
||||||
auto propertyElement = propertyNodes.item(propertyIndex).toElement();
|
|
||||||
auto propertyName = propertyElement.attributes().namedItem("name").nodeValue();
|
|
||||||
|
|
||||||
Property property;
|
|
||||||
property.name = propertyName.toStdString();
|
|
||||||
property.value = propertyElement.attributes().namedItem("value").nodeValue();
|
|
||||||
|
|
||||||
propertyGroup.propertiesMappedByName.insert(
|
|
||||||
std::pair(propertyName.toLower().toStdString(), property)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->propertyGroupsMappedByName.insert(std::pair(propertyGroup.name, propertyGroup));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TargetDescriptionFile::loadModules(const QDomDocument& document) {
|
void TargetDescriptionFile::loadModules(const QDomDocument& document) {
|
||||||
const auto deviceElement = document.elementsByTagName("device").item(0).toElement();
|
const auto deviceElement = document.elementsByTagName("device").item(0).toElement();
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,12 @@
|
|||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QDomDocument>
|
#include <QDomDocument>
|
||||||
|
#include <QDomElement>
|
||||||
|
#include <string>
|
||||||
|
#include <optional>
|
||||||
|
#include <functional>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "AddressSpace.hpp"
|
#include "AddressSpace.hpp"
|
||||||
#include "MemorySegment.hpp"
|
#include "MemorySegment.hpp"
|
||||||
@@ -82,10 +88,14 @@ namespace Targets::TargetDescription
|
|||||||
*/
|
*/
|
||||||
[[nodiscard]] TargetFamily getFamily() const;
|
[[nodiscard]] TargetFamily getFamily() const;
|
||||||
|
|
||||||
|
[[nodiscard]] std::optional<std::reference_wrapper<const PropertyGroup>> tryGetPropertyGroup(
|
||||||
|
std::string_view keyStr
|
||||||
|
) const;
|
||||||
|
[[nodiscard]] const PropertyGroup& getPropertyGroup(std::string_view keyStr) const;
|
||||||
protected:
|
protected:
|
||||||
std::map<std::string, std::string> deviceAttributesByName;
|
std::map<std::string, std::string> deviceAttributesByName;
|
||||||
std::map<std::string, AddressSpace> addressSpacesMappedById;
|
std::map<std::string, AddressSpace> addressSpacesMappedById;
|
||||||
std::map<std::string, PropertyGroup> propertyGroupsMappedByName;
|
std::map<std::string, PropertyGroup, std::less<void>> propertyGroupsMappedByKey;
|
||||||
std::map<std::string, Module> modulesMappedByName;
|
std::map<std::string, Module> modulesMappedByName;
|
||||||
std::map<std::string, Module> peripheralModulesMappedByName;
|
std::map<std::string, Module> peripheralModulesMappedByName;
|
||||||
std::map<std::string, std::vector<RegisterGroup>> peripheralRegisterGroupsMappedByModuleRegisterGroupName;
|
std::map<std::string, std::vector<RegisterGroup>> peripheralRegisterGroupsMappedByModuleRegisterGroupName;
|
||||||
@@ -105,6 +115,12 @@ namespace Targets::TargetDescription
|
|||||||
void init(const std::string& xmlFilePath);
|
void init(const std::string& xmlFilePath);
|
||||||
void init(const QDomDocument& document);
|
void init(const QDomDocument& document);
|
||||||
|
|
||||||
|
static std::optional<std::string> tryGetAttribute(const QDomElement& element, const QString& attributeName);
|
||||||
|
static std::string getAttribute(const QDomElement& element, const QString& attributeName);
|
||||||
|
|
||||||
|
static PropertyGroup propertyGroupFromXml(const QDomElement& xmlElement);
|
||||||
|
static Property propertyFromXml(const QDomElement& xmlElement);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an AddressSpace object from an XML element.
|
* Constructs an AddressSpace object from an XML element.
|
||||||
*
|
*
|
||||||
@@ -158,11 +174,6 @@ namespace Targets::TargetDescription
|
|||||||
*/
|
*/
|
||||||
void loadAddressSpaces(const QDomDocument& document);
|
void loadAddressSpaces(const QDomDocument& document);
|
||||||
|
|
||||||
/**
|
|
||||||
* Extracts all property groups and loads them into this->propertyGroupsMappedByName.
|
|
||||||
*/
|
|
||||||
void loadPropertyGroups(const QDomDocument& document);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts all modules and loads them into this->modulesMappedByName.
|
* Extracts all modules and loads them into this->modulesMappedByName.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user