diff --git a/CMakeLists.txt b/CMakeLists.txt index 44e6cef..361d563 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,8 @@ include(CPack) option(DEBUG "use debug flag" NO) option(ENABLE_TESTS "Enable Unittests" ON) +# Turn OFF, if you are using FetchContent to include it to your project +option(FETCH_CONTENT_INCLUSION "Include project with FetchContent_Declare in another project. In this case the headers and the cmake files are not needed, only the library" OFF) # defines variables used in the dbc.pc.in include(GNUInstallDirs) @@ -30,7 +32,9 @@ if (NOT ${FastFloat_FOUND}) GIT_REPOSITORY https://github.com/fastfloat/fast_float.git GIT_TAG 1ea4f27b2aeee2859a1354a3c24cff52a116cad1 ) - FetchContent_MakeAvailable(FastFloat) + # FetchContent_MakeAvailable(FastFloat) + FetchContent_Populate(FastFloat) + add_subdirectory(${fastfloat_SOURCE_DIR} ${fastfloat_BINARY_DIR} EXCLUDE_FROM_ALL) endif() set(GCC_COMPILE_FLAGS "-Wextra -Wall -Wfloat-equal -Wundef -Wshadow \ @@ -92,18 +96,21 @@ install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}) # install headers -if (${CMAKE_MINOR_VERSION} GREATER_EQUAL 23) +if (${CMAKE_MINOR_VERSION} GREATER_EQUAL 23 AND NOT FETCH_CONTENT_INCLUSION) install(TARGETS ${PROJECT_NAME} FILE_SET HEADERS DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/lib${PROJECT_NAME} INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) -else() +elseif(NOT FETCH_CONTENT_INCLUSION) install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/libdbc DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) endif() -# Generate pkg-config file -configure_file(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY) -install( - FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc - DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) + +if (NOT FETCH_CONTENT_INCLUSION) + # Generate pkg-config file + configure_file(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY) + install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) +endif() diff --git a/include/libdbc/message.hpp b/include/libdbc/message.hpp index a6613b2..204f5c2 100644 --- a/include/libdbc/message.hpp +++ b/include/libdbc/message.hpp @@ -31,6 +31,9 @@ struct Message { void appendSignal(const Signal& signal); const std::vector getSignals() const; uint32_t id() const; + const std::string& name() const { + return m_name; + } void addValueDescription(const std::string& signal_name, const std::vector&); virtual bool operator==(const Message& rhs) const; diff --git a/include/libdbc/signal.hpp b/include/libdbc/signal.hpp index f41cef6..1b7076f 100644 --- a/include/libdbc/signal.hpp +++ b/include/libdbc/signal.hpp @@ -2,6 +2,7 @@ #ifndef __SIGNAL_HPP__ #define __SIGNAL_HPP__ +#include #include #include #include diff --git a/src/message.cpp b/src/message.cpp index 1739b92..cc9a341 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -34,11 +34,8 @@ Message::ParseSignalsStatus Message::parseSignals(const std::vector& da 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); - } + } else + v = data_little_endian >> signal.start_bit; if (signal.is_signed && signal.size > 1) { switch (signal.size) { @@ -54,11 +51,23 @@ Message::ParseSignalsStatus Message::parseSignals(const std::vector& da case 64: values.push_back((int64_t)v * signal.factor + signal.offset); break; - default: - return ParseSignalsStatus::ErrorInvalidConversion; + default: { + // 2 complement -> decimal + const int negative = (v & (1 << (signal.size - 1))) != 0; + int64_t nativeInt; + if (negative) + nativeInt = v | ~((1 << signal.size) - 1); // invert all bits above signal.size + else + nativeInt = v & ((1 << signal.size) - 1); // masking + values.push_back(nativeInt * signal.factor + signal.offset); + break; } - } else + } + } else { + // use only the relevant bits + v = v & ((1 << signal.size) - 1); // masking values.push_back(v * signal.factor + signal.offset); + } } return ParseSignalsStatus::Success; } diff --git a/test/test_dbc.cpp b/test/test_dbc.cpp index 9c49888..dc386b5 100644 --- a/test/test_dbc.cpp +++ b/test/test_dbc.cpp @@ -80,6 +80,7 @@ TEST_CASE("Testing big endian, little endian") { parser.parse_file(filename); REQUIRE(parser.get_messages().size() == 1); + REQUIRE(parser.get_messages().at(0).name() == "MSG1"); REQUIRE(parser.get_messages().at(0).getSignals().size() == 2); { const auto signal = parser.get_messages().at(0).getSignals().at(0); @@ -104,6 +105,7 @@ TEST_CASE("Testing negative values") { parser.parse_file(filename); REQUIRE(parser.get_messages().size() == 1); + REQUIRE(parser.get_messages().at(0).name() == "MSG1"); REQUIRE(parser.get_messages().at(0).getSignals().size() == 4); SECTION("Evaluating first message") { @@ -146,6 +148,7 @@ TEST_CASE("Special characters in unit") { parser.parse_file(filename); REQUIRE(parser.get_messages().size() == 1); + REQUIRE(parser.get_messages().at(0).name() == "MSG1"); REQUIRE(parser.get_messages().at(0).getSignals().size() == 1); SECTION("Checking that signal with special characters as unit is parsed correctly") { const auto signal = parser.get_messages().at(0).getSignals().at(0); @@ -165,6 +168,7 @@ VAL_ 234 State1 123 "Description 1" 0 "Description 2" 90903489 "Big value and sp parser.parse_file(filename); REQUIRE(parser.get_messages().size() == 1); + REQUIRE(parser.get_messages().at(0).name() == "MSG1"); REQUIRE(parser.get_messages().at(0).getSignals().size() == 2); REQUIRE(parser.get_messages().at(0).getSignals().at(0).svDescriptions.size() == 3); @@ -194,6 +198,7 @@ VAL_ 3221225472 State1 123 "Description 1" 0 "Description 2" 4000000000 "Big val parser.parse_file(filename); REQUIRE(parser.get_messages().size() == 1); + REQUIRE(parser.get_messages().at(0).name() == "MSG1"); REQUIRE(parser.get_messages().at(0).getSignals().size() == 2); REQUIRE(parser.get_messages().at(0).getSignals().at(0).svDescriptions.size() == 3); @@ -217,7 +222,7 @@ TEST_CASE("Signal Value Multiple VAL_") { create_tmp_dbc_with(filename, R"(BO_ 3221225472 MSG1: 8 Vector__XXX SG_ State1 : 0|8@1+ (1,0) [0|200] "Km/h" DEVICE1,DEVICE2,DEVICE3 SG_ State2 : 0|8@1+ (1,0) [0|204] "" DEVICE1,DEVICE2,DEVICE3" -BO_ 123 MSG1: 8 Vector__XXX +BO_ 123 MSG2: 8 Vector__XXX SG_ State1 : 0|8@1+ (1,0) [0|200] "Km/h" DEVICE1,DEVICE2,DEVICE3 SG_ State2 : 0|8@1+ (1,0) [0|204] "" DEVICE1,DEVICE2,DEVICE3 VAL_ 3221225472 State1 123 "Description 1" 0 "Description 2" ; @@ -227,6 +232,9 @@ VAL_ 123 State1 123 "Description 3" 0 "Description 4" ;)"); parser.parse_file(filename); REQUIRE(parser.get_messages().size() == 2); + REQUIRE(parser.get_messages().at(0).name() == "MSG1"); + REQUIRE(parser.get_messages().at(1).name() == "MSG2"); + REQUIRE(parser.get_messages().at(0).getSignals().size() == 2); REQUIRE(parser.get_messages().at(0).getSignals().at(0).svDescriptions.size() == 2); diff --git a/test/test_parseMessage.cpp b/test/test_parseMessage.cpp index e171484..7ccb971 100644 --- a/test/test_parseMessage.cpp +++ b/test/test_parseMessage.cpp @@ -141,3 +141,41 @@ TEST_CASE("Parse Message big endian signed values") { REQUIRE(Catch::Approx(result_values.at(10)) == 3.5050); REQUIRE(Catch::Approx(result_values.at(11)) == 21.6); } + +TEST_CASE("Parse Message with non byte aligned values") { + const auto* filename = std::tmpnam(NULL); + create_tmp_dbc_with(filename, R"(BO_ 403 INFORMATION: 8 Vector__XXX + SG_ Voltage : 30|9@1+ (0.2,0) [0|102.2] "V" Vector__XXX + SG_ Phase_Current : 20|10@1- (1,0) [-512|512] "A" Vector__XXX + SG_ Iq_Current : 10|10@1- (1,0) [-512|512] "A" Vector__XXX + SG_ Id_Current : 0|10@1- (1,0) [-512|512] "A" Vector__XXX)"); + + libdbc::DbcParser p; + p.parse_file(filename); + + std::vector data{131, 51, 33, 9, 33, 0, 0, 0}; + std::vector result_values; + REQUIRE(p.parseMessage(403, data, result_values) == libdbc::Message::ParseSignalsStatus::Success); + REQUIRE(result_values.size() == 4); + REQUIRE(Catch::Approx(result_values.at(0)) == 26.4); + REQUIRE(Catch::Approx(result_values.at(1)) == 146); + REQUIRE(Catch::Approx(result_values.at(2)) == 76); + REQUIRE(Catch::Approx(result_values.at(3)) == -125); +} + +TEST_CASE("Parse Message data length < 8 unsigned") { + const auto* filename = std::tmpnam(NULL); + create_tmp_dbc_with(filename, R"(BO_ 234 MSG1: 8 Vector__XXX + SG_ Msg1Sig1 : 7|8@0+ (1,0) [-3276.8|-3276.7] "C" Vector__XXX + SG_ Msg1Sig2 : 15|8@0+ (1,0) [-3276.8|-3276.7] "km/h" Vector__XXX)"); + + libdbc::DbcParser p; + p.parse_file(filename); + + std::vector data{0x1, 0x2}; + std::vector result_values; + REQUIRE(p.parseMessage(234, data, result_values) == libdbc::Message::ParseSignalsStatus::Success); + REQUIRE(result_values.size() == 2); + REQUIRE(Catch::Approx(result_values.at(0)) == 0x1); + REQUIRE(Catch::Approx(result_values.at(1)) == 0x2); +}