#include "dbcc/dbc_iterator.h" #include #include namespace ad { namespace dbcc { constexpr const char* kPreambleNode = "BU_"; constexpr const char* kPreambleValueTable = "VAL_TABLE_"; constexpr const char* kPreambleMessage = "BO_"; constexpr const char* kPreambleSignal = "SG_"; constexpr const char* kPreambleComment = "CM_"; constexpr const char* kPreambleAttribute = "BA_"; constexpr const char* kPreambleAttributeDefinition = "BA_DEF_"; constexpr const char* kPreambleEnvironmentVariable = "EV_"; DbcIterator::DbcIterator(const std::string& filePath) { std::ifstream file(filePath); if (file) { Parse(file); } file.close(); } DbcIterator::DbcIterator(std::istream& stream) { Parse(stream); } std::ostream& operator<<(std::ostream& out, DbcIterator& dbc) { for (auto& msg : dbc) { out << msg.Name() << " " << msg.Id() << std::endl; for (auto& sig : msg) { out << "Signal: " << sig.Name() << " [" << (sig.IsFloat() ? "float" : "int") << "] "; out << "To: "; for (auto to : sig.To()) { out << to << ", "; } out << sig.StartBit() << "," << sig.Length() << std::endl; out << "(" << sig.Factor() << ", " << sig.Offset() << ")" << std::endl; out << "[" << sig.Minimum() << ", " << sig.Maximum() << "]" << std::endl; if (sig.GetMultiplexor() == Multiplexor::kMultiplexed) { out << "#" << sig.MultiplexedNumber() << "#" << std::endl; } else if (sig.GetMultiplexor() == Multiplexor::kMultiplexor) { out << "+Multiplexor+" << std::endl; } out << std::endl; } } return out; } inline std::string ExtractQuotedContent(std::istream& is) { std::string content; char ch; bool in_quotes = false; while (is.good()) { is >> std::noskipws >> ch; if (ch == '"') { if (in_quotes) { break; } else { in_quotes = true; continue; } } if (in_quotes) { content.push_back(ch); } } return content; } void DbcIterator::Parse(std::istream& stream) { /** * Here I will guarantee each parser will always process to the EOL. * So the preamble will always be the first word also. */ std::string preamble; messages_.clear(); do { stream >> preamble; if (preamble == kPreambleMessage) { Message msg; stream >> msg; if (stream.fail()) { stream.clear(); stream.ignore(std::numeric_limits::max(), '\n'); } if (msg.SignalCount() > 0) { messages_.emplace_back(msg); message_index_[msg.Id()] = static_cast(messages_.size() - 1); } } else if (preamble == kPreambleComment) { // TODO(anjingyu): Parse the comment // std::cout << "[W] CM_ is unsupported now, ignore!" << std::endl; stream.ignore(std::numeric_limits::max(), '\n'); } else if (preamble == kPreambleValueTable) { // std::cout << "[W] VAL_TABLE_ is unsupported now, ignore!" << std::endl; stream.ignore(std::numeric_limits::max(), '\n'); } else if (preamble == kPreambleAttribute) { // std::cout << "[W] BA_ is unsupported now, ignore!" << std::endl; stream.ignore(std::numeric_limits::max(), '\n'); } else if (preamble == kPreambleAttributeDefinition) { // std::cout << "[W] BA_DEF_ is unsupported now, ignore!" << std::endl; stream.ignore(std::numeric_limits::max(), '\n'); } else if (preamble == kPreambleEnvironmentVariable) { // std::cout << "[W] EV_ is unsupported now, ignore!" << std::endl; stream.ignore(std::numeric_limits::max(), '\n'); } else if (preamble == kPreambleNode) { // std::cout << "[W] BU_ is unsupported now, ignore!" << std::endl; stream.ignore(std::numeric_limits::max(), '\n'); } else { // std::cout << "[W] " << preamble << " is unsupported now, ignore!" << std::endl; stream.ignore(std::numeric_limits::max(), '\n'); } } while (!stream.eof()); } } // namespace dbcc } // namespace ad