diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..e553c79 --- /dev/null +++ b/.clang-format @@ -0,0 +1,104 @@ +--- +# SPDX-FileCopyrightText: 2019 Christoph Cullmann +# SPDX-FileCopyrightText: 2019 Gernot Gebhard +# +# SPDX-License-Identifier: MIT + +# This file got automatically created by ECM, do not edit +# See https://clang.llvm.org/docs/ClangFormatStyleOptions.html for the config options +# and https://community.kde.org/Policies/Frameworks_Coding_Style#Clang-format_automatic_code_formatting +# for clang-format tips & tricks +--- +Language: JavaScript +DisableFormat: true +--- + +# Style for C++ +Language: Cpp + +# base is WebKit coding style: https://webkit.org/code-style-guidelines/ +# below are only things set that diverge from this style! +BasedOnStyle: WebKit + +# enforce C++11 (e.g. for std::vector> +Standard: Cpp11 + +# 4 spaces indent +TabWidth: 4 +IndentWidth: 4 +UseTab: Always + +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: 1 + +# 2 * 80 wide lines +ColumnLimit: 160 + +# sort includes inside line separated groups +SortIncludes: true + +# break before braces on function, namespace and class definitions. +BreakBeforeBraces: Custom +BraceWrapping: + AfterClass: false + AfterCaseLabel: false + +# CrlInstruction *a; +DerivePointerAlignment: false +PointerAlignment: Left +ReferenceAlignment: Left + +# only clang format 14 +# RemoveBracesLLVM: true + +#QualifierAlignment: Left + +# horizontally aligns arguments after an open bracket. +AlignAfterOpenBracket: Align + +# don't move all parameters to new line +AllowAllParametersOfDeclarationOnNextLine: false + +# no single line functions +AllowShortFunctionsOnASingleLine: None + +# always break before you encounter multi line strings +AlwaysBreakBeforeMultilineStrings: true + +# don't move arguments to own lines if they are not all on the same +BinPackArguments: false + +# don't move parameters to own lines if they are not all on the same +BinPackParameters: false + +# In case we have an if statement with multiple lines the operator should be at the beginning of the line +# but we do not want to break assignments +BreakBeforeBinaryOperators: NonAssignment + +# format C++11 braced lists like function calls +Cpp11BracedListStyle: true + +# do not put a space before C++11 braced lists +SpaceBeforeCpp11BracedList: false + +# remove empty lines +KeepEmptyLinesAtTheStartOfBlocks: false + +# no namespace indentation to keep indent level low +NamespaceIndentation: None + +# we use template< without space. +SpaceAfterTemplateKeyword: false + +# Always break after template declaration +AlwaysBreakTemplateDeclarations: true + +# macros for which the opening brace stays attached. +ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH, forever, Q_FOREVER, QBENCHMARK, QBENCHMARK_ONCE , wl_resource_for_each, wl_resource_for_each_safe ] + +# keep lambda formatting multi-line if not empty +AllowShortLambdasOnASingleLine: Empty + +# We do not want clang-format to put all arguments on a new line +AllowAllArgumentsOnNextLine: false diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1b81835..4a6814a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -2,7 +2,8 @@ name: Libdbc Tests on: push: - branches: [ "master" ] + branches: + - "master" pull_request: env: @@ -10,34 +11,31 @@ env: BUILD_TYPE: Release jobs: - build: + build-and-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: install fast_float dependency - run: | - cd ${{github.workspace}} - git clone https://github.com/fastfloat/fast_float.git - mkdir fast_float/build - cd fast_float/build - cmake -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/installation" .. - make install - - name: Configure CMake - run: | - mkdir build - cd build - cmake -DFastFloat_DIR="${{github.workspace}}/installation/share/cmake/FastFloat" -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} .. + run: cmake -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -Bbuild -H. - - name: Build + - name: Build the library run: | cd build - make + make -j$(nproc) - - name: Test + - name: Run unit tests run: | cd build ctest --output-on-failure + format-check: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Test format with clang format + run: ./scripts/fmt.sh + diff --git a/CMakeLists.txt b/CMakeLists.txt index 0522203..44e6cef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.16) project(dbc VERSION 0.1.1 DESCRIPTION "C++ DBC Parser") +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + # package set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) diff --git a/include/libdbc/dbc.hpp b/include/libdbc/dbc.hpp index 7fd3200..b43d9e4 100644 --- a/include/libdbc/dbc.hpp +++ b/include/libdbc/dbc.hpp @@ -3,56 +3,53 @@ #define __DBC_HPP__ #include -#include -#include #include +#include +#include #include namespace libdbc { - class Parser { - public: - virtual ~Parser() = default; - - virtual void parse_file(const std::string& file) = 0; - - protected: - +class Parser { +public: + virtual ~Parser() = default; - }; + virtual void parse_file(const std::string& file) = 0; - class DbcParser : public Parser { - public: - DbcParser(); +protected: +}; - virtual ~DbcParser() = default; +class DbcParser : public Parser { +public: + DbcParser(); - virtual void parse_file(const std::string& file) final override; + virtual ~DbcParser() = default; - std::string get_version() const; - std::vector get_nodes() const; - std::vector get_messages() const; + virtual void parse_file(const std::string& file) final override; - Message::ParseSignalsStatus parseMessage(const uint32_t id, const std::vector& data, std::vector& out_values); + std::string get_version() const; + std::vector get_nodes() const; + std::vector get_messages() const; - private: - std::string version; - std::vector nodes; - std::vector messages; + Message::ParseSignalsStatus parseMessage(const uint32_t id, const std::vector& data, std::vector& out_values); - const std::regex version_re; - const std::regex bit_timing_re; - const std::regex name_space_re; - const std::regex node_re; - const std::regex message_re; - const std::regex signal_re; +private: + std::string version; + std::vector nodes; + std::vector messages; - void parse_dbc_header(std::istream& file_stream); - void parse_dbc_nodes(std::istream& file_stream); - void parse_dbc_messages(const std::vector& lines); + const std::regex version_re; + const std::regex bit_timing_re; + const std::regex name_space_re; + const std::regex node_re; + const std::regex message_re; + const std::regex signal_re; - }; + void parse_dbc_header(std::istream& file_stream); + void parse_dbc_nodes(std::istream& file_stream); + void parse_dbc_messages(const std::vector& lines); +}; } diff --git a/include/libdbc/exceptions/error.hpp b/include/libdbc/exceptions/error.hpp index 973217c..8fa3954 100644 --- a/include/libdbc/exceptions/error.hpp +++ b/include/libdbc/exceptions/error.hpp @@ -5,19 +5,19 @@ namespace libdbc { - class exception : public std::exception { - public: - const char * what() const throw() { - return "libdbc exception occurred"; - } - }; +class exception : public std::exception { +public: + const char* what() const throw() { + return "libdbc exception occurred"; + } +}; - class validity_error : public exception { - public: - const char * what() const throw() { - return "Invalid DBC file"; - } - }; +class validity_error : public exception { +public: + const char* what() const throw() { + return "Invalid DBC file"; + } +}; } // libdbc diff --git a/include/libdbc/message.hpp b/include/libdbc/message.hpp index 12ab43c..90a1dc1 100644 --- a/include/libdbc/message.hpp +++ b/include/libdbc/message.hpp @@ -1,50 +1,50 @@ #ifndef __MESSAGE_HPP__ #define __MESSAGE_HPP__ -#include -#include #include #include #include +#include +#include namespace libdbc { - struct Message { - Message() = delete; - explicit Message(uint32_t id, const std::string& name, uint8_t size, const std::string& node); - - enum class ParseSignalsStatus { - Success, - ErrorMessageToLong, - ErrorBigEndian, - ErrorUnknownID, - ErrorInvalidConversion, - }; - - /*! - * \brief parseSignals - * \param data - * \param values - * \return - */ - ParseSignalsStatus parseSignals(const std::vector& data, std::vector &values) const; - - void appendSignal(const Signal& signal); - const std::vector signals() const; - uint32_t id() const; - - virtual bool operator==(const Message& rhs) const; - - private: - uint32_t m_id; - std::string m_name; - uint8_t m_size; - std::string m_node; - std::vector m_signals; - - friend std::ostream& operator<<(std::ostream& os, const Message& dt); +struct Message { + Message() = delete; + explicit Message(uint32_t id, const std::string& name, uint8_t size, const std::string& node); + + enum class ParseSignalsStatus { + Success, + ErrorMessageToLong, + ErrorBigEndian, + ErrorUnknownID, + ErrorInvalidConversion, }; - std::ostream& operator<< (std::ostream &out, const Message& msg); + /*! + * \brief parseSignals + * \param data + * \param values + * \return + */ + ParseSignalsStatus parseSignals(const std::vector& data, std::vector& values) const; + + void appendSignal(const Signal& signal); + const std::vector signals() const; + uint32_t id() const; + + virtual bool operator==(const Message& rhs) const; + +private: + uint32_t m_id; + std::string m_name; + uint8_t m_size; + std::string m_node; + std::vector m_signals; + + friend std::ostream& operator<<(std::ostream& os, const Message& dt); +}; + +std::ostream& operator<<(std::ostream& out, const Message& msg); } diff --git a/include/libdbc/signal.hpp b/include/libdbc/signal.hpp index 2252700..30178de 100644 --- a/include/libdbc/signal.hpp +++ b/include/libdbc/signal.hpp @@ -2,33 +2,44 @@ #ifndef __SIGNAL_HPP__ #define __SIGNAL_HPP__ +#include #include #include -#include namespace libdbc { - struct Signal { - std::string name; - bool is_multiplexed; - uint32_t start_bit; - uint32_t size; - bool is_bigendian; - bool is_signed; - double factor; - double offset; - double min; - double max; - std::string unit; - std::vector receivers; - - Signal() = delete; - explicit Signal(std::string name, bool is_multiplexed, uint32_t start_bit, uint32_t size, bool is_bigendian, bool is_signed, double factor, double offset, double min, double max, std::string unit, std::vector recievers); - - virtual bool operator==(const Signal& rhs) const; - bool operator< (const Signal& rhs) const; - }; - - std::ostream& operator<< (std::ostream &out, const Signal& sig); +struct Signal { + std::string name; + bool is_multiplexed; + uint32_t start_bit; + uint32_t size; + bool is_bigendian; + bool is_signed; + double factor; + double offset; + double min; + double max; + std::string unit; + std::vector receivers; + + Signal() = delete; + explicit Signal(std::string name, + bool is_multiplexed, + uint32_t start_bit, + uint32_t size, + bool is_bigendian, + bool is_signed, + double factor, + double offset, + double min, + double max, + std::string unit, + std::vector recievers); + + virtual bool operator==(const Signal& rhs) const; + bool operator<(const Signal& rhs) const; +}; + +std::ostream& operator<<(std::ostream& out, const Signal& sig); } diff --git a/include/libdbc/utils/utils.hpp b/include/libdbc/utils/utils.hpp index aadfd8c..a7dde52 100644 --- a/include/libdbc/utils/utils.hpp +++ b/include/libdbc/utils/utils.hpp @@ -2,52 +2,47 @@ #ifndef __UTILS_HPP__ #define __UTILS_HPP__ -#include +#include #include #include -#include -#include #include +#include +#include namespace utils { - class StreamHandler { - public: - /** - * This is a safe non line ending specific get_ine function. This is to help with files - * carried over from different systems. i.e Unix file comes to Windows with LF endings - * instead of CRLF. - * - * @param stream [description] - * @param line [description] - * @return [description] - */ - static std::istream & get_line( std::istream & stream, std::string & line ); - - - static std::istream & get_next_non_blank_line( std::istream & stream, std::string & line ); - - static std::istream & skip_to_next_blank_line( std::istream & stream, std::string & line ); - - }; - - class String { - public: - - static std::string trim(const std::string& line); - - template - static void split(const std::string& str, Container& cont, char delim = ' ') { - std::stringstream ss(str); - std::string token; - - while (std::getline(ss, token, delim)) { - cont.push_back(token); - } +class StreamHandler { +public: + /** + * This is a safe non line ending specific get_ine function. This is to help with files + * carried over from different systems. i.e Unix file comes to Windows with LF endings + * instead of CRLF. + * + * @param stream [description] + * @param line [description] + * @return [description] + */ + static std::istream& get_line(std::istream& stream, std::string& line); + + static std::istream& get_next_non_blank_line(std::istream& stream, std::string& line); + + static std::istream& skip_to_next_blank_line(std::istream& stream, std::string& line); +}; + +class String { +public: + static std::string trim(const std::string& line); + + template + static void split(const std::string& str, Container& cont, char delim = ' ') { + std::stringstream ss(str); + std::string token; + + while (std::getline(ss, token, delim)) { + cont.push_back(token); } - - - }; + } +}; } diff --git a/scripts/fmt.sh b/scripts/fmt.sh new file mode 100755 index 0000000..8f360f8 --- /dev/null +++ b/scripts/fmt.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# Used to format files to the given format using clang format. +# example runs: +# ./scripts/fmt.sh +# ./scripts/fmt.sh format # This will write changes to file +APPLY_FORMAT=${1:-""} + + +# Variable that will hold the name of the clang-format command +FMT="" + +# Some distros just call it clang-format. Others (e.g. Ubuntu) are insistent +# that the version number be part of the command. We prefer clang-format if +# that's present, otherwise we check clang-format-13 +for clangfmt in clang-format{,-13}; do + if which "$clangfmt" &>/dev/null; then + FMT="$clangfmt" + break + fi +done + +# Check if we found a working clang-format +if [ -z "$FMT" ]; then + echo "failed to find clang-format. Please install clang-format version 13 or above" + exit 1 +fi + +files=$(find . \( -path ./build -prune -o -path ./.git -prune -o -path ./third_party -prune \) -o -type f -name "*[h|c]pp" -print) + +if [[ ${APPLY_FORMAT} = "format" ]]; then + ${FMT} -i ${files} +else + ${FMT} --dry-run --Werror ${files} +fi + diff --git a/src/dbc.cpp b/src/dbc.cpp index d0646c8..c091408 100644 --- a/src/dbc.cpp +++ b/src/dbc.cpp @@ -1,7 +1,7 @@ +#include +#include #include #include -#include -#include #include @@ -29,155 +29,137 @@ const auto whiteSpace = "\\s"; namespace libdbc { - DbcParser::DbcParser() : version(""), nodes(), - version_re("^(VERSION)\\s\"(.*)\""), bit_timing_re("^(BS_:)"), - name_space_re("^(NS_)\\s\\:"), node_re("^(BU_:)\\s((?:[\\w]+?\\s?)*)"), - message_re("^(BO_)\\s(\\d+)\\s(\\w+)\\:\\s(\\d+)\\s(\\w+|Vector__XXX)"), - // NOTE: No multiplex support yet - signal_re(std::string("^") + whiteSpace + - signalIdentifierPattern + - whiteSpace + - namePattern + - whiteSpace + - "\\:" + - whiteSpace + - bitStartPattern + - "\\|" + - lengthPattern + - "\\@" + - byteOrderPattern + - signPattern + - whiteSpace + - offsetScalePattern + - whiteSpace + - minMaxPattern + - whiteSpace + - unitPattern + - whiteSpace + - receiverPattern) { +DbcParser::DbcParser() + : version("") + , nodes() + , version_re("^(VERSION)\\s\"(.*)\"") + , bit_timing_re("^(BS_:)") + , name_space_re("^(NS_)\\s\\:") + , node_re("^(BU_:)\\s((?:[\\w]+?\\s?)*)") + , message_re("^(BO_)\\s(\\d+)\\s(\\w+)\\:\\s(\\d+)\\s(\\w+|Vector__XXX)") + , + // NOTE: No multiplex support yet + signal_re(std::string("^") + whiteSpace + signalIdentifierPattern + whiteSpace + namePattern + whiteSpace + "\\:" + whiteSpace + bitStartPattern + "\\|" + + lengthPattern + "\\@" + byteOrderPattern + signPattern + whiteSpace + offsetScalePattern + whiteSpace + minMaxPattern + whiteSpace + unitPattern + + whiteSpace + receiverPattern) { +} - } +void DbcParser::parse_file(const std::string& file) { + std::ifstream s(file.c_str()); + std::string line; + std::vector lines; - void DbcParser::parse_file(const std::string& file) { - std::ifstream s(file.c_str()); - std::string line; - std::vector lines; + messages.clear(); - messages.clear(); + parse_dbc_header(s); - parse_dbc_header(s); + parse_dbc_nodes(s); - parse_dbc_nodes(s); + while (!s.eof()) { + utils::StreamHandler::get_next_non_blank_line(s, line); + lines.push_back(line); + } - while(!s.eof()) { - utils::StreamHandler::get_next_non_blank_line( s, line ); - lines.push_back(line); - } + parse_dbc_messages(lines); +} - parse_dbc_messages(lines); - } +std::string DbcParser::get_version() const { + return version; +} - std::string DbcParser::get_version() const { - return version; - } +std::vector DbcParser::get_nodes() const { + return nodes; +} - std::vector DbcParser::get_nodes() const { - return nodes; - } +std::vector DbcParser::get_messages() const { + return messages; +} - std::vector DbcParser::get_messages() const { - return messages; +Message::ParseSignalsStatus DbcParser::parseMessage(const uint32_t id, const std::vector& data, std::vector& out_values) { + for (const auto& message : messages) { + if (message.id() == id) + return message.parseSignals(data, out_values); } + return Message::ParseSignalsStatus::ErrorUnknownID; +} - Message::ParseSignalsStatus DbcParser::parseMessage(const uint32_t id, const std::vector& data, std::vector& out_values) { - for (const auto& message: messages) { - if (message.id() == id) - return message.parseSignals(data, out_values); - } - return Message::ParseSignalsStatus::ErrorUnknownID; - } +void DbcParser::parse_dbc_header(std::istream& file_stream) { + std::string line; + std::smatch match; - void DbcParser::parse_dbc_header(std::istream& file_stream) { - std::string line; - std::smatch match; + utils::StreamHandler::get_line(file_stream, line); - utils::StreamHandler::get_line(file_stream, line); + if (!std::regex_search(line, match, version_re)) { + throw validity_error(); + } - if(!std::regex_search(line, match, version_re)) { - throw validity_error(); - } + version = match.str(2); - version = match.str(2); + utils::StreamHandler::get_next_non_blank_line(file_stream, line); - utils::StreamHandler::get_next_non_blank_line( file_stream, line ); + utils::StreamHandler::skip_to_next_blank_line(file_stream, line); - utils::StreamHandler::skip_to_next_blank_line( file_stream, line ); + utils::StreamHandler::get_next_non_blank_line(file_stream, line); - utils::StreamHandler::get_next_non_blank_line( file_stream, line ); + if (!std::regex_search(line, match, bit_timing_re)) + throw validity_error(); +} - if(!std::regex_search(line, match, bit_timing_re)) - throw validity_error(); +void DbcParser::parse_dbc_nodes(std::istream& file_stream) { + std::string line; + std::smatch match; - } + utils::StreamHandler::get_next_non_blank_line(file_stream, line); - void DbcParser::parse_dbc_nodes(std::istream& file_stream) { - std::string line; - std::smatch match; + if (!std::regex_search(line, match, node_re)) + throw validity_error(); - utils::StreamHandler::get_next_non_blank_line( file_stream, line ); + if (match.length() > 2) { + std::string n = match.str(2); + utils::String::split(n, nodes); + } +} - if(!std::regex_search(line, match, node_re)) - throw validity_error(); +void DbcParser::parse_dbc_messages(const std::vector& lines) { + std::smatch match; - if(match.length() > 2) { - std::string n = match.str(2); - utils::String::split(n, nodes); - } + for (const auto& line : lines) { + if (std::regex_search(line, match, message_re)) { + uint32_t id = std::stoul(match.str(2)); + std::string name = match.str(3); + uint8_t size = std::stoul(match.str(4)); + std::string node = match.str(5); - } + Message msg(id, name, size, node); - void DbcParser::parse_dbc_messages(const std::vector& lines) { - std::smatch match; - - for(const auto &line : lines) { - if(std::regex_search(line, match, message_re)) { - uint32_t id = std::stoul(match.str(2)); - std::string name = match.str(3); - uint8_t size = std::stoul(match.str(4)); - std::string node = match.str(5); - - Message msg(id, name, size, node); - - messages.push_back(msg); - } - - if(std::regex_search(line, match, signal_re)) { - std::string name = match.str(2); - bool is_multiplexed = false; // No support yet - uint32_t start_bit = std::stoul(match.str(3)); - uint32_t size = std::stoul(match.str(4)); - bool is_bigendian = (std::stoul(match.str(5)) == 0); - bool is_signed = (match.str(6) == "-"); - // Alternate groups because a group is for the decimal portion - double factor; - fast_float::from_chars(match.str(7).data(), match.str(7).data() + match.str(7).size(), factor); - double offset; - fast_float::from_chars(match.str(9).data(), match.str(9).data() + match.str(9).size(), offset); - double min; - fast_float::from_chars(match.str(11).data(), match.str(11).data() + match.str(11).size(), min); - double max; - fast_float::from_chars(match.str(13).data(), match.str(13).data() + match.str(13).size(), max); - std::string unit = match.str(15); - - std::vector receivers; - utils::String::split(match.str(16), receivers, ','); - - Signal sig(name, is_multiplexed, start_bit, size, is_bigendian, is_signed, factor, offset, min, max, unit, receivers); - messages.back().appendSignal(sig); - } + messages.push_back(msg); } + if (std::regex_search(line, match, signal_re)) { + std::string name = match.str(2); + bool is_multiplexed = false; // No support yet + uint32_t start_bit = std::stoul(match.str(3)); + uint32_t size = std::stoul(match.str(4)); + bool is_bigendian = (std::stoul(match.str(5)) == 0); + bool is_signed = (match.str(6) == "-"); + // Alternate groups because a group is for the decimal portion + double factor; + fast_float::from_chars(match.str(7).data(), match.str(7).data() + match.str(7).size(), factor); + double offset; + fast_float::from_chars(match.str(9).data(), match.str(9).data() + match.str(9).size(), offset); + double min; + fast_float::from_chars(match.str(11).data(), match.str(11).data() + match.str(11).size(), min); + double max; + fast_float::from_chars(match.str(13).data(), match.str(13).data() + match.str(13).size(), max); + std::string unit = match.str(15); + + std::vector receivers; + utils::String::split(match.str(16), receivers, ','); + + Signal sig(name, is_multiplexed, start_bit, size, is_bigendian, is_signed, factor, offset, min, max, unit, receivers); + messages.back().appendSignal(sig); + } } - +} } diff --git a/src/message.cpp b/src/message.cpp index 73abf8e..7a2331b 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -2,72 +2,84 @@ #include namespace libdbc { - Message::Message(uint32_t id, const std::string& name, uint8_t size, const std::string& node) : - m_id(id), m_name(name), m_size(size), m_node(node) {} +Message::Message(uint32_t id, const std::string& name, uint8_t size, const std::string& node) + : m_id(id) + , m_name(name) + , m_size(size) + , m_node(node) { +} - bool Message::operator==(const Message& rhs) const { - return (m_id == rhs.id()) && (m_name == rhs.m_name) && - (m_size == rhs.m_size) && (m_node == rhs.m_node); - } +bool Message::operator==(const Message& rhs) const { + return (m_id == rhs.id()) && (m_name == rhs.m_name) && (m_size == rhs.m_size) && (m_node == rhs.m_node); +} - Message::ParseSignalsStatus Message::parseSignals(const std::vector& data, std::vector& values) const { - int size = data.size(); - if (size > 8) - return ParseSignalsStatus::ErrorMessageToLong; // not supported yet +Message::ParseSignalsStatus Message::parseSignals(const std::vector& data, std::vector& values) const { + int size = data.size(); + if (size > 8) + return ParseSignalsStatus::ErrorMessageToLong; // not supported yet - uint64_t data_little_endian = 0; - uint64_t data_big_endian = 0; - for (int i=0; i < size; i++) { - data_little_endian |= ((uint64_t)data[i]) << i * 8; - data_big_endian = (data_big_endian << 8) | (uint64_t)data[i]; - } + uint64_t data_little_endian = 0; + uint64_t data_big_endian = 0; + for (int i = 0; i < size; i++) { + data_little_endian |= ((uint64_t)data[i]) << i * 8; + data_big_endian = (data_big_endian << 8) | (uint64_t)data[i]; + } - // TODO: does this also work on a big endian machine? + // TODO: does this also work on a big endian machine? - const uint32_t len = size * 8; - uint64_t v = 0; - for (const auto& signal: m_signals) { - if (signal.is_bigendian) { - uint32_t start_bit = 8* (signal.start_bit / 8) + (7 - (signal.start_bit % 8)); // Calculation taken from python CAN - v = data_big_endian << start_bit; - v = v >> (len - signal.size); - } else { - const uint32_t shiftLeft = (len - (signal.size + signal.start_bit)); - v = data_little_endian << shiftLeft; - v = v >> (shiftLeft + signal.start_bit); - } + const uint32_t len = size * 8; + uint64_t v = 0; + for (const auto& signal : m_signals) { + if (signal.is_bigendian) { + uint32_t start_bit = 8 * (signal.start_bit / 8) + (7 - (signal.start_bit % 8)); // Calculation taken from python CAN + v = data_big_endian << start_bit; + v = v >> (len - signal.size); + } else { + const uint32_t shiftLeft = (len - (signal.size + signal.start_bit)); + v = data_little_endian << shiftLeft; + v = v >> (shiftLeft + signal.start_bit); + } - if (signal.is_signed && signal.size > 1) { - switch (signal.size) { - case 8: values.push_back((int8_t)v * signal.factor + signal.offset); break; - case 16: values.push_back((int16_t)v * signal.factor + signal.offset); break; - case 32: values.push_back((int32_t)v * signal.factor + signal.offset); break; - case 64: values.push_back((int64_t)v * signal.factor + signal.offset); break; - default: return ParseSignalsStatus::ErrorInvalidConversion; - } - } else - values.push_back(v * signal.factor + signal.offset); - } - return ParseSignalsStatus::Success; - } + if (signal.is_signed && signal.size > 1) { + switch (signal.size) { + case 8: + values.push_back((int8_t)v * signal.factor + signal.offset); + break; + case 16: + values.push_back((int16_t)v * signal.factor + signal.offset); + break; + case 32: + values.push_back((int32_t)v * signal.factor + signal.offset); + break; + case 64: + values.push_back((int64_t)v * signal.factor + signal.offset); + break; + default: + return ParseSignalsStatus::ErrorInvalidConversion; + } + } else + values.push_back(v * signal.factor + signal.offset); + } + return ParseSignalsStatus::Success; +} - void Message::appendSignal(const Signal& signal) { - m_signals.push_back(signal); - } +void Message::appendSignal(const Signal& signal) { + m_signals.push_back(signal); +} - const std::vector Message::signals() const { - return m_signals; - } +const std::vector Message::signals() const { + return m_signals; +} - uint32_t Message::id() const { - return m_id; - } +uint32_t Message::id() const { + return m_id; +} - std::ostream& operator<< (std::ostream &out, const Message& msg) { - out << "Message: {id: " << msg.id() << ", "; - out << "name: " << msg.m_name << ", "; - out << "size: " << msg.m_size << ", "; - out << "node: " << msg.m_node << "}"; - return out; - } +std::ostream& operator<<(std::ostream& out, const Message& msg) { + out << "Message: {id: " << msg.id() << ", "; + out << "name: " << msg.m_name << ", "; + out << "size: " << msg.m_size << ", "; + out << "node: " << msg.m_node << "}"; + return out; +} } diff --git a/src/signal.cpp b/src/signal.cpp index 0aa79e9..c4b703b 100644 --- a/src/signal.cpp +++ b/src/signal.cpp @@ -1,33 +1,54 @@ #include namespace libdbc { - Signal::Signal(std::string name, bool is_multiplexed, uint32_t start_bit, uint32_t size, bool is_bigendian, bool is_signed, double factor, double offset, double min, double max, std::string unit, std::vector receivers) : - name(name), is_multiplexed(is_multiplexed), start_bit(start_bit), size(size), is_bigendian(is_bigendian), is_signed(is_signed), factor(factor), offset(offset), min(min), max(max), unit(unit), receivers(receivers) {} +Signal::Signal(std::string name, + bool is_multiplexed, + uint32_t start_bit, + uint32_t size, + bool is_bigendian, + bool is_signed, + double factor, + double offset, + double min, + double max, + std::string unit, + std::vector receivers) + : name(name) + , is_multiplexed(is_multiplexed) + , start_bit(start_bit) + , size(size) + , is_bigendian(is_bigendian) + , is_signed(is_signed) + , factor(factor) + , offset(offset) + , min(min) + , max(max) + , unit(unit) + , receivers(receivers) { +} - bool Signal::operator==(const Signal& rhs) const { - return (this->name == rhs.name) && (this->is_multiplexed == rhs.is_multiplexed) && - (this->start_bit == rhs.start_bit) && (this->size == rhs.size) && - (this->is_bigendian == rhs.is_bigendian) && (this->is_signed == rhs.is_signed) && - (this->offset == rhs.offset) && (this->min == rhs.min) && (this->max == rhs.max) && - (this->unit == rhs.unit) && (this->receivers == rhs.receivers); - } +bool Signal::operator==(const Signal& rhs) const { + return (this->name == rhs.name) && (this->is_multiplexed == rhs.is_multiplexed) && (this->start_bit == rhs.start_bit) && (this->size == rhs.size) + && (this->is_bigendian == rhs.is_bigendian) && (this->is_signed == rhs.is_signed) && (this->offset == rhs.offset) && (this->min == rhs.min) + && (this->max == rhs.max) && (this->unit == rhs.unit) && (this->receivers == rhs.receivers); +} - bool Signal::operator< (const Signal& rhs) const { - return start_bit < rhs.start_bit; - } +bool Signal::operator<(const Signal& rhs) const { + return start_bit < rhs.start_bit; +} - std::ostream& operator<< (std::ostream &out, const Signal& sig) { - out << "Signal {name: " << sig.name << ", "; - out << "Multiplexed: " << (sig.is_multiplexed ? "True" : "False") << ", "; - out << "Start bit: " << sig.start_bit << ", "; - out << "Size: " << sig.size << ", "; - out << "Endianness: " << (sig.is_bigendian ? "Big endian" : "Little endian") << ", "; - out << "Value Type: " << (sig.is_signed ? "Signed" : "Unsigned") << ", "; - out << "Min: " << sig.min << ", Max: " << sig.max << ", "; - out << "Unit: (" << sig.unit << "), "; - out << "receivers: "; - for(const auto &r : sig.receivers) - out << r; - return out << "}"; - } +std::ostream& operator<<(std::ostream& out, const Signal& sig) { + out << "Signal {name: " << sig.name << ", "; + out << "Multiplexed: " << (sig.is_multiplexed ? "True" : "False") << ", "; + out << "Start bit: " << sig.start_bit << ", "; + out << "Size: " << sig.size << ", "; + out << "Endianness: " << (sig.is_bigendian ? "Big endian" : "Little endian") << ", "; + out << "Value Type: " << (sig.is_signed ? "Signed" : "Unsigned") << ", "; + out << "Min: " << sig.min << ", Max: " << sig.max << ", "; + out << "Unit: (" << sig.unit << "), "; + out << "receivers: "; + for (const auto& r : sig.receivers) + out << r; + return out << "}"; +} } \ No newline at end of file diff --git a/src/utils.cpp b/src/utils.cpp index 824e041..bd6e4fd 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -4,72 +4,69 @@ namespace utils { - std::istream & StreamHandler::get_line( std::istream & stream, std::string & line ) { - std::string newline; +std::istream& StreamHandler::get_line(std::istream& stream, std::string& line) { + std::string newline; - std::getline( stream, newline ); + std::getline(stream, newline); - // Windows CRLF (\r\n) - if ( newline.size() && newline[newline.size()-1] == '\r' ) { - line = newline.substr( 0, newline.size() - 1 ); + // Windows CRLF (\r\n) + if (newline.size() && newline[newline.size() - 1] == '\r') { + line = newline.substr(0, newline.size() - 1); // MacOS LF (\r) - } else if (newline.size() && newline[newline.size()] == '\r') { - line = newline.replace(newline.size(), 1, "\n"); - } else { - line = newline; - } - - return stream; + } else if (newline.size() && newline[newline.size()] == '\r') { + line = newline.replace(newline.size(), 1, "\n"); + } else { + line = newline; } + return stream; +} - std::istream & StreamHandler::get_next_non_blank_line( std::istream & stream, std::string & line ) { - bool is_blank = true; +std::istream& StreamHandler::get_next_non_blank_line(std::istream& stream, std::string& line) { + bool is_blank = true; - const std::regex whitespace_re("\\s*(.*)"); - std::smatch match; + const std::regex whitespace_re("\\s*(.*)"); + std::smatch match; - while(is_blank) { - utils::StreamHandler::get_line(stream, line); + while (is_blank) { + utils::StreamHandler::get_line(stream, line); - std::regex_search(line, match, whitespace_re); + std::regex_search(line, match, whitespace_re); - if((!line.empty() && !match.empty()) || (stream.eof())){ - if((match.length(1) > 0) || (stream.eof())){ - is_blank = false; - } + if ((!line.empty() && !match.empty()) || (stream.eof())) { + if ((match.length(1) > 0) || (stream.eof())) { + is_blank = false; } } - - return stream; } - std::istream & StreamHandler::skip_to_next_blank_line( std::istream & stream, std::string & line ) { - bool line_is_empty = false; + return stream; +} - const std::regex whitespace_re("\\s*(.*)"); - std::smatch match; +std::istream& StreamHandler::skip_to_next_blank_line(std::istream& stream, std::string& line) { + bool line_is_empty = false; - while(!line_is_empty) { - utils::StreamHandler::get_line(stream, line); + const std::regex whitespace_re("\\s*(.*)"); + std::smatch match; - std::regex_search(line, match, whitespace_re); + while (!line_is_empty) { + utils::StreamHandler::get_line(stream, line); - if((match.length(1) == 0) || (stream.eof())){ - line_is_empty = true; - } - } + std::regex_search(line, match, whitespace_re); - return stream; + if ((match.length(1) == 0) || (stream.eof())) { + line_is_empty = true; + } } + return stream; +} +std::string String::trim(const std::string& line) { + const char* WhiteSpace = " \t\v\r\n"; + std::size_t start = line.find_first_not_of(WhiteSpace); + std::size_t end = line.find_last_not_of(WhiteSpace); + return start == end ? std::string() : line.substr(start, end - start + 1); +} - std::string String::trim(const std::string& line) { - const char* WhiteSpace = " \t\v\r\n"; - std::size_t start = line.find_first_not_of(WhiteSpace); - std::size_t end = line.find_last_not_of(WhiteSpace); - return start == end ? std::string() : line.substr(start, end - start + 1); - } - -} // Namespace Utils +} // Namespace Utils diff --git a/test/common.cpp b/test/common.cpp index 9459242..383ebac 100644 --- a/test/common.cpp +++ b/test/common.cpp @@ -1,16 +1,14 @@ #include "common.hpp" #include "defines.hpp" +bool create_tmp_dbc_with(const char* filename, const char* content) { + auto* file = std::fopen(filename, "w"); + if (!file) { + return false; + } -bool create_tmp_dbc_with(const char* filename, const char* content) -{ - auto* file = std::fopen(filename, "w"); - if (!file) { - return false; - } - - std::fputs(PRIMITIVE_DBC.c_str(), file); - std::fputs(content, file); - std::fclose(file); - return true; + std::fputs(PRIMITIVE_DBC.c_str(), file); + std::fputs(content, file); + std::fclose(file); + return true; } diff --git a/test/defines.hpp b/test/defines.hpp index 0855be5..fcd0206 100644 --- a/test/defines.hpp +++ b/test/defines.hpp @@ -1,17 +1,17 @@ #include // Correctly formated files -static const std::string COMPLEX_DBC_FILE = std::string(TESTDBCFILES_PATH) + "/Complex.dbc"; -static const std::string SIMPLE_DBC_FILE = std::string(TESTDBCFILES_PATH) + "/Simple.dbc"; +static const std::string COMPLEX_DBC_FILE = std::string(TESTDBCFILES_PATH) + "/Complex.dbc"; +static const std::string SIMPLE_DBC_FILE = std::string(TESTDBCFILES_PATH) + "/Simple.dbc"; // Files with Errors -static const std::string MISSING_NEW_SYMBOLS_DBC_FILE = std::string(TESTDBCFILES_PATH) + "/MissingNewSymbols.dbc"; -static const std::string MISSING_VERSION_DBC_FILE = std::string(TESTDBCFILES_PATH) + "/MissingVersion.dbc"; -static const std::string MISSING_BIT_TIMING_DBC_FILE = std::string(TESTDBCFILES_PATH) + "/MissingBitTiming.dbc"; -static const std::string TEXT_FILE = std::string(TESTDBCFILES_PATH) + "/TextFile.txt"; +static const std::string MISSING_NEW_SYMBOLS_DBC_FILE = std::string(TESTDBCFILES_PATH) + "/MissingNewSymbols.dbc"; +static const std::string MISSING_VERSION_DBC_FILE = std::string(TESTDBCFILES_PATH) + "/MissingVersion.dbc"; +static const std::string MISSING_BIT_TIMING_DBC_FILE = std::string(TESTDBCFILES_PATH) + "/MissingBitTiming.dbc"; +static const std::string TEXT_FILE = std::string(TESTDBCFILES_PATH) + "/TextFile.txt"; static const std::string PRIMITIVE_DBC = -R"(VERSION "1.0.0" + R"(VERSION "1.0.0" NS_ : diff --git a/test/test_dbc.cpp b/test/test_dbc.cpp index dd519eb..1c218aa 100644 --- a/test/test_dbc.cpp +++ b/test/test_dbc.cpp @@ -1,10 +1,9 @@ -#include +#include "common.hpp" +#include "defines.hpp" #include +#include #include -#include "defines.hpp" #include -#include "common.hpp" - TEST_CASE("Testing dbc file loading error issues", "[fileio][error]") { auto parser = std::unique_ptr(new libdbc::DbcParser()); @@ -27,8 +26,7 @@ TEST_CASE("Testing dbc file loading error issues", "[fileio][error]") { CHECK_NOTHROW(parser->parse_file(MISSING_NEW_SYMBOLS_DBC_FILE)); } - SECTION("Verify that what() method is accessible for all exceptions", "[error]") - { + SECTION("Verify that what() method is accessible for all exceptions", "[error]") { auto generic_error = libdbc::exception(); REQUIRE(generic_error.what() == "libdbc exception occurred"); @@ -47,7 +45,7 @@ TEST_CASE("Testing dbc file loading", "[fileio]") { std::vector receivers{"DBG"}; libdbc::Signal sig("IO_DEBUG_test_unsigned", false, 0, 8, false, false, 1, 0, 0, 0, "", receivers); - msg.appendSignal(sig); + msg.appendSignal(sig); std::vector msgs = {msg}; @@ -59,99 +57,98 @@ TEST_CASE("Testing dbc file loading", "[fileio]") { REQUIRE(parser->get_messages() == msgs); - REQUIRE(parser->get_messages().front().signals() == msg.signals()); + REQUIRE(parser->get_messages().front().signals() == msg.signals()); } - } TEST_CASE("Testing big endian, little endian") { - const auto* filename = std::tmpnam(NULL); + const auto* filename = std::tmpnam(NULL); - auto* file = std::fopen(filename, "w"); - CHECK(file); + auto* file = std::fopen(filename, "w"); + CHECK(file); - std::fputs(PRIMITIVE_DBC.c_str(), file); - // first big endian - // second little endian - std::fputs(R"(BO_ 234 MSG1: 8 Vector__XXX + std::fputs(PRIMITIVE_DBC.c_str(), file); + // first big endian + // second little endian + std::fputs(R"(BO_ 234 MSG1: 8 Vector__XXX SG_ Sig1 : 55|16@0- (0.1,0) [-3276.8|-3276.7] "C" Vector__XXX - SG_ Sig2 : 39|16@1- (0.1,0) [-3276.8|-3276.7] "C" Vector__XXX)", file); - std::fclose(file); - - auto parser = libdbc::DbcParser(); - parser.parse_file(filename); - - REQUIRE(parser.get_messages().size() == 1); - REQUIRE(parser.get_messages().at(0).signals().size() == 2); - { - const auto signal = parser.get_messages().at(0).signals().at(0); - REQUIRE(signal.is_bigendian == true); - } - { - const auto signal = parser.get_messages().at(0).signals().at(1); - REQUIRE(signal.is_bigendian == false); - } + SG_ Sig2 : 39|16@1- (0.1,0) [-3276.8|-3276.7] "C" Vector__XXX)", + file); + std::fclose(file); + + auto parser = libdbc::DbcParser(); + parser.parse_file(filename); + + REQUIRE(parser.get_messages().size() == 1); + REQUIRE(parser.get_messages().at(0).signals().size() == 2); + { + const auto signal = parser.get_messages().at(0).signals().at(0); + REQUIRE(signal.is_bigendian == true); + } + { + const auto signal = parser.get_messages().at(0).signals().at(1); + REQUIRE(signal.is_bigendian == false); + } } TEST_CASE("Testing negative values") { - const auto* filename = std::tmpnam(NULL); + const auto* filename = std::tmpnam(NULL); - create_tmp_dbc_with(filename, R"(BO_ 234 MSG1: 8 Vector__XXX + create_tmp_dbc_with(filename, R"(BO_ 234 MSG1: 8 Vector__XXX SG_ Sig1 : 55|16@0- (0.1,0) [-3276.8|-3276.7] "C" Vector__XXX SG_ Sig2 : 39|16@0- (0.1,0) [-3276.8|-3276.7] "C" Vector__XXX SG_ Sig3 : 23|16@0- (10,0) [-3276.8|-3276.7] "C" Vector__XXX SG_ Sig4 : 7|16@0- (1,-10) [0|32767] "" Vector__XXX)"); - auto parser = libdbc::DbcParser(); - parser.parse_file(filename); - - REQUIRE(parser.get_messages().size() == 1); - REQUIRE(parser.get_messages().at(0).signals().size() == 4); - - SECTION("Evaluating first message") { - const auto signal = parser.get_messages().at(0).signals().at(0); - REQUIRE(signal.factor == 0.1); - REQUIRE(signal.offset == 0); - REQUIRE(signal.min == -3276.8); - REQUIRE(signal.max == -3276.7); - } - SECTION("Evaluating second message") { - const auto signal = parser.get_messages().at(0).signals().at(1); - REQUIRE(signal.factor == 0.1); - REQUIRE(signal.offset == 0); - REQUIRE(signal.min == -3276.8); - REQUIRE(signal.max == -3276.7); - } - SECTION("Evaluating third message"){ - const auto signal = parser.get_messages().at(0).signals().at(2); - REQUIRE(signal.factor == 10); - REQUIRE(signal.offset == 0); - REQUIRE(signal.min == -3276.8); - REQUIRE(signal.max == -3276.7); - } - SECTION("Evaluating fourth message"){ - const auto signal = parser.get_messages().at(0).signals().at(3); - REQUIRE(signal.factor == 1); - REQUIRE(signal.offset == -10); - REQUIRE(signal.min == 0); - REQUIRE(signal.max == 32767); - } + auto parser = libdbc::DbcParser(); + parser.parse_file(filename); + + REQUIRE(parser.get_messages().size() == 1); + REQUIRE(parser.get_messages().at(0).signals().size() == 4); + + SECTION("Evaluating first message") { + const auto signal = parser.get_messages().at(0).signals().at(0); + REQUIRE(signal.factor == 0.1); + REQUIRE(signal.offset == 0); + REQUIRE(signal.min == -3276.8); + REQUIRE(signal.max == -3276.7); + } + SECTION("Evaluating second message") { + const auto signal = parser.get_messages().at(0).signals().at(1); + REQUIRE(signal.factor == 0.1); + REQUIRE(signal.offset == 0); + REQUIRE(signal.min == -3276.8); + REQUIRE(signal.max == -3276.7); + } + SECTION("Evaluating third message") { + const auto signal = parser.get_messages().at(0).signals().at(2); + REQUIRE(signal.factor == 10); + REQUIRE(signal.offset == 0); + REQUIRE(signal.min == -3276.8); + REQUIRE(signal.max == -3276.7); + } + SECTION("Evaluating fourth message") { + const auto signal = parser.get_messages().at(0).signals().at(3); + REQUIRE(signal.factor == 1); + REQUIRE(signal.offset == -10); + REQUIRE(signal.min == 0); + REQUIRE(signal.max == 32767); + } } TEST_CASE("Special characters in unit") { - const auto* filename = std::tmpnam(NULL); + const auto* filename = std::tmpnam(NULL); - create_tmp_dbc_with(filename, R"(BO_ 234 MSG1: 8 Vector__XXX + create_tmp_dbc_with(filename, R"(BO_ 234 MSG1: 8 Vector__XXX SG_ Speed : 0|8@1+ (1,0) [0|204] "Km/h" DEVICE1,DEVICE2,DEVICE3)"); + auto parser = libdbc::DbcParser(); + parser.parse_file(filename); - auto parser = libdbc::DbcParser(); - parser.parse_file(filename); - - REQUIRE(parser.get_messages().size() == 1); - REQUIRE(parser.get_messages().at(0).signals().size() == 1); - SECTION("Checking that signal with special characters as unit is parsed correctly") { - const auto signal = parser.get_messages().at(0).signals().at(0); - REQUIRE(signal.unit.compare("Km/h") == 0); - } + REQUIRE(parser.get_messages().size() == 1); + REQUIRE(parser.get_messages().at(0).signals().size() == 1); + SECTION("Checking that signal with special characters as unit is parsed correctly") { + const auto signal = parser.get_messages().at(0).signals().at(0); + REQUIRE(signal.unit.compare("Km/h") == 0); + } } diff --git a/test/test_parseMessage.cpp b/test/test_parseMessage.cpp index 5543578..e171484 100644 --- a/test/test_parseMessage.cpp +++ b/test/test_parseMessage.cpp @@ -1,5 +1,5 @@ -#include #include +#include #include #include @@ -9,9 +9,9 @@ // Testing of parsing messages TEST_CASE("Parse Message Unknown ID") { - libdbc::DbcParser parser; + libdbc::DbcParser parser; - const auto dbcContent = R"(BO_ 234 MSG1: 8 Vector__XXX + const auto dbcContent = R"(BO_ 234 MSG1: 8 Vector__XXX SG_ Msg1Sig1 : 0|8@0+ (1,0) [-3276.8|-3276.7] "C" Vector__XXX SG_ MsgSig2 : 8|8@0+ (1,0) [-3276.8|-3276.7] "C" Vector__XXX BO_ 123 MSG2: 8 Vector__XXX @@ -19,21 +19,21 @@ BO_ 123 MSG2: 8 Vector__XXX SG_ Msg2Sig1 : 8|8@0+ (1,0) [-3276.8|-3276.7] "C" Vector__XXX )"; - const auto* filename = std::tmpnam(NULL); - CHECK(create_tmp_dbc_with(filename, dbcContent)); + const auto* filename = std::tmpnam(NULL); + CHECK(create_tmp_dbc_with(filename, dbcContent)); - parser.parse_file(filename); + parser.parse_file(filename); - SECTION("Evaluating unknown message id") { - std::vector out_values; - CHECK(parser.parseMessage(578, std::vector({0xFF, 0xA2}), out_values) == libdbc::Message::ParseSignalsStatus::ErrorUnknownID); - } + SECTION("Evaluating unknown message id") { + std::vector out_values; + CHECK(parser.parseMessage(578, std::vector({0xFF, 0xA2}), out_values) == libdbc::Message::ParseSignalsStatus::ErrorUnknownID); + } } TEST_CASE("Parse Message Big Number not aligned little endian") { - libdbc::DbcParser parser; + libdbc::DbcParser parser; - const auto dbcContent = R"(BO_ 337 STATUS: 8 Vector__XXX + const auto dbcContent = R"(BO_ 337 STATUS: 8 Vector__XXX SG_ Value6 : 27|3@1+ (1,0) [0|7] "" Vector__XXX SG_ Value5 : 16|11@1+ (0.1,-102) [-102|102] "%" Vector__XXX SG_ Value2 : 8|2@1+ (1,0) [0|2] "" Vector__XXX @@ -43,71 +43,71 @@ TEST_CASE("Parse Message Big Number not aligned little endian") { SG_ Value1 : 0|8@1+ (1,0) [0|204] "Km/h" Vector__XXX )"; - const auto* filename = std::tmpnam(NULL); - CHECK(create_tmp_dbc_with(filename, dbcContent)); - - parser.parse_file(filename); - - SECTION("Evaluating first message") { - std::vector out_values; - CHECK(parser.parseMessage(337, std::vector({0, 4, 252, 19, 0, 0, 0, 0}), out_values) == libdbc::Message::ParseSignalsStatus::Success); - std::vector refData{2, 0, 0, 1, 0, 0, 0}; - CHECK(refData.size() == 7); - CHECK(out_values.size() == refData.size()); - for (int i=0; i < refData.size(); i++) { - CHECK(out_values.at(i) == refData.at(i)); - } - } - - SECTION("Evaluating second message") { - std::vector out_values; - CHECK(parser.parseMessage(337, std::vector({47, 4, 60, 29, 0, 0, 0, 0}), out_values) == libdbc::Message::ParseSignalsStatus::Success); - std::vector refData{3, 32, 0, 1, 0, 0, 47}; - CHECK(refData.size() == 7); - CHECK(out_values.size() == refData.size()); - for (int i=0; i < refData.size(); i++) { - CHECK(out_values.at(i) == refData.at(i)); - } - } - - SECTION("Evaluating third message") { - std::vector out_values; - CHECK(parser.parseMessage(337, std::vector({57, 4, 250, 29, 0, 0, 0, 0}), out_values) == libdbc::Message::ParseSignalsStatus::Success); - std::vector refData{3, 51, 0, 1, 0, 0, 57}; - CHECK(refData.size() == 7); - CHECK(out_values.size() == refData.size()); - for (int i=0; i < refData.size(); i++) { - CHECK(out_values.at(i) == refData.at(i)); - } - } + const auto* filename = std::tmpnam(NULL); + CHECK(create_tmp_dbc_with(filename, dbcContent)); + + parser.parse_file(filename); + + SECTION("Evaluating first message") { + std::vector out_values; + CHECK(parser.parseMessage(337, std::vector({0, 4, 252, 19, 0, 0, 0, 0}), out_values) == libdbc::Message::ParseSignalsStatus::Success); + std::vector refData{2, 0, 0, 1, 0, 0, 0}; + CHECK(refData.size() == 7); + CHECK(out_values.size() == refData.size()); + for (int i = 0; i < refData.size(); i++) { + CHECK(out_values.at(i) == refData.at(i)); + } + } + + SECTION("Evaluating second message") { + std::vector out_values; + CHECK(parser.parseMessage(337, std::vector({47, 4, 60, 29, 0, 0, 0, 0}), out_values) == libdbc::Message::ParseSignalsStatus::Success); + std::vector refData{3, 32, 0, 1, 0, 0, 47}; + CHECK(refData.size() == 7); + CHECK(out_values.size() == refData.size()); + for (int i = 0; i < refData.size(); i++) { + CHECK(out_values.at(i) == refData.at(i)); + } + } + + SECTION("Evaluating third message") { + std::vector out_values; + CHECK(parser.parseMessage(337, std::vector({57, 4, 250, 29, 0, 0, 0, 0}), out_values) == libdbc::Message::ParseSignalsStatus::Success); + std::vector refData{3, 51, 0, 1, 0, 0, 57}; + CHECK(refData.size() == 7); + CHECK(out_values.size() == refData.size()); + for (int i = 0; i < refData.size(); i++) { + CHECK(out_values.at(i) == refData.at(i)); + } + } } TEST_CASE("Parse Message little endian") { - const auto* filename = std::tmpnam(NULL); + const auto* filename = std::tmpnam(NULL); - create_tmp_dbc_with(filename, R"(BO_ 541 STATUS: 8 DEVICE1 + create_tmp_dbc_with(filename, R"(BO_ 541 STATUS: 8 DEVICE1 SG_ Temperature : 48|16@1+ (0.01,-40) [-40|125] "C" DEVICE1 SG_ SOH : 0|16@1+ (0.01,0) [0|100] "%" DEVICE1 SG_ SOE : 32|16@1+ (0.01,0) [0|100] "%" DEVICE1 SG_ SOC : 16|16@1+ (0.01,0) [0|100] "%" DEVICE1)"); - libdbc::DbcParser p; - p.parse_file(filename); + libdbc::DbcParser p; + p.parse_file(filename); - std::vector data{0x08, 0x27, 0xa3, 0x22, 0xe5, 0x1f, 0x45, 0x14}; // little endian - std::vector result_values; - REQUIRE(p.parseMessage(0x21d, data, result_values) == libdbc::Message::ParseSignalsStatus::Success); - REQUIRE(result_values.size() == 4); + std::vector data{0x08, 0x27, 0xa3, 0x22, 0xe5, 0x1f, 0x45, 0x14}; // little endian + std::vector result_values; + REQUIRE(p.parseMessage(0x21d, data, result_values) == libdbc::Message::ParseSignalsStatus::Success); + REQUIRE(result_values.size() == 4); - REQUIRE(Catch::Approx(result_values.at(0)) == 11.89); - REQUIRE(Catch::Approx(result_values.at(1)) == 99.92); - REQUIRE(Catch::Approx(result_values.at(2)) == 81.65); - REQUIRE(Catch::Approx(result_values.at(3)) == 88.67); + REQUIRE(Catch::Approx(result_values.at(0)) == 11.89); + REQUIRE(Catch::Approx(result_values.at(1)) == 99.92); + REQUIRE(Catch::Approx(result_values.at(2)) == 81.65); + REQUIRE(Catch::Approx(result_values.at(3)) == 88.67); } TEST_CASE("Parse Message big endian signed values") { - const auto* filename = std::tmpnam(NULL); - create_tmp_dbc_with(filename, R"(BO_ 545 MSG: 8 BMS2 + const auto* filename = std::tmpnam(NULL); + create_tmp_dbc_with(filename, R"(BO_ 545 MSG: 8 BMS2 SG_ Sig1 : 62|1@0+ (1,0) [0|0] "" Vector__XXX SG_ Sig2 : 49|2@0+ (1,0) [0|0] "" Vector__XXX SG_ Sig3 : 39|16@0- (0.1,0) [0|0] "A" Vector__XXX @@ -121,23 +121,23 @@ TEST_CASE("Parse Message big endian signed values") { SG_ Sig11 : 7|16@0+ (0.001,0) [0|65.535] "V" Vector__XXX SG_ Sig12 : 23|16@0+ (0.1,0) [0|6553.5] "A" Vector__XXX)"); - libdbc::DbcParser p; - p.parse_file(filename); - - std::vector data{13, 177, 0, 216, 251, 180, 0, 31}; // big endian - std::vector result_values; - REQUIRE(p.parseMessage(545, data, result_values) == libdbc::Message::ParseSignalsStatus::Success); - REQUIRE(result_values.size() == 12); - REQUIRE(Catch::Approx(result_values.at(0)) == 0); - REQUIRE(Catch::Approx(result_values.at(1)) == 0); - REQUIRE(Catch::Approx(result_values.at(2)) == -110); - REQUIRE(Catch::Approx(result_values.at(3)) == 1); - REQUIRE(Catch::Approx(result_values.at(4)) == 0); - REQUIRE(Catch::Approx(result_values.at(5)) == 1); - REQUIRE(Catch::Approx(result_values.at(6)) == 1); - REQUIRE(Catch::Approx(result_values.at(7)) == 1); - REQUIRE(Catch::Approx(result_values.at(8)) == 1); - REQUIRE(Catch::Approx(result_values.at(9)) == 0); - REQUIRE(Catch::Approx(result_values.at(10)) == 3.5050); - REQUIRE(Catch::Approx(result_values.at(11)) == 21.6); + libdbc::DbcParser p; + p.parse_file(filename); + + std::vector data{13, 177, 0, 216, 251, 180, 0, 31}; // big endian + std::vector result_values; + REQUIRE(p.parseMessage(545, data, result_values) == libdbc::Message::ParseSignalsStatus::Success); + REQUIRE(result_values.size() == 12); + REQUIRE(Catch::Approx(result_values.at(0)) == 0); + REQUIRE(Catch::Approx(result_values.at(1)) == 0); + REQUIRE(Catch::Approx(result_values.at(2)) == -110); + REQUIRE(Catch::Approx(result_values.at(3)) == 1); + REQUIRE(Catch::Approx(result_values.at(4)) == 0); + REQUIRE(Catch::Approx(result_values.at(5)) == 1); + REQUIRE(Catch::Approx(result_values.at(6)) == 1); + REQUIRE(Catch::Approx(result_values.at(7)) == 1); + REQUIRE(Catch::Approx(result_values.at(8)) == 1); + REQUIRE(Catch::Approx(result_values.at(9)) == 0); + REQUIRE(Catch::Approx(result_values.at(10)) == 3.5050); + REQUIRE(Catch::Approx(result_values.at(11)) == 21.6); } diff --git a/test/test_utils.cpp b/test/test_utils.cpp index 37aab50..6417498 100644 --- a/test/test_utils.cpp +++ b/test/test_utils.cpp @@ -1,5 +1,5 @@ -#include #include "defines.hpp" +#include #include #include @@ -14,7 +14,7 @@ TEST_CASE("Basic file input with safe get_line that is non line ending specific" TextFile.open(TEXT_FILE, std::ios::in); CHECK(TextFile.is_open()); - if(TextFile.is_open()) { + if (TextFile.is_open()) { StreamHandler::get_line(TextFile, test); REQUIRE(test == "This is a non dbc formatted file."); StreamHandler::get_line(TextFile, test); @@ -31,8 +31,8 @@ TEST_CASE("Basic file input with safe get_line that is non line ending specific" TEST_CASE("Test line finding utility functions", "") { std::string line; - std::string test_string = \ -"hello\n\ + std::string test_string = + "hello\n\ \n\ \n\ \n\ @@ -91,4 +91,3 @@ TEST_CASE("Test string split feature", "[string]") { REQUIRE(v == vs); } -