Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/master/load_esi/load_esi.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "kickcat/CoE/EsiParser.h"
#include "kickcat/ESI/Parser.h"
#include "kickcat/OS/Time.h"
#include <argparse/argparse.hpp>

Expand All @@ -25,7 +25,7 @@ int main(int argc, char const* argv[])
return 1;
}

CoE::EsiParser parser;
ESI::Parser parser;

nanoseconds t1 = since_epoch();
CoE::Dictionary coe_dict = parser.loadFile(esi_file);
Expand Down
2 changes: 1 addition & 1 deletion lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ endif()

if (ENABLE_ESI_PARSER)
find_package(tinyxml2 CONFIG REQUIRED)
list(APPEND KICKCAT_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/CoE/EsiParser.cc)
list(APPEND KICKCAT_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/ESI/Parser.cc)
list(APPEND OS_LIBRARIES tinyxml2::tinyxml2)
endif()

Expand Down
66 changes: 2 additions & 64 deletions lib/include/kickcat/CoE/EsiParser.h
Original file line number Diff line number Diff line change
@@ -1,73 +1,11 @@
#ifndef KICKCAT_COE_ESI_PARSER_H
#define KICKCAT_COE_ESI_PARSER_H

#include <tinyxml2.h>
#include <unordered_map>

#include "kickcat/CoE/OD.h"
#include "kickcat/ESI/Parser.h"

namespace kickcat::CoE
{
class EsiParser
{
public:
EsiParser() = default;
~EsiParser() = default;

CoE::Dictionary loadFile (std::string const& file);
CoE::Dictionary loadString(std::string const& xml);

char const* vendor() const { return vendor_->FirstChildElement("Name")->GetText(); }
char const* profile() const { return profile_->FirstChildElement("ProfileNo")->GetText(); }

private:
template<typename T>
T toNumber(tinyxml2::XMLElement* node)
{
std::string field = node->GetText();
if (field.rfind("#x", 0) == 0)
{
field[0] = '0';
}
return std::stoi(field, nullptr, 0);
}

CoE::Dictionary parse(); // main method
std::vector<uint8_t> loadHexBinary(tinyxml2::XMLElement* node);
std::vector<uint8_t> loadString(tinyxml2::XMLElement* node);

void loadDefaultData(tinyxml2::XMLNode* node, Object& obj, Entry& entry);

uint16_t loadAccess(tinyxml2::XMLNode* node);

std::tuple<DataType, uint16_t, uint16_t> parseType(tinyxml2::XMLNode* node);

DataType resolveType(std::string const& type_name);

tinyxml2::XMLNode* findNodeType(tinyxml2::XMLNode* node);

Object create(tinyxml2::XMLNode* node);


// Manage XML entry point
tinyxml2::XMLDocument doc_;
tinyxml2::XMLElement* root_;

// second level
tinyxml2::XMLElement* vendor_;
tinyxml2::XMLElement* desc_;

// jump on profile and associated dictionnary
tinyxml2::XMLElement* profile_;
tinyxml2::XMLElement* devices_;
tinyxml2::XMLElement* device_;
tinyxml2::XMLElement* dictionary_;
tinyxml2::XMLElement* dtypes_;
tinyxml2::XMLElement* objects_;

static const std::unordered_map<std::string, DataType> BASIC_TYPES;
static const std::unordered_map<std::string, uint8_t> SM_CONF;
};
using EsiParser = ::kickcat::ESI::Parser;
}

#endif
48 changes: 48 additions & 0 deletions lib/include/kickcat/ESI/Device.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#ifndef KICKCAT_ESI_DEVICE_H
#define KICKCAT_ESI_DEVICE_H

#include <cstdint>
#include <cstddef>
#include <optional>
#include <string>
#include <vector>

#include "kickcat/CoE/OD.h"

namespace kickcat::ESI
{
struct DeviceSummary
{
std::string type;
uint32_t product_code = 0;
uint32_t revision_no = 0;
uint32_t serial_no = 0;
std::string name;
};

struct DeviceFilter
{
std::optional<std::string> type;
std::optional<uint32_t> product_code;
std::optional<uint32_t> revision_no;
std::size_t index = 0;
};

struct Device
{
std::string type;
uint32_t product_code = 0;
uint32_t revision_no = 0;
uint32_t serial_no = 0;
std::string name;
std::string group_type;
uint16_t profile_no = 0;

std::string vendor_name;
uint32_t vendor_id = 0;

CoE::Dictionary dictionary;
};
}

#endif
77 changes: 77 additions & 0 deletions lib/include/kickcat/ESI/Parser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#ifndef KICKCAT_ESI_PARSER_H
#define KICKCAT_ESI_PARSER_H

#include <tinyxml2.h>
#include <string>
#include <tuple>
#include <unordered_map>
#include <vector>

#include "kickcat/CoE/OD.h"
#include "kickcat/ESI/Device.h"

namespace kickcat::ESI
{
class Parser
{
public:
Parser() = default;
~Parser() = default;

CoE::Dictionary loadFile (std::string const& file);
CoE::Dictionary loadString(std::string const& xml);

char const* vendor() const { return vendor_name_.c_str(); }
char const* profile() const { return profile_no_.c_str(); }

std::vector<DeviceSummary> listDevices (std::string const& file);
std::vector<DeviceSummary> listDevicesString(std::string const& xml);

Device loadDevice (std::string const& file, DeviceFilter const& filter = {});
Device loadDeviceString(std::string const& xml, DeviceFilter const& filter = {});

private:
static std::optional<uint32_t> readHexDecAttr(tinyxml2::XMLElement* node, char const* name);

void openFile (std::string const& file);
void openString(std::string const& xml);
void resolveTopLevel();

std::vector<DeviceSummary> listDevicesImpl();
Device loadDeviceImpl(DeviceFilter const& filter);

tinyxml2::XMLElement* selectDevice(DeviceFilter const& filter);
DeviceSummary summarize (tinyxml2::XMLElement* device);

CoE::Dictionary buildDictionary(tinyxml2::XMLElement* device, tinyxml2::XMLElement* profile);

std::vector<uint8_t> loadHexBinary(tinyxml2::XMLElement* node);
std::vector<uint8_t> loadStringData(tinyxml2::XMLElement* node);

void loadDefaultData(tinyxml2::XMLNode* node, CoE::Object& obj, CoE::Entry& entry);
uint16_t loadAccess(tinyxml2::XMLNode* node);

static constexpr int MAX_TYPE_DEPTH = 16;

std::tuple<CoE::DataType, uint16_t, uint16_t> parseType(tinyxml2::XMLNode* node);
CoE::DataType resolveType (std::string const& type_name, int depth = 0);
tinyxml2::XMLNode* findNodeType(tinyxml2::XMLNode* node, std::string const& where);

CoE::Object createObject(tinyxml2::XMLNode* node);

tinyxml2::XMLDocument doc_;
tinyxml2::XMLElement* root_ = nullptr;
tinyxml2::XMLElement* vendor_xml_ = nullptr;
tinyxml2::XMLElement* devices_ = nullptr;

tinyxml2::XMLElement* dtypes_ = nullptr;

std::string vendor_name_;
std::string profile_no_;

static const std::unordered_map<std::string, CoE::DataType> BASIC_TYPES;
static const std::unordered_map<std::string, uint8_t> SM_CONF;
};
}

#endif
Loading
Loading