|
- #include "dbcc/helper/gen_helper.h"
-
- #include <sstream>
- #include <iostream>
- #include <fstream>
- #include <stdexcept>
-
- #include "dbcc/dbc_iterator.h"
-
- #include "dbcc/message.h" /**< ad::dbcc::Message */
- #include "dbcc/helper/signal_helper.h"
-
- #include "rapidjson/document.h" /**< rapidjson::Document */
- #include "rapidjson/istreamwrapper.h" /**< rapidjson::IStreamWrapper */
-
- namespace ad {
- namespace dbcc {
- namespace helper {
-
- const std::string kDefaultIndentSpaces = " ";
- const std::string kCPackAndUnpackMacros = std::string(
- "#define PACK_LEFT_SHIFT(value,shift,mask) (uint8_t)((uint8_t)(value << "
- "shift) & mask)\n"
- "#define UNPACK_LEFT_SHIFT(_type,value,shift,mask) (_type)((_type)(value & "
- "mask) << shift)\n"
- "\n"
- "#define PACK_RIGHT_SHIFT(value,shift,mask) (uint8_t)((uint8_t)(value >> "
- "shift) & mask)\n"
- "#define UNPACK_RIGHT_SHIFT(_type,value,shift,mask) (_type)((_type)(value "
- "& mask) >> shift)\n");
-
- inline const std::string GenerateIndent(int indent_level)
- {
- std::stringstream ss;
-
- for (int i = 0; i < indent_level; i++) {
- ss << kDefaultIndentSpaces;
- }
-
- return ss.str();
- }
-
- class GenHelper::Generator
- {
- public:
- Generator(const std::string &dbc, const std::string &dbc_json) : iter_(dbc)
- {
- const std::vector<std::string> kRequiredKeys{"control", "feedback"};
- std::ifstream ifs(dbc_json.c_str());
-
- if (!ifs.good())
- {
- // Maybe the fail is not readable, not existent etc.
- throw std::runtime_error("Failed to load the configuration file: " + dbc_json);
- }
-
- rapidjson::IStreamWrapper isw(ifs);
- config_.ParseStream(isw);
-
- // Check the required keys
- for (auto &s : kRequiredKeys)
- {
- if (!config_.HasMember(s.c_str()))
- {
- throw std::runtime_error("Required key <" + s + "> is not existent!");
- }
- }
- }
-
- ~Generator() = default;
-
- inline std::string GenAll()
- {
- ad::dbcc::helper::NameSignalVector sigs;
- std::stringstream ss;
-
- // Headers
- ss << "#include <stdint.h> /**< uint8_t uint16_t */\n"
- << "#include <stddef.h> /**< size_t */\n" << std::endl;
-
- ss << kCPackAndUnpackMacros << std::endl;
-
- for (auto &msg : config_["feedback"].GetObject())
- {
- sigs.clear();
-
- ad::dbcc::Message msgp = FindMessageByName(msg.name.GetString());
-
- for (auto &m : msg.value.GetObject())
- {
- size_t idx = msgp[m.name.GetString()];
- if (idx != ad::dbcc::kInvalidIndex)
- {
- sigs.push_back(std::make_pair(m.name.GetString(), msgp[idx]));
- } else {
- throw std::runtime_error("The signal " + std::string(m.name.GetString()) + " is NOT existent!");
- }
- }
-
- ss << GenHelper::GenMessageDef(msgp, sigs, 0) << std::endl;
- ss << GenHelper::GenMessageUnpackDecl(msgp, 0) << std::endl;
- ss << GenHelper::GenMessageUnpackDef(msgp, sigs, 0) << std::endl;
- }
-
- for (auto &msg : config_["control"].GetObject())
- {
- sigs.clear();
-
- ad::dbcc::Message msgp = FindMessageByName(msg.name.GetString());
-
- for (auto &m : msg.value.GetObject())
- {
- size_t idx = msgp[m.name.GetString()];
- if (idx != ad::dbcc::kInvalidIndex)
- {
- sigs.push_back(std::make_pair(m.name.GetString(), msgp[idx]));
- } else {
- throw std::runtime_error("The signal " + std::string(m.name.GetString()) + " is NOT existent!");
- }
- }
-
- ss << GenHelper::GenMessageDef(msgp, sigs, 0) << std::endl;
- ss << GenHelper::GenMessagePackDecl(msgp, 0) << std::endl;
- ss << GenHelper::GenMessagePackDef(msgp, sigs, 0) << std::endl;
- }
-
- return ss.str();
- }
-
- inline ad::dbcc::Message &FindMessageByName(const std::string &msg)
- {
- for (auto &m : iter_)
- {
- if (m.Name() == msg)
- {
- return m;
- }
- }
-
- throw std::runtime_error("Message is NOT existent: " + msg);
- }
-
- inline ad::dbcc::helper::NameSignalVector GenSignalsFromMessage(const std::string &msg)
- {
- ad::dbcc::helper::NameSignalVector sigs;
-
- if (config_["feedback"].HasMember(msg.c_str()))
- {
- if (config_["feedback"][msg.c_str()].IsObject())
- {
- ad::dbcc::Message msgp = FindMessageByName(msg);
-
- for (auto &m : config_["feedback"][msg.c_str()].GetObject())
- {
- size_t idx = msgp[m.name.GetString()];
- if (idx != ad::dbcc::kInvalidIndex)
- {
- sigs.push_back(std::make_pair(m.name.GetString(), msgp[idx]));
- } else {
- throw std::runtime_error("The signal " + std::string(m.name.GetString()) + " is NOT existent!");
- }
- }
- } else {
- throw std::runtime_error("The value of a message can ONLY be an object");
- }
- }
- else if (config_["control"].HasMember(msg.c_str()))
- {
- if (config_["control"][msg.c_str()].IsObject())
- {
- ad::dbcc::Message msgp = FindMessageByName(msg);
-
- for (auto &m : config_["control"][msg.c_str()].GetObject())
- {
- size_t idx = msgp[m.name.GetString()];
- if (idx != ad::dbcc::kInvalidIndex)
- {
- sigs.push_back(std::make_pair(m.name.GetString(), msgp[idx]));
- } else {
- throw std::runtime_error("The signal " + std::string(m.name.GetString()) + " is NOT existent!");
- }
- }
- } else {
- throw std::runtime_error("The value of a message can ONLY be an object");
- }
- }
- else
- {
- throw std::runtime_error("The message is not existent: " + msg);
- }
-
- return sigs;
- }
-
- inline std::string GenMessageDef(const std::string &msg, int indent_level)
- {
- ad::dbcc::helper::NameSignalVector sigs = GenSignalsFromMessage(msg);
- ad::dbcc::Message msgp = FindMessageByName(msg);
-
- return GenHelper::GenMessageDef(msgp, sigs, indent_level);
- }
-
- inline std::string GenMessageUnpackDecl(const std::string &msg, int indent_level)
- {
- ad::dbcc::Message msgp = FindMessageByName(msg);
-
- return GenHelper::GenMessageUnpackDecl(msgp, indent_level);
- }
-
- inline std::string GenMessageUnpackDef(const std::string &msg, int indent_level)
- {
- ad::dbcc::helper::NameSignalVector sigs = GenSignalsFromMessage(msg);
- ad::dbcc::Message msgp = FindMessageByName(msg);
-
- return GenHelper::GenMessageUnpackDef(msgp, sigs, indent_level);
- }
-
- inline std::string GenMessagePackDecl(const std::string &msg, int indent_level)
- {
- ad::dbcc::Message msgp = FindMessageByName(msg);
-
- return GenHelper::GenMessagePackDecl(msgp, indent_level);
- }
-
- inline std::string GenMessagePackDef(const std::string &msg, int indent_level)
- {
- ad::dbcc::helper::NameSignalVector sigs = GenSignalsFromMessage(msg);
- ad::dbcc::Message msgp = FindMessageByName(msg);
-
- return GenHelper::GenMessagePackDef(msgp, sigs, indent_level);
- }
-
- private:
- ad::dbcc::DbcIterator iter_;
- rapidjson::Document config_;
- };
-
- GenHelper::GenHelper(const std::string &dbc, const std::string &dbc_json)
- {
- impl_ = std::unique_ptr<GenHelper::Generator>(new GenHelper::Generator(dbc, dbc_json));
- }
-
- GenHelper::~GenHelper() {}
-
- std::string GenHelper::GenAll()
- {
- return impl_->GenAll();
- }
-
- std::string GenHelper::GenMessageDef(const std::string &msg, int indent_level)
- {
- return impl_->GenMessageDef(msg, indent_level);
- }
-
- std::string GenHelper::GenMessageUnpackDecl(const std::string &msg, int indent_level)
- {
- return impl_->GenMessageUnpackDecl(msg, indent_level);
- }
-
- std::string GenHelper::GenMessageUnpackDef(const std::string &msg, int indent_level)
- {
- return impl_->GenMessageUnpackDef(msg, indent_level);
- }
-
- std::string GenHelper::GenMessagePackDecl(const std::string &msg, int indent_level)
- {
- return impl_->GenMessagePackDecl(msg, indent_level);
- }
-
- std::string GenHelper::GenMessagePackDef(const std::string &msg, int indent_level)
- {
- return impl_->GenMessagePackDef(msg, indent_level);
- }
-
- std::string GenHelper::GenMacros(int indent_level)
- {
- std::stringstream ss;
- const std::string indent = GenerateIndent(indent_level);
-
- ss << indent << "#define PACK_LEFT_SHIFT(value,shift,mask) (uint8_t)((uint8_t)(value << shift) & mask)\n";
- ss << indent << "#define UNPACK_LEFT_SHIFT(_type,value,shift,mask) (_type)((_type)(value & mask) << shift)\n\n";
-
- ss << indent << "#define PACK_RIGHT_SHIFT(value,shift,mask) (uint8_t)((uint8_t)(value >> shift) & mask)\n";
- ss << indent << "#define UNPACK_RIGHT_SHIFT(_type,value,shift,mask) (_type)((_type)(value & mask) >> shift)\n";
-
- return ss.str();
- }
-
- /*
- struct <msg.Name()>_<msg.Id()>
- {
- <type1> <sig1.Name()>;
- <type2> <sig2.Name()>;
- <type3> <sig3.Name()>;
- ...
- };
- */
- std::string GenHelper::GenMessageDef(const ad::dbcc::Message &msg, const ad::dbcc::helper::NameSignalVector &sigs,
- int indent_level)
- {
- std::stringstream ss;
- const std::string indent = GenerateIndent(indent_level);
- const std::string indent2 = GenerateIndent(indent_level + 1);
- ss << indent << "/* " << msg.Name() << "(0x" << std::hex << msg.Id() << std::dec << "), len: " << msg.Dlc() << " bytes */"
- << std::endl;
- ss << indent << "typedef struct {" << std::endl;
- for (const auto &sig : sigs) {
- ad::dbcc::helper::SignalHelper sig_helper(sig.second);
-
- std::string signal_member_name = sig.first.empty() ? sig.second.Name() : sig.first;
-
- ss << indent2 << sig_helper.TypeName() << " "
- << signal_member_name << ";" << std::endl;
- }
- ss << indent << "} " << msg.Name() << "_0x" << std::hex << msg.Id() << std::dec << ";" << std::endl;
-
- return ss.str();
- }
-
- std::string GenHelper::GenMessageUnpackDecl(const ad::dbcc::Message &msg, int indent_level)
- {
- std::stringstream ss;
- const std::string indent = GenerateIndent(indent_level);
- ss << indent << "/* Unpack message " << msg.Name() << "(0x" << std::hex << msg.Id() << std::dec << ") from a CAN data frame */"
- << std::endl;
- ss << indent << "void Unpack_" << msg.Name() << "_0x" << std::hex << msg.Id() << std::dec
- << "(" << msg.Name() << "_0x" << std::hex << msg.Id() << std::dec << " *msg, const uint8_t *data, size_t len);" << std::endl;
-
- return ss.str();
- }
-
- std::string GenHelper::GenMessageUnpackDef(const ad::dbcc::Message &msg, const ad::dbcc::helper::NameSignalVector &sigs,
- int indent_level)
- {
- std::stringstream ss;
- ss << msg.Name() << "_0x" << std::hex << msg.Id() << std::dec;
- const std::string msg_name = ss.str();
-
- const std::string indent = GenerateIndent(indent_level);
- const std::string indent2 = GenerateIndent(indent_level + 1);
-
- ss.str("");
- ss.clear();
-
- ss << indent << "/* Unpack message " << msg.Name() << "(0x" << std::hex << msg.Id() << std::dec << ") from a CAN data frame */"
- << std::endl;
- ss << indent << "void Unpack_" << msg_name
- << "(" << msg_name << " *msg, const uint8_t *data, size_t len)" << std::endl;
- ss << indent << "{" << std::endl;
-
- bool need_new_line = false;
-
- for (const auto &sig : sigs)
- {
- if (need_new_line)
- {
- ss << std::endl;
- }
-
- ad::dbcc::helper::SignalHelper sig_helper(sig.second);
- std::string signal_member_name = sig.first.empty() ? sig.second.Name() : sig.first;
-
- ss << indent2 << "/* " << sig.second.Name() << ": "
- << sig.second.StartBit() << ", " << sig.second.Length() << " */"
- << std::endl;
- ss << sig_helper.Unpack2Code(signal_member_name, "msg->", indent_level + 1) << std::endl;
- need_new_line = true;
- }
-
- ss << indent << "}" << std::endl;
-
- return ss.str();
- }
-
- std::string GenHelper::GenMessagePackDecl(const ad::dbcc::Message &msg, int indent_level)
- {
- std::stringstream ss;
- const std::string indent = GenerateIndent(indent_level);
- ss << indent << "/* Pack message " << msg.Name() << "(0x" << std::hex << msg.Id() << std::dec << ") as a CAN data frame */"
- << std::endl;
- ss << indent << "void Pack_" << msg.Name() << "_0x" << std::hex << msg.Id() << std::dec
- << "(const " << msg.Name() << "_0x" << std::hex << msg.Id() << std::dec << " *msg, uint8_t *data, size_t len);" << std::endl;
-
- return ss.str();
- }
-
- std::string GenHelper::GenMessagePackDef(const ad::dbcc::Message &msg, const ad::dbcc::helper::NameSignalVector &sigs,
- int indent_level)
- {
- std::stringstream ss;
- ss << msg.Name() << "_0x" << std::hex << msg.Id() << std::dec;
- const std::string msg_name = ss.str();
-
- const std::string indent = GenerateIndent(indent_level);
- const std::string indent2 = GenerateIndent(indent_level + 1);
-
- ss.str("");
- ss.clear();
-
- ss << indent << "/* Pack message " << msg.Name() << "(0x" << std::hex << msg.Id() << std::dec << ") as a CAN data frame */"
- << std::endl;
- ss << indent << "void Pack_" << msg_name
- << "(const " << msg_name << " *msg, uint8_t *data, size_t len)" << std::endl;
- ss << indent << "{" << std::endl;
-
- bool need_new_line = false;
-
- for (const auto &sig : sigs)
- {
- if (need_new_line)
- {
- ss << std::endl;
- }
-
- ad::dbcc::helper::SignalHelper sig_helper(sig.second);
- std::string signal_member_name = sig.first.empty() ? sig.second.Name() : sig.first;
-
- ss << indent2 << "/* " << sig.second.Name() << ": "
- << sig.second.StartBit() << ", " << sig.second.Length() << " */"
- << std::endl;
- ss << sig_helper.Pack2Code(signal_member_name, "msg->", indent_level + 1) << std::endl;
- need_new_line = true;
- }
-
- ss << indent << "}" << std::endl;
-
- return ss.str();
- }
-
- } // namespace helper
- } // namespace dbcc
- } // namespace ad
|