From 58f485ee6bd94525291b0ae636503b7f6985bbfa Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Thu, 1 Feb 2024 18:56:02 -0500 Subject: [PATCH 01/47] Require bracing on single line if statements using clang format --- .clang-format | 2 ++ src/dbc.cpp | 56 ++++++++++++++++++++++++++++++++----------------- src/message.cpp | 11 ++++++---- src/signal.cpp | 3 ++- 4 files changed, 48 insertions(+), 24 deletions(-) diff --git a/.clang-format b/.clang-format index e5d309b..c409644 100644 --- a/.clang-format +++ b/.clang-format @@ -44,6 +44,8 @@ BraceWrapping: AfterClass: false AfterCaseLabel: false +InsertBraces: true + # CrlInstruction *a; DerivePointerAlignment: false PointerAlignment: Left diff --git a/src/dbc.cpp b/src/dbc.cpp index 8b3dac6..be9d34f 100644 --- a/src/dbc.cpp +++ b/src/dbc.cpp @@ -43,20 +43,25 @@ bool parseVal(const std::string& str, VALObject& obj) { for (;;) { switch (state) { case Identifier: { - if (*a != 'V') + if (*a != 'V') { return false; + } a++; - if (*a != 'A') + if (*a != 'A') { return false; + } a++; - if (*a != 'L') + if (*a != 'L') { return false; + } a++; - if (*a != '_') + if (*a != '_') { return false; + } a++; - if (*a != ' ') + if (*a != ' ') { return false; + } a++; // skip whitespace state = CANId; break; @@ -67,27 +72,31 @@ bool parseVal(const std::string& str, VALObject& obj) { can_id_str += *a; a++; } - if (can_id_str.empty()) + if (can_id_str.empty()) { return false; + } obj.can_id = static_cast(std::stoul(can_id_str)); - if (*a != ' ') + if (*a != ' ') { return false; + } a++; // skip whitespace state = SignalName; break; } case SignalName: { - if ((*a >= 'a' && *a <= 'z') || (*a >= 'A' && *a <= 'Z') || *a == '_') + if ((*a >= 'a' && *a <= 'z') || (*a >= 'A' && *a <= 'Z') || *a == '_') { obj.signal_name += *a; - else + } else { return false; + } a++; while ((*a >= 'a' && *a <= 'z') || (*a >= 'A' && *a <= 'Z') || *a == '_' || (*a >= '0' && *a <= '9')) { obj.signal_name += *a; a++; } - if (*a != ' ') + if (*a != ' ') { return false; + } a++; // skip whitespace state = Value; break; @@ -99,15 +108,18 @@ bool parseVal(const std::string& str, VALObject& obj) { a++; } if (*a == ';') { - if (value_str.empty()) + if (value_str.empty()) { return true; + } return false; } - if (value_str.empty()) + if (value_str.empty()) { return false; + } - if (*a != ' ') + if (*a != ' ') { return false; + } a++; // skip whitespace vd.value = (uint32_t)std::stoul(value_str); state = Description; @@ -115,18 +127,21 @@ bool parseVal(const std::string& str, VALObject& obj) { } case Description: { std::string desc; - if (*a != '"') + if (*a != '"') { return false; + } a++; while (*a != '"' && *a != 0) { desc += *a; a++; } - if (*a == 0) + if (*a == 0) { return false; + } a++; - if (*a != ' ') + if (*a != ' ') { return false; + } a++; // skip whitespace vd.description = desc; @@ -188,8 +203,9 @@ std::vector DbcParser::get_messages() const { 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) + if (message.id() == id) { return message.parseSignals(data, out_values); + } } return Message::ParseSignalsStatus::ErrorUnknownID; } @@ -212,8 +228,9 @@ void DbcParser::parse_dbc_header(std::istream& file_stream) { utils::StreamHandler::get_next_non_blank_line(file_stream, line); - if (!std::regex_search(line, match, bit_timing_re)) + if (!std::regex_search(line, match, bit_timing_re)) { throw validity_error(); + } } void DbcParser::parse_dbc_nodes(std::istream& file_stream) { @@ -222,8 +239,9 @@ void DbcParser::parse_dbc_nodes(std::istream& file_stream) { utils::StreamHandler::get_next_non_blank_line(file_stream, line); - if (!std::regex_search(line, match, node_re)) + if (!std::regex_search(line, match, node_re)) { throw validity_error(); + } if (match.length() > 2) { std::string n = match.str(2); diff --git a/src/message.cpp b/src/message.cpp index 443526a..f16677a 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -16,8 +16,9 @@ bool Message::operator==(const Message& rhs) const { Message::ParseSignalsStatus Message::parseSignals(const std::vector& data, std::vector& values) const { auto size = data.size(); - if (size > 8) + if (size > 8) { return ParseSignalsStatus::ErrorMessageToLong; // not supported yet + } uint64_t data_little_endian = 0; uint64_t data_big_endian = 0; @@ -35,8 +36,9 @@ 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 + } else { v = data_little_endian >> signal.start_bit; + } if (signal.is_signed && signal.size > 1) { switch (signal.size) { @@ -56,10 +58,11 @@ Message::ParseSignalsStatus Message::parseSignals(const std::vector& da // 2 complement -> decimal const int negative = (v & (1ull << (signal.size - 1))) != 0; int64_t nativeInt; - if (negative) + if (negative) { nativeInt = static_cast(v | ~((1ull << signal.size) - 1)); // invert all bits above signal.size - else + } else { nativeInt = static_cast(v & ((1ull << signal.size) - 1)); // masking + } values.push_back(static_cast(nativeInt) * signal.factor + signal.offset); break; } diff --git a/src/signal.cpp b/src/signal.cpp index a2ad53d..d1ab7d8 100644 --- a/src/signal.cpp +++ b/src/signal.cpp @@ -47,8 +47,9 @@ std::ostream& operator<<(std::ostream& out, const Signal& sig) { out << "Min: " << sig.min << ", Max: " << sig.max << ", "; out << "Unit: (" << sig.unit << "), "; out << "receivers: "; - for (const auto& r : sig.receivers) + for (const auto& r : sig.receivers) { out << r; + } return out << "}"; } } From 753119d6615674876d5f21216438d8dd663bca92 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Thu, 1 Feb 2024 19:05:39 -0500 Subject: [PATCH 02/47] Removing whitespace and dead comments --- include/libdbc/message.hpp | 6 ------ src/dbc.cpp | 2 -- src/utils.cpp | 1 - 3 files changed, 9 deletions(-) diff --git a/include/libdbc/message.hpp b/include/libdbc/message.hpp index e903fed..f3b0b66 100644 --- a/include/libdbc/message.hpp +++ b/include/libdbc/message.hpp @@ -21,12 +21,6 @@ struct Message { ErrorInvalidConversion, }; - /*! - * \brief parseSignals - * \param data - * \param values - * \return - */ ParseSignalsStatus parseSignals(const std::vector& data, std::vector& values) const; void appendSignal(const Signal& signal); diff --git a/src/dbc.cpp b/src/dbc.cpp index be9d34f..7ea7ce3 100644 --- a/src/dbc.cpp +++ b/src/dbc.cpp @@ -223,9 +223,7 @@ void DbcParser::parse_dbc_header(std::istream& file_stream) { version = match.str(2); utils::StreamHandler::get_next_non_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); if (!std::regex_search(line, match, bit_timing_re)) { diff --git a/src/utils.cpp b/src/utils.cpp index 35cff0c..f39cc81 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -75,7 +75,6 @@ std::string String::trim(const std::string& line) { double String::convert_to_double(const std::string& value, double default_value) { double converted_value = default_value; fast_float::from_chars(value.data(), value.data() + value.size(), converted_value); - // converted_value = std::stod(value); return converted_value; } From 6a2aeff602f14e506789086271f37ab4b8f4d399 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Thu, 1 Feb 2024 21:48:54 -0500 Subject: [PATCH 03/47] Adding initial clang tidy file and target to run it --- .clang-tidy | 368 +++++++++++++++++++++++++++++++++++++++++++++++++ CMakeLists.txt | 7 + 2 files changed, 375 insertions(+) create mode 100644 .clang-tidy diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..45b0537 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,368 @@ +--- +Checks: 'clang-diagnostic-*,clang-analyzer-*,*,-clang-analyzer-alpha.*,-llvm-include-order' +WarningsAsErrors: '' +HeaderFilterRegex: '' +AnalyzeTemporaryDtors: false +FormatStyle: none +User: dwag +CheckOptions: + hicpp-move-const-arg.CheckMoveToConstRef: 'true' + readability-suspicious-call-argument.PrefixSimilarAbove: '30' + cppcoreguidelines-no-malloc.Reallocations: '::realloc' + portability-simd-intrinsics.Std: '' + cppcoreguidelines-owning-memory.LegacyResourceConsumers: '::free;::realloc;::freopen;::fclose' + bugprone-reserved-identifier.Invert: 'false' + cert-dcl16-c.IgnoreMacros: 'true' + bugprone-narrowing-conversions.PedanticMode: 'false' + altera-struct-pack-align.MaxConfiguredAlignment: '128' + bugprone-unused-return-value.CheckedFunctions: '::std::async;::std::launder;::std::remove;::std::remove_if;::std::unique;::std::unique_ptr::release;::std::basic_string::empty;::std::vector::empty;::std::back_inserter;::std::distance;::std::find;::std::find_if;::std::inserter;::std::lower_bound;::std::make_pair;::std::map::count;::std::map::find;::std::map::lower_bound;::std::multimap::equal_range;::std::multimap::upper_bound;::std::set::count;::std::set::find;::std::setfill;::std::setprecision;::std::setw;::std::upper_bound;::std::vector::at;::bsearch;::ferror;::feof;::isalnum;::isalpha;::isblank;::iscntrl;::isdigit;::isgraph;::islower;::isprint;::ispunct;::isspace;::isupper;::iswalnum;::iswprint;::iswspace;::isxdigit;::memchr;::memcmp;::strcmp;::strcoll;::strncmp;::strpbrk;::strrchr;::strspn;::strstr;::wcscmp;::access;::bind;::connect;::difftime;::dlsym;::fnmatch;::getaddrinfo;::getopt;::htonl;::htons;::iconv_open;::inet_addr;::isascii;::isatty;::mmap;::newlocale;::openat;::pathconf;::pthread_equal;::pthread_getspecific;::pthread_mutex_trylock;::readdir;::readlink;::recvmsg;::regexec;::scandir;::semget;::setjmp;::shm_open;::shmget;::sigismember;::strcasecmp;::strsignal;::ttyname' + modernize-use-auto.MinTypeNameLength: '5' + cert-dcl51-cpp.AggressiveDependentMemberLookup: 'false' + hicpp-use-auto.MinTypeNameLength: '5' + readability-inconsistent-declaration-parameter-name.Strict: 'false' + hicpp-use-override.IgnoreDestructors: 'false' + cppcoreguidelines-macro-usage.CheckCapsOnly: 'false' + readability-suspicious-call-argument.DiceDissimilarBelow: '60' + cert-dcl37-c.AllowedIdentifiers: '' + performance-inefficient-vector-operation.VectorLikeClasses: '::std::vector' + hicpp-use-emplace.SmartPointers: '::std::shared_ptr;::std::unique_ptr;::std::auto_ptr;::std::weak_ptr' + bugprone-assert-side-effect.IgnoredFunctions: __builtin_expect + hicpp-member-init.IgnoreArrays: 'false' + openmp-exception-escape.IgnoredExceptions: '' + readability-suspicious-call-argument.Equality: 'true' + hicpp-use-override.AllowOverrideAndFinal: 'false' + misc-uniqueptr-reset-release.IncludeStyle: llvm + abseil-string-find-str-contains.StringLikeClasses: '::std::basic_string;::std::basic_string_view;::absl::string_view' + readability-const-return-type.IgnoreMacros: 'true' + hicpp-signed-bitwise.IgnorePositiveIntegerLiterals: 'false' + bugprone-easily-swappable-parameters.QualifiersMix: 'false' + cert-err09-cpp.WarnOnLargeObjects: 'false' + bugprone-suspicious-string-compare.WarnOnImplicitComparison: 'true' + bugprone-argument-comment.CommentNullPtrs: '0' + android-comparison-in-temp-failure-retry.RetryMacros: TEMP_FAILURE_RETRY + cppcoreguidelines-narrowing-conversions.WarnOnFloatingPointNarrowingConversion: 'true' + hicpp-use-equals-delete.IgnoreMacros: 'true' + cppcoreguidelines-init-variables.IncludeStyle: llvm + modernize-use-nodiscard.ReplacementString: '[[nodiscard]]' + modernize-loop-convert.MakeReverseRangeHeader: '' + readability-avoid-const-params-in-decls.IgnoreMacros: 'true' + readability-suspicious-call-argument.SuffixSimilarAbove: '30' + misc-definitions-in-headers.HeaderFileExtensions: ';h;hh;hpp;hxx' + hicpp-uppercase-literal-suffix.NewSuffixes: '' + modernize-use-emplace.ContainersWithPush: '::std::stack;::std::queue;::std::priority_queue' + cppcoreguidelines-narrowing-conversions.WarnOnIntegerNarrowingConversion: 'true' + bugprone-easily-swappable-parameters.IgnoredParameterNames: '"";iterator;Iterator;begin;Begin;end;End;first;First;last;Last;lhs;LHS;rhs;RHS' + modernize-loop-convert.UseCxx20ReverseRanges: 'true' + cppcoreguidelines-prefer-member-initializer.UseAssignment: 'false' + hicpp-function-size.VariableThreshold: '4294967295' + cert-oop57-cpp.MemSetNames: '' + hicpp-no-malloc.Deallocations: '::free' + performance-type-promotion-in-math-fn.IncludeStyle: llvm + google-readability-function-size.LineThreshold: '4294967295' + readability-function-cognitive-complexity.DescribeBasicIncrements: 'true' + bugprone-suspicious-include.ImplementationFileExtensions: 'c;cc;cpp;cxx' + hicpp-use-emplace.ContainersWithPushFront: '::std::forward_list;::std::list;::std::deque' + modernize-loop-convert.MakeReverseRangeFunction: '' + readability-inconsistent-declaration-parameter-name.IgnoreMacros: 'true' + bugprone-suspicious-missing-comma.SizeThreshold: '5' + readability-identifier-naming.IgnoreFailedSplit: 'false' + hicpp-multiway-paths-covered.WarnOnMissingElse: 'false' + readability-qualified-auto.AddConstToQualified: 'true' + bugprone-sizeof-expression.WarnOnSizeOfThis: 'true' + bugprone-string-constructor.WarnOnLargeLength: 'true' + cppcoreguidelines-explicit-virtual-functions.OverrideSpelling: override + hicpp-no-malloc.Allocations: '::malloc;::calloc' + hicpp-use-noexcept.UseNoexceptFalse: 'true' + abseil-string-find-startswith.IncludeStyle: llvm + google-global-names-in-headers.HeaderFileExtensions: ';h;hh;hpp;hxx' + readability-uppercase-literal-suffix.IgnoreMacros: 'true' + modernize-make-shared.IgnoreMacros: 'true' + modernize-use-emplace.ContainersWithPushFront: '::std::forward_list;::std::list;::std::deque' + misc-const-correctness.TransformValues: 'true' + cert-dcl59-cpp.HeaderFileExtensions: ';h;hh;hpp;hxx' + bugprone-suspicious-enum-usage.StrictMode: 'false' + performance-unnecessary-copy-initialization.AllowedTypes: '' + bugprone-suspicious-missing-comma.MaxConcatenatedTokens: '5' + modernize-use-transparent-functors.SafeMode: 'false' + readability-suspicious-call-argument.Levenshtein: 'true' + bugprone-not-null-terminated-result.WantToUseSafeFunctions: 'true' + misc-throw-by-value-catch-by-reference.CheckThrowTemporaries: 'true' + bugprone-string-constructor.LargeLengthThreshold: '8388608' + bugprone-dynamic-static-initializers.HeaderFileExtensions: ';h;hh;hpp;hxx' + readability-simplify-boolean-expr.ChainedConditionalAssignment: 'false' + cppcoreguidelines-avoid-magic-numbers.IgnoreAllFloatingPointValues: 'false' + cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField: 'false' + cert-err09-cpp.CheckThrowTemporaries: 'true' + performance-inefficient-vector-operation.EnableProto: 'false' + bugprone-exception-escape.FunctionsThatShouldNotThrow: '' + modernize-loop-convert.MaxCopySize: '16' + readability-suspicious-call-argument.PrefixDissimilarBelow: '25' + readability-function-size.LineThreshold: '4294967295' + bugprone-easily-swappable-parameters.MinimumLength: '2' + portability-simd-intrinsics.Suggest: 'false' + hicpp-deprecated-headers.CheckHeaderFile: 'false' + modernize-use-override.IgnoreDestructors: 'false' + cppcoreguidelines-pro-bounds-constant-array-index.GslHeader: '' + modernize-make-shared.MakeSmartPtrFunctionHeader: '' + modernize-make-shared.MakeSmartPtrFunction: 'std::make_shared' + misc-non-private-member-variables-in-classes.IgnorePublicMemberVariables: 'false' + bugprone-sizeof-expression.WarnOnSizeOfConstant: 'true' + readability-redundant-string-init.StringNames: '::std::basic_string_view;::std::basic_string' + modernize-make-unique.IgnoreDefaultInitialization: 'true' + modernize-use-emplace.ContainersWithPushBack: '::std::vector;::std::list;::std::deque' + readability-magic-numbers.IgnoreBitFieldsWidths: 'true' + modernize-make-unique.IncludeStyle: llvm + modernize-use-override.OverrideSpelling: override + google-readability-function-size.NestingThreshold: '4294967295' + google-build-namespaces.HeaderFileExtensions: ';h;hh;hpp;hxx' + readability-suspicious-call-argument.LevenshteinDissimilarBelow: '50' + bugprone-argument-comment.CommentStringLiterals: '0' + concurrency-mt-unsafe.FunctionSet: any + readability-identifier-length.IgnoredExceptionVariableNames: '^[e]$' + google-readability-braces-around-statements.ShortStatementLines: '1' + bugprone-reserved-identifier.AllowedIdentifiers: '' + cppcoreguidelines-pro-type-member-init.IgnoreArrays: 'false' + readability-else-after-return.WarnOnUnfixable: 'true' + cppcoreguidelines-avoid-magic-numbers.IgnoredFloatingPointValues: '1.0;100.0;' + modernize-use-emplace.IgnoreImplicitConstructors: 'false' + cppcoreguidelines-macro-usage.IgnoreCommandLineMacros: 'true' + readability-suspicious-call-argument.Substring: 'true' + modernize-use-equals-delete.IgnoreMacros: 'true' + objc-forbidden-subclassing.ForbiddenSuperClassNames: 'ABNewPersonViewController;ABPeoplePickerNavigationController;ABPersonViewController;ABUnknownPersonViewController;NSHashTable;NSMapTable;NSPointerArray;NSPointerFunctions;NSTimer;UIActionSheet;UIAlertView;UIImagePickerController;UITextInputMode;UIWebView' + readability-identifier-length.IgnoredVariableNames: '' + readability-magic-numbers.IgnoreAllFloatingPointValues: 'false' + cppcoreguidelines-pro-bounds-constant-array-index.IncludeStyle: llvm + hicpp-use-auto.RemoveStars: 'false' + readability-suspicious-call-argument.Abbreviations: 'arr=array;cnt=count;idx=index;src=source;stmt=statement;cpy=copy;dest=destination;dist=distancedst=distance;ptr=pointer;wdth=width;str=string;ln=line;srv=server;attr=attribute;ref=reference;buf=buffer;col=column;nr=number;vec=vector;len=length;elem=element;val=value;i=index;var=variable;hght=height;cl=client;num=number;pos=position;lst=list;addr=address' + bugprone-misplaced-widening-cast.CheckImplicitCasts: 'false' + readability-uppercase-literal-suffix.NewSuffixes: '' + modernize-loop-convert.MinConfidence: reasonable + performance-unnecessary-value-param.AllowedTypes: '' + readability-uniqueptr-delete-release.PreferResetCall: 'false' + readability-identifier-length.MinimumExceptionNameLength: '2' + misc-definitions-in-headers.UseHeaderFileExtension: 'true' + google-readability-namespace-comments.SpacesBeforeComments: '2' + cppcoreguidelines-avoid-magic-numbers.IgnoreBitFieldsWidths: 'true' + cert-err61-cpp.CheckThrowTemporaries: 'true' + cppcoreguidelines-avoid-magic-numbers.IgnoredIntegerValues: '1;2;3;4;' + cppcoreguidelines-no-malloc.Allocations: '::malloc;::calloc' + misc-throw-by-value-catch-by-reference.MaxSize: '-1' + cppcoreguidelines-avoid-magic-numbers.IgnorePowersOf2IntegerValues: 'false' + bugprone-narrowing-conversions.IgnoreConversionFromTypes: '' + readability-function-size.BranchThreshold: '4294967295' + bugprone-suspicious-missing-comma.RatioThreshold: '0.200000' + hicpp-function-size.LineThreshold: '4294967295' + readability-implicit-bool-conversion.AllowIntegerConditions: 'false' + readability-identifier-length.IgnoredParameterNames: '^[n]$' + readability-function-size.StatementThreshold: '800' + hicpp-use-noexcept.ReplacementString: '' + readability-identifier-naming.IgnoreMainLikeFunctions: 'false' + cppcoreguidelines-init-variables.MathHeader: '' + google-runtime-int.SignedTypePrefix: int + google-readability-function-size.StatementThreshold: '800' + cert-msc51-cpp.DisallowedSeedTypes: 'time_t,std::time_t' + hicpp-use-emplace.TupleMakeFunctions: '::std::make_pair;::std::make_tuple' + bugprone-reserved-identifier.AggressiveDependentMemberLookup: 'false' + readability-suspicious-call-argument.DiceSimilarAbove: '70' + modernize-use-equals-default.IgnoreMacros: 'true' + readability-suspicious-call-argument.Abbreviation: 'true' + cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor: 'false' + cert-dcl37-c.AggressiveDependentMemberLookup: 'false' + readability-identifier-length.MinimumLoopCounterNameLength: '2' + abseil-string-find-str-contains.AbseilStringsMatchHeader: 'absl/strings/match.h' + bugprone-dangling-handle.HandleClasses: 'std::basic_string_view;std::experimental::basic_string_view' + cert-msc54-cpp.AsyncSafeFunctionSet: POSIX + modernize-use-emplace.SmartPointers: '::std::shared_ptr;::std::unique_ptr;::std::auto_ptr;::std::weak_ptr' + readability-magic-numbers.IgnorePowersOf2IntegerValues: 'false' + misc-const-correctness.TransformPointersAsValues: 'false' + readability-suspicious-call-argument.JaroWinklerSimilarAbove: '85' + misc-unused-parameters.StrictMode: 'false' + cppcoreguidelines-no-malloc.Deallocations: '::free' + readability-simplify-subscript-expr.Types: '::std::basic_string;::std::basic_string_view;::std::vector;::std::array' + performance-unnecessary-copy-initialization.ExcludedContainerTypes: '' + modernize-replace-auto-ptr.IncludeStyle: llvm + performance-move-const-arg.CheckTriviallyCopyableMove: 'true' + misc-const-correctness.TransformReferences: 'true' + hicpp-move-const-arg.CheckTriviallyCopyableMove: 'true' + readability-function-size.VariableThreshold: '4294967295' + readability-static-accessed-through-instance.NameSpecifierNestingThreshold: '3' + cert-dcl16-c.NewSuffixes: 'L;LL;LU;LLU' + misc-const-correctness.AnalyzeValues: 'true' + readability-identifier-naming.GetConfigPerFile: 'true' + bugprone-narrowing-conversions.WarnOnFloatingPointNarrowingConversion: 'true' + cert-sig30-c.AsyncSafeFunctionSet: POSIX + readability-simplify-boolean-expr.SimplifyDeMorgan: 'true' + cert-err61-cpp.MaxSize: '-1' + hicpp-member-init.UseAssignment: 'false' + modernize-use-default-member-init.UseAssignment: 'false' + readability-function-size.NestingThreshold: '4294967295' + google-readability-function-size.BranchThreshold: '4294967295' + bugprone-sizeof-expression.WarnOnSizeOfPointerToAggregate: 'true' + llvm-namespace-comment.ShortNamespaceLines: '1' + llvm-namespace-comment.SpacesBeforeComments: '1' + modernize-use-override.AllowOverrideAndFinal: 'false' + cppcoreguidelines-narrowing-conversions.IgnoreConversionFromTypes: '' + readability-function-size.ParameterThreshold: '4294967295' + hicpp-function-size.NestingThreshold: '4294967295' + modernize-pass-by-value.ValuesOnly: 'false' + readability-function-cognitive-complexity.IgnoreMacros: 'false' + modernize-loop-convert.IncludeStyle: llvm + cert-str34-c.DiagnoseSignedUnsignedCharComparisons: 'false' + bugprone-narrowing-conversions.WarnWithinTemplateInstantiation: 'false' + cert-err33-c.CheckedFunctions: '::aligned_alloc;::asctime_s;::at_quick_exit;::atexit;::bsearch;::bsearch_s;::btowc;::c16rtomb;::c32rtomb;::calloc;::clock;::cnd_broadcast;::cnd_init;::cnd_signal;::cnd_timedwait;::cnd_wait;::ctime_s;::fclose;::fflush;::fgetc;::fgetpos;::fgets;::fgetwc;::fopen;::fopen_s;::fprintf;::fprintf_s;::fputc;::fputs;::fputwc;::fputws;::fread;::freopen;::freopen_s;::fscanf;::fscanf_s;::fseek;::fsetpos;::ftell;::fwprintf;::fwprintf_s;::fwrite;::fwscanf;::fwscanf_s;::getc;::getchar;::getenv;::getenv_s;::gets_s;::getwc;::getwchar;::gmtime;::gmtime_s;::localtime;::localtime_s;::malloc;::mbrtoc16;::mbrtoc32;::mbsrtowcs;::mbsrtowcs_s;::mbstowcs;::mbstowcs_s;::memchr;::mktime;::mtx_init;::mtx_lock;::mtx_timedlock;::mtx_trylock;::mtx_unlock;::printf_s;::putc;::putwc;::raise;::realloc;::remove;::rename;::scanf;::scanf_s;::setlocale;::setvbuf;::signal;::snprintf;::snprintf_s;::sprintf;::sprintf_s;::sscanf;::sscanf_s;::strchr;::strerror_s;::strftime;::strpbrk;::strrchr;::strstr;::strtod;::strtof;::strtoimax;::strtok;::strtok_s;::strtol;::strtold;::strtoll;::strtoul;::strtoull;::strtoumax;::strxfrm;::swprintf;::swprintf_s;::swscanf;::swscanf_s;::thrd_create;::thrd_detach;::thrd_join;::thrd_sleep;::time;::timespec_get;::tmpfile;::tmpfile_s;::tmpnam;::tmpnam_s;::tss_create;::tss_get;::tss_set;::ungetc;::ungetwc;::vfprintf;::vfprintf_s;::vfscanf;::vfscanf_s;::vfwprintf;::vfwprintf_s;::vfwscanf;::vfwscanf_s;::vprintf_s;::vscanf;::vscanf_s;::vsnprintf;::vsnprintf_s;::vsprintf;::vsprintf_s;::vsscanf;::vsscanf_s;::vswprintf;::vswprintf_s;::vswscanf;::vswscanf_s;::vwprintf_s;::vwscanf;::vwscanf_s;::wcrtomb;::wcschr;::wcsftime;::wcspbrk;::wcsrchr;::wcsrtombs;::wcsrtombs_s;::wcsstr;::wcstod;::wcstof;::wcstoimax;::wcstok;::wcstok_s;::wcstol;::wcstold;::wcstoll;::wcstombs;::wcstombs_s;::wcstoul;::wcstoull;::wcstoumax;::wcsxfrm;::wctob;::wctrans;::wctype;::wmemchr;::wprintf_s;::wscanf;::wscanf_s;' + bugprone-suspicious-string-compare.WarnOnLogicalNotComparison: 'false' + hicpp-braces-around-statements.ShortStatementLines: '0' + cppcoreguidelines-explicit-virtual-functions.AllowOverrideAndFinal: 'false' + google-readability-function-size.ParameterThreshold: '4294967295' + readability-redundant-smartptr-get.IgnoreMacros: 'true' + readability-identifier-naming.AggressiveDependentMemberLookup: 'false' + cert-err61-cpp.WarnOnLargeObjects: 'false' + misc-const-correctness.WarnPointersAsValues: 'false' + readability-identifier-length.MinimumParameterNameLength: '3' + modernize-use-emplace.TupleTypes: '::std::pair;::std::tuple' + hicpp-use-emplace.IgnoreImplicitConstructors: 'false' + modernize-use-emplace.TupleMakeFunctions: '::std::make_pair;::std::make_tuple' + bugprone-narrowing-conversions.WarnOnIntegerToFloatingPointNarrowingConversion: 'true' + cppcoreguidelines-owning-memory.LegacyResourceProducers: '::malloc;::aligned_alloc;::realloc;::calloc;::fopen;::freopen;::tmpfile' + bugprone-easily-swappable-parameters.SuppressParametersUsedTogether: 'true' + bugprone-argument-comment.StrictMode: '0' + hicpp-uppercase-literal-suffix.IgnoreMacros: 'true' + misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic: 'false' + modernize-replace-random-shuffle.IncludeStyle: llvm + modernize-use-bool-literals.IgnoreMacros: 'true' + bugprone-easily-swappable-parameters.NamePrefixSuffixSilenceDissimilarityTreshold: '1' + bugprone-unhandled-self-assignment.WarnOnlyIfThisHasSuspiciousField: 'true' + google-readability-namespace-comments.ShortNamespaceLines: '10' + readability-suspicious-call-argument.JaroWinklerDissimilarBelow: '75' + bugprone-suspicious-string-compare.StringCompareLikeFunctions: '' + modernize-avoid-bind.PermissiveParameterList: 'false' + readability-suspicious-call-argument.Suffix: 'true' + cert-err09-cpp.MaxSize: '-1' + modernize-use-override.FinalSpelling: final + hicpp-use-equals-default.IgnoreMacros: 'true' + modernize-use-noexcept.ReplacementString: '' + hicpp-use-override.OverrideSpelling: override + modernize-use-using.IgnoreMacros: 'true' + hicpp-use-override.FinalSpelling: final + cppcoreguidelines-explicit-virtual-functions.FinalSpelling: final + readability-suspicious-call-argument.MinimumIdentifierNameLength: '3' + bugprone-narrowing-conversions.WarnOnIntegerNarrowingConversion: 'true' + modernize-loop-convert.NamingStyle: CamelCase + cppcoreguidelines-pro-type-member-init.UseAssignment: 'false' + bugprone-suspicious-include.HeaderFileExtensions: ';h;hh;hpp;hxx' + hicpp-function-size.StatementThreshold: '800' + readability-suspicious-call-argument.SubstringDissimilarBelow: '40' + hicpp-no-malloc.Reallocations: '::realloc' + bugprone-stringview-nullptr.IncludeStyle: llvm + performance-for-range-copy.WarnOnAllAutoCopies: 'false' + google-runtime-int.UnsignedTypePrefix: uint + performance-no-automatic-move.AllowedTypes: '' + modernize-pass-by-value.IncludeStyle: llvm + bugprone-argument-comment.CommentIntegerLiterals: '0' + bugprone-argument-comment.CommentFloatLiterals: '0' + bugprone-too-small-loop-variable.MagnitudeBitsUpperLimit: '16' + abseil-string-find-startswith.AbseilStringsMatchHeader: 'absl/strings/match.h' + readability-simplify-boolean-expr.ChainedConditionalReturn: 'false' + readability-else-after-return.WarnOnConditionVariables: 'true' + modernize-use-nullptr.NullMacros: 'NULL' + readability-suspicious-call-argument.SuffixDissimilarBelow: '25' + bugprone-argument-comment.CommentCharacterLiterals: '0' + cppcoreguidelines-macro-usage.AllowedRegexp: '^DEBUG_*' + llvm-header-guard.HeaderFileExtensions: ';h;hh;hpp;hxx' + readability-suspicious-call-argument.LevenshteinSimilarAbove: '66' + cppcoreguidelines-narrowing-conversions.PedanticMode: 'false' + modernize-make-shared.IgnoreDefaultInitialization: 'true' + readability-suspicious-call-argument.JaroWinkler: 'true' + bugprone-implicit-widening-of-multiplication-result.UseCXXHeadersInCppSources: 'true' + modernize-make-shared.IncludeStyle: llvm + readability-suspicious-call-argument.Prefix: 'true' + hicpp-special-member-functions.AllowMissingMoveFunctions: 'false' + cppcoreguidelines-special-member-functions.AllowMissingMoveFunctions: 'false' + bugprone-implicit-widening-of-multiplication-result.UseCXXStaticCastsInCppSources: 'true' + bugprone-signed-char-misuse.CharTypdefsToIgnore: '' + cert-dcl51-cpp.Invert: 'false' + hicpp-special-member-functions.AllowSoleDefaultDtor: 'false' + modernize-deprecated-headers.CheckHeaderFile: 'false' + hicpp-use-emplace.EmplacyFunctions: 'vector::emplace_back;vector::emplace;deque::emplace;deque::emplace_front;deque::emplace_back;forward_list::emplace_after;forward_list::emplace_front;list::emplace;list::emplace_back;list::emplace_front;set::emplace;set::emplace_hint;map::emplace;map::emplace_hint;multiset::emplace;multiset::emplace_hint;multimap::emplace;multimap::emplace_hint;unordered_set::emplace;unordered_set::emplace_hint;unordered_map::emplace;unordered_map::emplace_hint;unordered_multiset::emplace;unordered_multiset::emplace_hint;unordered_multimap::emplace;unordered_multimap::emplace_hint;stack::emplace;queue::emplace;priority_queue::emplace' + cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors: 'false' + modernize-make-unique.IgnoreMacros: 'true' + performance-for-range-copy.AllowedTypes: '' + hicpp-function-size.BranchThreshold: '4294967295' + misc-const-correctness.AnalyzeReferences: 'true' + bugprone-unchecked-optional-access.IgnoreSmartPointerDereference: 'false' + bugprone-argument-comment.CommentBoolLiterals: '0' + readability-braces-around-statements.ShortStatementLines: '0' + bugprone-argument-comment.CommentUserDefinedLiterals: '0' + hicpp-use-emplace.ContainersWithPushBack: '::std::vector;::std::list;::std::deque' + abseil-string-find-startswith.StringLikeClasses: '::std::basic_string' + hicpp-special-member-functions.AllowMissingMoveFunctionsWhenCopyIsDeleted: 'false' + performance-inefficient-string-concatenation.StrictMode: 'false' + readability-redundant-declaration.IgnoreMacros: 'true' + readability-magic-numbers.IgnoredFloatingPointValues: '1.0;100.0;' + bugprone-easily-swappable-parameters.IgnoredParameterTypeSuffixes: 'bool;Bool;_Bool;it;It;iterator;Iterator;inputit;InputIt;forwardit;ForwardIt;bidirit;BidirIt;constiterator;const_iterator;Const_Iterator;Constiterator;ConstIterator;RandomIt;randomit;random_iterator;ReverseIt;reverse_iterator;reverse_const_iterator;ConstReverseIterator;Const_Reverse_Iterator;const_reverse_iterator;Constreverseiterator;constreverseiterator' + modernize-make-unique.MakeSmartPtrFunction: 'std::make_unique' + google-runtime-int.TypeSuffix: '' + hicpp-function-size.ParameterThreshold: '4294967295' + cert-dcl51-cpp.AllowedIdentifiers: '' + abseil-cleanup-ctad.IncludeStyle: llvm + cert-oop57-cpp.MemCpyNames: '' + modernize-make-unique.MakeSmartPtrFunctionHeader: '' + bugprone-signal-handler.AsyncSafeFunctionSet: POSIX + bugprone-easily-swappable-parameters.ModelImplicitConversions: 'true' + readability-suspicious-call-argument.SubstringSimilarAbove: '50' + cppcoreguidelines-narrowing-conversions.WarnWithinTemplateInstantiation: 'false' + portability-restrict-system-includes.Includes: '*' + performance-move-const-arg.CheckMoveToConstRef: 'true' + readability-identifier-length.MinimumVariableNameLength: '3' + modernize-use-emplace.EmplacyFunctions: 'vector::emplace_back;vector::emplace;deque::emplace;deque::emplace_front;deque::emplace_back;forward_list::emplace_after;forward_list::emplace_front;list::emplace;list::emplace_back;list::emplace_front;set::emplace;set::emplace_hint;map::emplace;map::emplace_hint;multiset::emplace;multiset::emplace_hint;multimap::emplace;multimap::emplace_hint;unordered_set::emplace;unordered_set::emplace_hint;unordered_map::emplace;unordered_map::emplace_hint;unordered_multiset::emplace;unordered_multiset::emplace_hint;unordered_multimap::emplace;unordered_multimap::emplace_hint;stack::emplace;queue::emplace;priority_queue::emplace' + zircon-temporary-objects.Names: '' + cppcoreguidelines-narrowing-conversions.WarnOnEquivalentBitWidth: 'true' + hicpp-use-emplace.TupleTypes: '::std::pair;::std::tuple' + cppcoreguidelines-non-private-member-variables-in-classes.IgnorePublicMemberVariables: 'false' + readability-implicit-bool-conversion.AllowPointerConditions: 'false' + cppcoreguidelines-special-member-functions.AllowMissingMoveFunctionsWhenCopyIsDeleted: 'false' + cert-oop57-cpp.MemCmpNames: '' + modernize-use-noexcept.UseNoexceptFalse: 'true' + readability-function-cognitive-complexity.Threshold: '25' + cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic: 'true' + readability-simplify-boolean-expr.SimplifyDeMorganRelaxed: 'false' + bugprone-narrowing-conversions.WarnOnEquivalentBitWidth: 'true' + bugprone-sizeof-expression.WarnOnSizeOfIntegerExpression: 'false' + performance-faster-string-find.StringLikeClasses: '::std::basic_string;::std::basic_string_view' + cppcoreguidelines-narrowing-conversions.WarnOnIntegerToFloatingPointNarrowingConversion: 'true' + google-readability-function-size.VariableThreshold: '4294967295' + bugprone-assert-side-effect.CheckFunctionCalls: 'false' + bugprone-string-constructor.StringNames: '::std::basic_string;::std::basic_string_view' + bugprone-assert-side-effect.AssertMacros: assert,NSAssert,NSCAssert + bugprone-exception-escape.IgnoredExceptions: '' + bugprone-signed-char-misuse.DiagnoseSignedUnsignedCharComparisons: 'true' + altera-unroll-loops.MaxLoopIterations: '100' + llvm-qualified-auto.AddConstToQualified: 'false' + hicpp-use-emplace.ContainersWithPush: '::std::stack;::std::queue;::std::priority_queue' + modernize-use-default-member-init.IgnoreMacros: 'true' + cert-str34-c.CharTypdefsToIgnore: '' + misc-use-anonymous-namespace.HeaderFileExtensions: ';h;hh;hpp;hxx' + llvm-else-after-return.WarnOnConditionVariables: 'false' + bugprone-sizeof-expression.WarnOnSizeOfCompareToConstant: 'true' + bugprone-argument-comment.IgnoreSingleArgument: '0' + modernize-raw-string-literal.DelimiterStem: lit + readability-suspicious-call-argument.Dice: 'true' + misc-throw-by-value-catch-by-reference.WarnOnLargeObjects: 'false' + readability-identifier-length.IgnoredLoopCounterNames: '^[ijk_]$' + cert-dcl37-c.Invert: 'false' + altera-single-work-item-barrier.AOCVersion: '1600' + cppcoreguidelines-avoid-do-while.IgnoreMacros: 'false' + modernize-raw-string-literal.ReplaceShorterLiterals: 'false' + fuchsia-header-anon-namespaces.HeaderFileExtensions: ';h;hh;hpp;hxx' + readability-magic-numbers.IgnoredIntegerValues: '1;2;3;4;' + modernize-use-auto.RemoveStars: 'false' + abseil-string-find-str-contains.IncludeStyle: llvm + bugprone-implicit-widening-of-multiplication-result.IncludeStyle: llvm + llvmlibc-restrict-system-libc-headers.Includes: '-*' + hicpp-use-nullptr.NullMacros: '' + readability-redundant-member-init.IgnoreBaseInCopyConstructors: 'false' + modernize-replace-disallow-copy-and-assign-macro.MacroName: DISALLOW_COPY_AND_ASSIGN + performance-unnecessary-value-param.IncludeStyle: llvm + llvm-else-after-return.WarnOnUnfixable: 'false' + cert-msc32-c.DisallowedSeedTypes: 'time_t,std::time_t' +... \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index e3afc99..d938626 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,3 +111,10 @@ configure_file(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) + +# Clang tidy +add_custom_target(clang-tidy-check + clang-tidy -p ${CMAKE_BINARY_DIR}/compile_commands.json -checks=* -dump-config -checks=*,-clang-analyzer-alpha.*,-llvm-include-order ${SOURCE_FILES} ${HEADER_FILES} + # clang-tidy -p ${CMAKE_BINARY_DIR}/compile_commands.json -checks=* -dump-config${SOURCE_FILES} ${HEADER_FILES} + DEPENDS ${SOURCE_FILES} ${HEADER_FILES} + ) \ No newline at end of file From 772663d2b1ee2988696b97fe854986312ab75ebb Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Thu, 1 Feb 2024 22:18:53 -0500 Subject: [PATCH 04/47] fixing clang tidy to not contain warnings from checks we don't want. Should be basic ones Need to clean up the warnings still --- .clang-tidy | 368 ------------------------------------------------- CMakeLists.txt | 4 +- 2 files changed, 2 insertions(+), 370 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 45b0537..e69de29 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,368 +0,0 @@ ---- -Checks: 'clang-diagnostic-*,clang-analyzer-*,*,-clang-analyzer-alpha.*,-llvm-include-order' -WarningsAsErrors: '' -HeaderFilterRegex: '' -AnalyzeTemporaryDtors: false -FormatStyle: none -User: dwag -CheckOptions: - hicpp-move-const-arg.CheckMoveToConstRef: 'true' - readability-suspicious-call-argument.PrefixSimilarAbove: '30' - cppcoreguidelines-no-malloc.Reallocations: '::realloc' - portability-simd-intrinsics.Std: '' - cppcoreguidelines-owning-memory.LegacyResourceConsumers: '::free;::realloc;::freopen;::fclose' - bugprone-reserved-identifier.Invert: 'false' - cert-dcl16-c.IgnoreMacros: 'true' - bugprone-narrowing-conversions.PedanticMode: 'false' - altera-struct-pack-align.MaxConfiguredAlignment: '128' - bugprone-unused-return-value.CheckedFunctions: '::std::async;::std::launder;::std::remove;::std::remove_if;::std::unique;::std::unique_ptr::release;::std::basic_string::empty;::std::vector::empty;::std::back_inserter;::std::distance;::std::find;::std::find_if;::std::inserter;::std::lower_bound;::std::make_pair;::std::map::count;::std::map::find;::std::map::lower_bound;::std::multimap::equal_range;::std::multimap::upper_bound;::std::set::count;::std::set::find;::std::setfill;::std::setprecision;::std::setw;::std::upper_bound;::std::vector::at;::bsearch;::ferror;::feof;::isalnum;::isalpha;::isblank;::iscntrl;::isdigit;::isgraph;::islower;::isprint;::ispunct;::isspace;::isupper;::iswalnum;::iswprint;::iswspace;::isxdigit;::memchr;::memcmp;::strcmp;::strcoll;::strncmp;::strpbrk;::strrchr;::strspn;::strstr;::wcscmp;::access;::bind;::connect;::difftime;::dlsym;::fnmatch;::getaddrinfo;::getopt;::htonl;::htons;::iconv_open;::inet_addr;::isascii;::isatty;::mmap;::newlocale;::openat;::pathconf;::pthread_equal;::pthread_getspecific;::pthread_mutex_trylock;::readdir;::readlink;::recvmsg;::regexec;::scandir;::semget;::setjmp;::shm_open;::shmget;::sigismember;::strcasecmp;::strsignal;::ttyname' - modernize-use-auto.MinTypeNameLength: '5' - cert-dcl51-cpp.AggressiveDependentMemberLookup: 'false' - hicpp-use-auto.MinTypeNameLength: '5' - readability-inconsistent-declaration-parameter-name.Strict: 'false' - hicpp-use-override.IgnoreDestructors: 'false' - cppcoreguidelines-macro-usage.CheckCapsOnly: 'false' - readability-suspicious-call-argument.DiceDissimilarBelow: '60' - cert-dcl37-c.AllowedIdentifiers: '' - performance-inefficient-vector-operation.VectorLikeClasses: '::std::vector' - hicpp-use-emplace.SmartPointers: '::std::shared_ptr;::std::unique_ptr;::std::auto_ptr;::std::weak_ptr' - bugprone-assert-side-effect.IgnoredFunctions: __builtin_expect - hicpp-member-init.IgnoreArrays: 'false' - openmp-exception-escape.IgnoredExceptions: '' - readability-suspicious-call-argument.Equality: 'true' - hicpp-use-override.AllowOverrideAndFinal: 'false' - misc-uniqueptr-reset-release.IncludeStyle: llvm - abseil-string-find-str-contains.StringLikeClasses: '::std::basic_string;::std::basic_string_view;::absl::string_view' - readability-const-return-type.IgnoreMacros: 'true' - hicpp-signed-bitwise.IgnorePositiveIntegerLiterals: 'false' - bugprone-easily-swappable-parameters.QualifiersMix: 'false' - cert-err09-cpp.WarnOnLargeObjects: 'false' - bugprone-suspicious-string-compare.WarnOnImplicitComparison: 'true' - bugprone-argument-comment.CommentNullPtrs: '0' - android-comparison-in-temp-failure-retry.RetryMacros: TEMP_FAILURE_RETRY - cppcoreguidelines-narrowing-conversions.WarnOnFloatingPointNarrowingConversion: 'true' - hicpp-use-equals-delete.IgnoreMacros: 'true' - cppcoreguidelines-init-variables.IncludeStyle: llvm - modernize-use-nodiscard.ReplacementString: '[[nodiscard]]' - modernize-loop-convert.MakeReverseRangeHeader: '' - readability-avoid-const-params-in-decls.IgnoreMacros: 'true' - readability-suspicious-call-argument.SuffixSimilarAbove: '30' - misc-definitions-in-headers.HeaderFileExtensions: ';h;hh;hpp;hxx' - hicpp-uppercase-literal-suffix.NewSuffixes: '' - modernize-use-emplace.ContainersWithPush: '::std::stack;::std::queue;::std::priority_queue' - cppcoreguidelines-narrowing-conversions.WarnOnIntegerNarrowingConversion: 'true' - bugprone-easily-swappable-parameters.IgnoredParameterNames: '"";iterator;Iterator;begin;Begin;end;End;first;First;last;Last;lhs;LHS;rhs;RHS' - modernize-loop-convert.UseCxx20ReverseRanges: 'true' - cppcoreguidelines-prefer-member-initializer.UseAssignment: 'false' - hicpp-function-size.VariableThreshold: '4294967295' - cert-oop57-cpp.MemSetNames: '' - hicpp-no-malloc.Deallocations: '::free' - performance-type-promotion-in-math-fn.IncludeStyle: llvm - google-readability-function-size.LineThreshold: '4294967295' - readability-function-cognitive-complexity.DescribeBasicIncrements: 'true' - bugprone-suspicious-include.ImplementationFileExtensions: 'c;cc;cpp;cxx' - hicpp-use-emplace.ContainersWithPushFront: '::std::forward_list;::std::list;::std::deque' - modernize-loop-convert.MakeReverseRangeFunction: '' - readability-inconsistent-declaration-parameter-name.IgnoreMacros: 'true' - bugprone-suspicious-missing-comma.SizeThreshold: '5' - readability-identifier-naming.IgnoreFailedSplit: 'false' - hicpp-multiway-paths-covered.WarnOnMissingElse: 'false' - readability-qualified-auto.AddConstToQualified: 'true' - bugprone-sizeof-expression.WarnOnSizeOfThis: 'true' - bugprone-string-constructor.WarnOnLargeLength: 'true' - cppcoreguidelines-explicit-virtual-functions.OverrideSpelling: override - hicpp-no-malloc.Allocations: '::malloc;::calloc' - hicpp-use-noexcept.UseNoexceptFalse: 'true' - abseil-string-find-startswith.IncludeStyle: llvm - google-global-names-in-headers.HeaderFileExtensions: ';h;hh;hpp;hxx' - readability-uppercase-literal-suffix.IgnoreMacros: 'true' - modernize-make-shared.IgnoreMacros: 'true' - modernize-use-emplace.ContainersWithPushFront: '::std::forward_list;::std::list;::std::deque' - misc-const-correctness.TransformValues: 'true' - cert-dcl59-cpp.HeaderFileExtensions: ';h;hh;hpp;hxx' - bugprone-suspicious-enum-usage.StrictMode: 'false' - performance-unnecessary-copy-initialization.AllowedTypes: '' - bugprone-suspicious-missing-comma.MaxConcatenatedTokens: '5' - modernize-use-transparent-functors.SafeMode: 'false' - readability-suspicious-call-argument.Levenshtein: 'true' - bugprone-not-null-terminated-result.WantToUseSafeFunctions: 'true' - misc-throw-by-value-catch-by-reference.CheckThrowTemporaries: 'true' - bugprone-string-constructor.LargeLengthThreshold: '8388608' - bugprone-dynamic-static-initializers.HeaderFileExtensions: ';h;hh;hpp;hxx' - readability-simplify-boolean-expr.ChainedConditionalAssignment: 'false' - cppcoreguidelines-avoid-magic-numbers.IgnoreAllFloatingPointValues: 'false' - cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField: 'false' - cert-err09-cpp.CheckThrowTemporaries: 'true' - performance-inefficient-vector-operation.EnableProto: 'false' - bugprone-exception-escape.FunctionsThatShouldNotThrow: '' - modernize-loop-convert.MaxCopySize: '16' - readability-suspicious-call-argument.PrefixDissimilarBelow: '25' - readability-function-size.LineThreshold: '4294967295' - bugprone-easily-swappable-parameters.MinimumLength: '2' - portability-simd-intrinsics.Suggest: 'false' - hicpp-deprecated-headers.CheckHeaderFile: 'false' - modernize-use-override.IgnoreDestructors: 'false' - cppcoreguidelines-pro-bounds-constant-array-index.GslHeader: '' - modernize-make-shared.MakeSmartPtrFunctionHeader: '' - modernize-make-shared.MakeSmartPtrFunction: 'std::make_shared' - misc-non-private-member-variables-in-classes.IgnorePublicMemberVariables: 'false' - bugprone-sizeof-expression.WarnOnSizeOfConstant: 'true' - readability-redundant-string-init.StringNames: '::std::basic_string_view;::std::basic_string' - modernize-make-unique.IgnoreDefaultInitialization: 'true' - modernize-use-emplace.ContainersWithPushBack: '::std::vector;::std::list;::std::deque' - readability-magic-numbers.IgnoreBitFieldsWidths: 'true' - modernize-make-unique.IncludeStyle: llvm - modernize-use-override.OverrideSpelling: override - google-readability-function-size.NestingThreshold: '4294967295' - google-build-namespaces.HeaderFileExtensions: ';h;hh;hpp;hxx' - readability-suspicious-call-argument.LevenshteinDissimilarBelow: '50' - bugprone-argument-comment.CommentStringLiterals: '0' - concurrency-mt-unsafe.FunctionSet: any - readability-identifier-length.IgnoredExceptionVariableNames: '^[e]$' - google-readability-braces-around-statements.ShortStatementLines: '1' - bugprone-reserved-identifier.AllowedIdentifiers: '' - cppcoreguidelines-pro-type-member-init.IgnoreArrays: 'false' - readability-else-after-return.WarnOnUnfixable: 'true' - cppcoreguidelines-avoid-magic-numbers.IgnoredFloatingPointValues: '1.0;100.0;' - modernize-use-emplace.IgnoreImplicitConstructors: 'false' - cppcoreguidelines-macro-usage.IgnoreCommandLineMacros: 'true' - readability-suspicious-call-argument.Substring: 'true' - modernize-use-equals-delete.IgnoreMacros: 'true' - objc-forbidden-subclassing.ForbiddenSuperClassNames: 'ABNewPersonViewController;ABPeoplePickerNavigationController;ABPersonViewController;ABUnknownPersonViewController;NSHashTable;NSMapTable;NSPointerArray;NSPointerFunctions;NSTimer;UIActionSheet;UIAlertView;UIImagePickerController;UITextInputMode;UIWebView' - readability-identifier-length.IgnoredVariableNames: '' - readability-magic-numbers.IgnoreAllFloatingPointValues: 'false' - cppcoreguidelines-pro-bounds-constant-array-index.IncludeStyle: llvm - hicpp-use-auto.RemoveStars: 'false' - readability-suspicious-call-argument.Abbreviations: 'arr=array;cnt=count;idx=index;src=source;stmt=statement;cpy=copy;dest=destination;dist=distancedst=distance;ptr=pointer;wdth=width;str=string;ln=line;srv=server;attr=attribute;ref=reference;buf=buffer;col=column;nr=number;vec=vector;len=length;elem=element;val=value;i=index;var=variable;hght=height;cl=client;num=number;pos=position;lst=list;addr=address' - bugprone-misplaced-widening-cast.CheckImplicitCasts: 'false' - readability-uppercase-literal-suffix.NewSuffixes: '' - modernize-loop-convert.MinConfidence: reasonable - performance-unnecessary-value-param.AllowedTypes: '' - readability-uniqueptr-delete-release.PreferResetCall: 'false' - readability-identifier-length.MinimumExceptionNameLength: '2' - misc-definitions-in-headers.UseHeaderFileExtension: 'true' - google-readability-namespace-comments.SpacesBeforeComments: '2' - cppcoreguidelines-avoid-magic-numbers.IgnoreBitFieldsWidths: 'true' - cert-err61-cpp.CheckThrowTemporaries: 'true' - cppcoreguidelines-avoid-magic-numbers.IgnoredIntegerValues: '1;2;3;4;' - cppcoreguidelines-no-malloc.Allocations: '::malloc;::calloc' - misc-throw-by-value-catch-by-reference.MaxSize: '-1' - cppcoreguidelines-avoid-magic-numbers.IgnorePowersOf2IntegerValues: 'false' - bugprone-narrowing-conversions.IgnoreConversionFromTypes: '' - readability-function-size.BranchThreshold: '4294967295' - bugprone-suspicious-missing-comma.RatioThreshold: '0.200000' - hicpp-function-size.LineThreshold: '4294967295' - readability-implicit-bool-conversion.AllowIntegerConditions: 'false' - readability-identifier-length.IgnoredParameterNames: '^[n]$' - readability-function-size.StatementThreshold: '800' - hicpp-use-noexcept.ReplacementString: '' - readability-identifier-naming.IgnoreMainLikeFunctions: 'false' - cppcoreguidelines-init-variables.MathHeader: '' - google-runtime-int.SignedTypePrefix: int - google-readability-function-size.StatementThreshold: '800' - cert-msc51-cpp.DisallowedSeedTypes: 'time_t,std::time_t' - hicpp-use-emplace.TupleMakeFunctions: '::std::make_pair;::std::make_tuple' - bugprone-reserved-identifier.AggressiveDependentMemberLookup: 'false' - readability-suspicious-call-argument.DiceSimilarAbove: '70' - modernize-use-equals-default.IgnoreMacros: 'true' - readability-suspicious-call-argument.Abbreviation: 'true' - cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor: 'false' - cert-dcl37-c.AggressiveDependentMemberLookup: 'false' - readability-identifier-length.MinimumLoopCounterNameLength: '2' - abseil-string-find-str-contains.AbseilStringsMatchHeader: 'absl/strings/match.h' - bugprone-dangling-handle.HandleClasses: 'std::basic_string_view;std::experimental::basic_string_view' - cert-msc54-cpp.AsyncSafeFunctionSet: POSIX - modernize-use-emplace.SmartPointers: '::std::shared_ptr;::std::unique_ptr;::std::auto_ptr;::std::weak_ptr' - readability-magic-numbers.IgnorePowersOf2IntegerValues: 'false' - misc-const-correctness.TransformPointersAsValues: 'false' - readability-suspicious-call-argument.JaroWinklerSimilarAbove: '85' - misc-unused-parameters.StrictMode: 'false' - cppcoreguidelines-no-malloc.Deallocations: '::free' - readability-simplify-subscript-expr.Types: '::std::basic_string;::std::basic_string_view;::std::vector;::std::array' - performance-unnecessary-copy-initialization.ExcludedContainerTypes: '' - modernize-replace-auto-ptr.IncludeStyle: llvm - performance-move-const-arg.CheckTriviallyCopyableMove: 'true' - misc-const-correctness.TransformReferences: 'true' - hicpp-move-const-arg.CheckTriviallyCopyableMove: 'true' - readability-function-size.VariableThreshold: '4294967295' - readability-static-accessed-through-instance.NameSpecifierNestingThreshold: '3' - cert-dcl16-c.NewSuffixes: 'L;LL;LU;LLU' - misc-const-correctness.AnalyzeValues: 'true' - readability-identifier-naming.GetConfigPerFile: 'true' - bugprone-narrowing-conversions.WarnOnFloatingPointNarrowingConversion: 'true' - cert-sig30-c.AsyncSafeFunctionSet: POSIX - readability-simplify-boolean-expr.SimplifyDeMorgan: 'true' - cert-err61-cpp.MaxSize: '-1' - hicpp-member-init.UseAssignment: 'false' - modernize-use-default-member-init.UseAssignment: 'false' - readability-function-size.NestingThreshold: '4294967295' - google-readability-function-size.BranchThreshold: '4294967295' - bugprone-sizeof-expression.WarnOnSizeOfPointerToAggregate: 'true' - llvm-namespace-comment.ShortNamespaceLines: '1' - llvm-namespace-comment.SpacesBeforeComments: '1' - modernize-use-override.AllowOverrideAndFinal: 'false' - cppcoreguidelines-narrowing-conversions.IgnoreConversionFromTypes: '' - readability-function-size.ParameterThreshold: '4294967295' - hicpp-function-size.NestingThreshold: '4294967295' - modernize-pass-by-value.ValuesOnly: 'false' - readability-function-cognitive-complexity.IgnoreMacros: 'false' - modernize-loop-convert.IncludeStyle: llvm - cert-str34-c.DiagnoseSignedUnsignedCharComparisons: 'false' - bugprone-narrowing-conversions.WarnWithinTemplateInstantiation: 'false' - cert-err33-c.CheckedFunctions: '::aligned_alloc;::asctime_s;::at_quick_exit;::atexit;::bsearch;::bsearch_s;::btowc;::c16rtomb;::c32rtomb;::calloc;::clock;::cnd_broadcast;::cnd_init;::cnd_signal;::cnd_timedwait;::cnd_wait;::ctime_s;::fclose;::fflush;::fgetc;::fgetpos;::fgets;::fgetwc;::fopen;::fopen_s;::fprintf;::fprintf_s;::fputc;::fputs;::fputwc;::fputws;::fread;::freopen;::freopen_s;::fscanf;::fscanf_s;::fseek;::fsetpos;::ftell;::fwprintf;::fwprintf_s;::fwrite;::fwscanf;::fwscanf_s;::getc;::getchar;::getenv;::getenv_s;::gets_s;::getwc;::getwchar;::gmtime;::gmtime_s;::localtime;::localtime_s;::malloc;::mbrtoc16;::mbrtoc32;::mbsrtowcs;::mbsrtowcs_s;::mbstowcs;::mbstowcs_s;::memchr;::mktime;::mtx_init;::mtx_lock;::mtx_timedlock;::mtx_trylock;::mtx_unlock;::printf_s;::putc;::putwc;::raise;::realloc;::remove;::rename;::scanf;::scanf_s;::setlocale;::setvbuf;::signal;::snprintf;::snprintf_s;::sprintf;::sprintf_s;::sscanf;::sscanf_s;::strchr;::strerror_s;::strftime;::strpbrk;::strrchr;::strstr;::strtod;::strtof;::strtoimax;::strtok;::strtok_s;::strtol;::strtold;::strtoll;::strtoul;::strtoull;::strtoumax;::strxfrm;::swprintf;::swprintf_s;::swscanf;::swscanf_s;::thrd_create;::thrd_detach;::thrd_join;::thrd_sleep;::time;::timespec_get;::tmpfile;::tmpfile_s;::tmpnam;::tmpnam_s;::tss_create;::tss_get;::tss_set;::ungetc;::ungetwc;::vfprintf;::vfprintf_s;::vfscanf;::vfscanf_s;::vfwprintf;::vfwprintf_s;::vfwscanf;::vfwscanf_s;::vprintf_s;::vscanf;::vscanf_s;::vsnprintf;::vsnprintf_s;::vsprintf;::vsprintf_s;::vsscanf;::vsscanf_s;::vswprintf;::vswprintf_s;::vswscanf;::vswscanf_s;::vwprintf_s;::vwscanf;::vwscanf_s;::wcrtomb;::wcschr;::wcsftime;::wcspbrk;::wcsrchr;::wcsrtombs;::wcsrtombs_s;::wcsstr;::wcstod;::wcstof;::wcstoimax;::wcstok;::wcstok_s;::wcstol;::wcstold;::wcstoll;::wcstombs;::wcstombs_s;::wcstoul;::wcstoull;::wcstoumax;::wcsxfrm;::wctob;::wctrans;::wctype;::wmemchr;::wprintf_s;::wscanf;::wscanf_s;' - bugprone-suspicious-string-compare.WarnOnLogicalNotComparison: 'false' - hicpp-braces-around-statements.ShortStatementLines: '0' - cppcoreguidelines-explicit-virtual-functions.AllowOverrideAndFinal: 'false' - google-readability-function-size.ParameterThreshold: '4294967295' - readability-redundant-smartptr-get.IgnoreMacros: 'true' - readability-identifier-naming.AggressiveDependentMemberLookup: 'false' - cert-err61-cpp.WarnOnLargeObjects: 'false' - misc-const-correctness.WarnPointersAsValues: 'false' - readability-identifier-length.MinimumParameterNameLength: '3' - modernize-use-emplace.TupleTypes: '::std::pair;::std::tuple' - hicpp-use-emplace.IgnoreImplicitConstructors: 'false' - modernize-use-emplace.TupleMakeFunctions: '::std::make_pair;::std::make_tuple' - bugprone-narrowing-conversions.WarnOnIntegerToFloatingPointNarrowingConversion: 'true' - cppcoreguidelines-owning-memory.LegacyResourceProducers: '::malloc;::aligned_alloc;::realloc;::calloc;::fopen;::freopen;::tmpfile' - bugprone-easily-swappable-parameters.SuppressParametersUsedTogether: 'true' - bugprone-argument-comment.StrictMode: '0' - hicpp-uppercase-literal-suffix.IgnoreMacros: 'true' - misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic: 'false' - modernize-replace-random-shuffle.IncludeStyle: llvm - modernize-use-bool-literals.IgnoreMacros: 'true' - bugprone-easily-swappable-parameters.NamePrefixSuffixSilenceDissimilarityTreshold: '1' - bugprone-unhandled-self-assignment.WarnOnlyIfThisHasSuspiciousField: 'true' - google-readability-namespace-comments.ShortNamespaceLines: '10' - readability-suspicious-call-argument.JaroWinklerDissimilarBelow: '75' - bugprone-suspicious-string-compare.StringCompareLikeFunctions: '' - modernize-avoid-bind.PermissiveParameterList: 'false' - readability-suspicious-call-argument.Suffix: 'true' - cert-err09-cpp.MaxSize: '-1' - modernize-use-override.FinalSpelling: final - hicpp-use-equals-default.IgnoreMacros: 'true' - modernize-use-noexcept.ReplacementString: '' - hicpp-use-override.OverrideSpelling: override - modernize-use-using.IgnoreMacros: 'true' - hicpp-use-override.FinalSpelling: final - cppcoreguidelines-explicit-virtual-functions.FinalSpelling: final - readability-suspicious-call-argument.MinimumIdentifierNameLength: '3' - bugprone-narrowing-conversions.WarnOnIntegerNarrowingConversion: 'true' - modernize-loop-convert.NamingStyle: CamelCase - cppcoreguidelines-pro-type-member-init.UseAssignment: 'false' - bugprone-suspicious-include.HeaderFileExtensions: ';h;hh;hpp;hxx' - hicpp-function-size.StatementThreshold: '800' - readability-suspicious-call-argument.SubstringDissimilarBelow: '40' - hicpp-no-malloc.Reallocations: '::realloc' - bugprone-stringview-nullptr.IncludeStyle: llvm - performance-for-range-copy.WarnOnAllAutoCopies: 'false' - google-runtime-int.UnsignedTypePrefix: uint - performance-no-automatic-move.AllowedTypes: '' - modernize-pass-by-value.IncludeStyle: llvm - bugprone-argument-comment.CommentIntegerLiterals: '0' - bugprone-argument-comment.CommentFloatLiterals: '0' - bugprone-too-small-loop-variable.MagnitudeBitsUpperLimit: '16' - abseil-string-find-startswith.AbseilStringsMatchHeader: 'absl/strings/match.h' - readability-simplify-boolean-expr.ChainedConditionalReturn: 'false' - readability-else-after-return.WarnOnConditionVariables: 'true' - modernize-use-nullptr.NullMacros: 'NULL' - readability-suspicious-call-argument.SuffixDissimilarBelow: '25' - bugprone-argument-comment.CommentCharacterLiterals: '0' - cppcoreguidelines-macro-usage.AllowedRegexp: '^DEBUG_*' - llvm-header-guard.HeaderFileExtensions: ';h;hh;hpp;hxx' - readability-suspicious-call-argument.LevenshteinSimilarAbove: '66' - cppcoreguidelines-narrowing-conversions.PedanticMode: 'false' - modernize-make-shared.IgnoreDefaultInitialization: 'true' - readability-suspicious-call-argument.JaroWinkler: 'true' - bugprone-implicit-widening-of-multiplication-result.UseCXXHeadersInCppSources: 'true' - modernize-make-shared.IncludeStyle: llvm - readability-suspicious-call-argument.Prefix: 'true' - hicpp-special-member-functions.AllowMissingMoveFunctions: 'false' - cppcoreguidelines-special-member-functions.AllowMissingMoveFunctions: 'false' - bugprone-implicit-widening-of-multiplication-result.UseCXXStaticCastsInCppSources: 'true' - bugprone-signed-char-misuse.CharTypdefsToIgnore: '' - cert-dcl51-cpp.Invert: 'false' - hicpp-special-member-functions.AllowSoleDefaultDtor: 'false' - modernize-deprecated-headers.CheckHeaderFile: 'false' - hicpp-use-emplace.EmplacyFunctions: 'vector::emplace_back;vector::emplace;deque::emplace;deque::emplace_front;deque::emplace_back;forward_list::emplace_after;forward_list::emplace_front;list::emplace;list::emplace_back;list::emplace_front;set::emplace;set::emplace_hint;map::emplace;map::emplace_hint;multiset::emplace;multiset::emplace_hint;multimap::emplace;multimap::emplace_hint;unordered_set::emplace;unordered_set::emplace_hint;unordered_map::emplace;unordered_map::emplace_hint;unordered_multiset::emplace;unordered_multiset::emplace_hint;unordered_multimap::emplace;unordered_multimap::emplace_hint;stack::emplace;queue::emplace;priority_queue::emplace' - cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors: 'false' - modernize-make-unique.IgnoreMacros: 'true' - performance-for-range-copy.AllowedTypes: '' - hicpp-function-size.BranchThreshold: '4294967295' - misc-const-correctness.AnalyzeReferences: 'true' - bugprone-unchecked-optional-access.IgnoreSmartPointerDereference: 'false' - bugprone-argument-comment.CommentBoolLiterals: '0' - readability-braces-around-statements.ShortStatementLines: '0' - bugprone-argument-comment.CommentUserDefinedLiterals: '0' - hicpp-use-emplace.ContainersWithPushBack: '::std::vector;::std::list;::std::deque' - abseil-string-find-startswith.StringLikeClasses: '::std::basic_string' - hicpp-special-member-functions.AllowMissingMoveFunctionsWhenCopyIsDeleted: 'false' - performance-inefficient-string-concatenation.StrictMode: 'false' - readability-redundant-declaration.IgnoreMacros: 'true' - readability-magic-numbers.IgnoredFloatingPointValues: '1.0;100.0;' - bugprone-easily-swappable-parameters.IgnoredParameterTypeSuffixes: 'bool;Bool;_Bool;it;It;iterator;Iterator;inputit;InputIt;forwardit;ForwardIt;bidirit;BidirIt;constiterator;const_iterator;Const_Iterator;Constiterator;ConstIterator;RandomIt;randomit;random_iterator;ReverseIt;reverse_iterator;reverse_const_iterator;ConstReverseIterator;Const_Reverse_Iterator;const_reverse_iterator;Constreverseiterator;constreverseiterator' - modernize-make-unique.MakeSmartPtrFunction: 'std::make_unique' - google-runtime-int.TypeSuffix: '' - hicpp-function-size.ParameterThreshold: '4294967295' - cert-dcl51-cpp.AllowedIdentifiers: '' - abseil-cleanup-ctad.IncludeStyle: llvm - cert-oop57-cpp.MemCpyNames: '' - modernize-make-unique.MakeSmartPtrFunctionHeader: '' - bugprone-signal-handler.AsyncSafeFunctionSet: POSIX - bugprone-easily-swappable-parameters.ModelImplicitConversions: 'true' - readability-suspicious-call-argument.SubstringSimilarAbove: '50' - cppcoreguidelines-narrowing-conversions.WarnWithinTemplateInstantiation: 'false' - portability-restrict-system-includes.Includes: '*' - performance-move-const-arg.CheckMoveToConstRef: 'true' - readability-identifier-length.MinimumVariableNameLength: '3' - modernize-use-emplace.EmplacyFunctions: 'vector::emplace_back;vector::emplace;deque::emplace;deque::emplace_front;deque::emplace_back;forward_list::emplace_after;forward_list::emplace_front;list::emplace;list::emplace_back;list::emplace_front;set::emplace;set::emplace_hint;map::emplace;map::emplace_hint;multiset::emplace;multiset::emplace_hint;multimap::emplace;multimap::emplace_hint;unordered_set::emplace;unordered_set::emplace_hint;unordered_map::emplace;unordered_map::emplace_hint;unordered_multiset::emplace;unordered_multiset::emplace_hint;unordered_multimap::emplace;unordered_multimap::emplace_hint;stack::emplace;queue::emplace;priority_queue::emplace' - zircon-temporary-objects.Names: '' - cppcoreguidelines-narrowing-conversions.WarnOnEquivalentBitWidth: 'true' - hicpp-use-emplace.TupleTypes: '::std::pair;::std::tuple' - cppcoreguidelines-non-private-member-variables-in-classes.IgnorePublicMemberVariables: 'false' - readability-implicit-bool-conversion.AllowPointerConditions: 'false' - cppcoreguidelines-special-member-functions.AllowMissingMoveFunctionsWhenCopyIsDeleted: 'false' - cert-oop57-cpp.MemCmpNames: '' - modernize-use-noexcept.UseNoexceptFalse: 'true' - readability-function-cognitive-complexity.Threshold: '25' - cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic: 'true' - readability-simplify-boolean-expr.SimplifyDeMorganRelaxed: 'false' - bugprone-narrowing-conversions.WarnOnEquivalentBitWidth: 'true' - bugprone-sizeof-expression.WarnOnSizeOfIntegerExpression: 'false' - performance-faster-string-find.StringLikeClasses: '::std::basic_string;::std::basic_string_view' - cppcoreguidelines-narrowing-conversions.WarnOnIntegerToFloatingPointNarrowingConversion: 'true' - google-readability-function-size.VariableThreshold: '4294967295' - bugprone-assert-side-effect.CheckFunctionCalls: 'false' - bugprone-string-constructor.StringNames: '::std::basic_string;::std::basic_string_view' - bugprone-assert-side-effect.AssertMacros: assert,NSAssert,NSCAssert - bugprone-exception-escape.IgnoredExceptions: '' - bugprone-signed-char-misuse.DiagnoseSignedUnsignedCharComparisons: 'true' - altera-unroll-loops.MaxLoopIterations: '100' - llvm-qualified-auto.AddConstToQualified: 'false' - hicpp-use-emplace.ContainersWithPush: '::std::stack;::std::queue;::std::priority_queue' - modernize-use-default-member-init.IgnoreMacros: 'true' - cert-str34-c.CharTypdefsToIgnore: '' - misc-use-anonymous-namespace.HeaderFileExtensions: ';h;hh;hpp;hxx' - llvm-else-after-return.WarnOnConditionVariables: 'false' - bugprone-sizeof-expression.WarnOnSizeOfCompareToConstant: 'true' - bugprone-argument-comment.IgnoreSingleArgument: '0' - modernize-raw-string-literal.DelimiterStem: lit - readability-suspicious-call-argument.Dice: 'true' - misc-throw-by-value-catch-by-reference.WarnOnLargeObjects: 'false' - readability-identifier-length.IgnoredLoopCounterNames: '^[ijk_]$' - cert-dcl37-c.Invert: 'false' - altera-single-work-item-barrier.AOCVersion: '1600' - cppcoreguidelines-avoid-do-while.IgnoreMacros: 'false' - modernize-raw-string-literal.ReplaceShorterLiterals: 'false' - fuchsia-header-anon-namespaces.HeaderFileExtensions: ';h;hh;hpp;hxx' - readability-magic-numbers.IgnoredIntegerValues: '1;2;3;4;' - modernize-use-auto.RemoveStars: 'false' - abseil-string-find-str-contains.IncludeStyle: llvm - bugprone-implicit-widening-of-multiplication-result.IncludeStyle: llvm - llvmlibc-restrict-system-libc-headers.Includes: '-*' - hicpp-use-nullptr.NullMacros: '' - readability-redundant-member-init.IgnoreBaseInCopyConstructors: 'false' - modernize-replace-disallow-copy-and-assign-macro.MacroName: DISALLOW_COPY_AND_ASSIGN - performance-unnecessary-value-param.IncludeStyle: llvm - llvm-else-after-return.WarnOnUnfixable: 'false' - cert-msc32-c.DisallowedSeedTypes: 'time_t,std::time_t' -... \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index d938626..c973386 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,7 +114,7 @@ install( # Clang tidy add_custom_target(clang-tidy-check - clang-tidy -p ${CMAKE_BINARY_DIR}/compile_commands.json -checks=* -dump-config -checks=*,-clang-analyzer-alpha.*,-llvm-include-order ${SOURCE_FILES} ${HEADER_FILES} - # clang-tidy -p ${CMAKE_BINARY_DIR}/compile_commands.json -checks=* -dump-config${SOURCE_FILES} ${HEADER_FILES} + # clang-tidy -checks=-*,clang-analyzer-*,clang-analyzer-cplusplus*,cert-*,cppcoreguidelines-*,portability-*,readability-*,clang-diagnostic-* -dump-config -p ${CMAKE_BINARY_DIR}/compile_commands.json ${SOURCE_FILES} ${HEADER_FILES} > ../.clang-tidy + clang-tidy -p ${CMAKE_BINARY_DIR}/compile_commands.json ${SOURCE_FILES} ${HEADER_FILES} DEPENDS ${SOURCE_FILES} ${HEADER_FILES} ) \ No newline at end of file From 806832c3a27e044c6893199ada9c80a6a52bb212 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Thu, 1 Feb 2024 22:24:06 -0500 Subject: [PATCH 05/47] Updated the clang format file one more time and added commands to dump the clang-tidy file with current checks and run the fixes --- .clang-tidy | 160 +++++++++++++++++++++++++++++++++++++++++++++++++ CMakeLists.txt | 13 +++- 2 files changed, 171 insertions(+), 2 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index e69de29..cc7ef80 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -0,0 +1,160 @@ +--- +Checks: 'clang-diagnostic-*,clang-analyzer-*,-*,clang-analyzer-*,clang-analyzer-cplusplus*,cert-*,cppcoreguidelines-*,portability-*,readability-*,clang-diagnostic-*' +WarningsAsErrors: '' +HeaderFilterRegex: '' +AnalyzeTemporaryDtors: false +FormatStyle: none +User: dwag +CheckOptions: + readability-simplify-subscript-expr.Types: '::std::basic_string;::std::basic_string_view;::std::vector;::std::array' + readability-suspicious-call-argument.PrefixSimilarAbove: '30' + modernize-replace-auto-ptr.IncludeStyle: llvm + cppcoreguidelines-no-malloc.Reallocations: '::realloc' + cppcoreguidelines-owning-memory.LegacyResourceConsumers: '::free;::realloc;::freopen;::fclose' + readability-static-accessed-through-instance.NameSpecifierNestingThreshold: '3' + readability-simplify-boolean-expr.SimplifyDeMorgan: 'true' + readability-function-size.VariableThreshold: '4294967295' + cert-dcl16-c.NewSuffixes: 'L;LL;LU;LLU' + cert-dcl51-cpp.AggressiveDependentMemberLookup: 'false' + readability-identifier-naming.GetConfigPerFile: 'true' + cert-err61-cpp.MaxSize: '-1' + cert-sig30-c.AsyncSafeFunctionSet: POSIX + readability-inconsistent-declaration-parameter-name.Strict: 'false' + cppcoreguidelines-macro-usage.CheckCapsOnly: 'false' + readability-suspicious-call-argument.DiceDissimilarBelow: '60' + cert-dcl37-c.AllowedIdentifiers: '' + readability-function-size.NestingThreshold: '4294967295' + cppcoreguidelines-narrowing-conversions.IgnoreConversionFromTypes: '' + readability-function-size.ParameterThreshold: '4294967295' + readability-suspicious-call-argument.Equality: 'true' + readability-function-cognitive-complexity.IgnoreMacros: 'false' + cert-str34-c.DiagnoseSignedUnsignedCharComparisons: 'false' + cert-err33-c.CheckedFunctions: '::aligned_alloc;::asctime_s;::at_quick_exit;::atexit;::bsearch;::bsearch_s;::btowc;::c16rtomb;::c32rtomb;::calloc;::clock;::cnd_broadcast;::cnd_init;::cnd_signal;::cnd_timedwait;::cnd_wait;::ctime_s;::fclose;::fflush;::fgetc;::fgetpos;::fgets;::fgetwc;::fopen;::fopen_s;::fprintf;::fprintf_s;::fputc;::fputs;::fputwc;::fputws;::fread;::freopen;::freopen_s;::fscanf;::fscanf_s;::fseek;::fsetpos;::ftell;::fwprintf;::fwprintf_s;::fwrite;::fwscanf;::fwscanf_s;::getc;::getchar;::getenv;::getenv_s;::gets_s;::getwc;::getwchar;::gmtime;::gmtime_s;::localtime;::localtime_s;::malloc;::mbrtoc16;::mbrtoc32;::mbsrtowcs;::mbsrtowcs_s;::mbstowcs;::mbstowcs_s;::memchr;::mktime;::mtx_init;::mtx_lock;::mtx_timedlock;::mtx_trylock;::mtx_unlock;::printf_s;::putc;::putwc;::raise;::realloc;::remove;::rename;::scanf;::scanf_s;::setlocale;::setvbuf;::signal;::snprintf;::snprintf_s;::sprintf;::sprintf_s;::sscanf;::sscanf_s;::strchr;::strerror_s;::strftime;::strpbrk;::strrchr;::strstr;::strtod;::strtof;::strtoimax;::strtok;::strtok_s;::strtol;::strtold;::strtoll;::strtoul;::strtoull;::strtoumax;::strxfrm;::swprintf;::swprintf_s;::swscanf;::swscanf_s;::thrd_create;::thrd_detach;::thrd_join;::thrd_sleep;::time;::timespec_get;::tmpfile;::tmpfile_s;::tmpnam;::tmpnam_s;::tss_create;::tss_get;::tss_set;::ungetc;::ungetwc;::vfprintf;::vfprintf_s;::vfscanf;::vfscanf_s;::vfwprintf;::vfwprintf_s;::vfwscanf;::vfwscanf_s;::vprintf_s;::vscanf;::vscanf_s;::vsnprintf;::vsnprintf_s;::vsprintf;::vsprintf_s;::vsscanf;::vsscanf_s;::vswprintf;::vswprintf_s;::vswscanf;::vswscanf_s;::vwprintf_s;::vwscanf;::vwscanf_s;::wcrtomb;::wcschr;::wcsftime;::wcspbrk;::wcsrchr;::wcsrtombs;::wcsrtombs_s;::wcsstr;::wcstod;::wcstof;::wcstoimax;::wcstok;::wcstok_s;::wcstol;::wcstold;::wcstoll;::wcstombs;::wcstombs_s;::wcstoul;::wcstoull;::wcstoumax;::wcsxfrm;::wctob;::wctrans;::wctype;::wmemchr;::wprintf_s;::wscanf;::wscanf_s;' + cppcoreguidelines-explicit-virtual-functions.AllowOverrideAndFinal: 'false' + readability-redundant-smartptr-get.IgnoreMacros: 'true' + readability-identifier-naming.AggressiveDependentMemberLookup: 'false' + readability-const-return-type.IgnoreMacros: 'true' + cert-err61-cpp.WarnOnLargeObjects: 'false' + cert-err09-cpp.WarnOnLargeObjects: 'false' + readability-identifier-length.MinimumParameterNameLength: '3' + cppcoreguidelines-owning-memory.LegacyResourceProducers: '::malloc;::aligned_alloc;::realloc;::calloc;::fopen;::freopen;::tmpfile' + cppcoreguidelines-narrowing-conversions.WarnOnFloatingPointNarrowingConversion: 'true' + cppcoreguidelines-init-variables.IncludeStyle: llvm + readability-avoid-const-params-in-decls.IgnoreMacros: 'true' + google-readability-namespace-comments.ShortNamespaceLines: '10' + readability-suspicious-call-argument.JaroWinklerDissimilarBelow: '75' + readability-suspicious-call-argument.SuffixSimilarAbove: '30' + readability-suspicious-call-argument.Suffix: 'true' + cert-err09-cpp.MaxSize: '-1' + cppcoreguidelines-narrowing-conversions.WarnOnIntegerNarrowingConversion: 'true' + cppcoreguidelines-prefer-member-initializer.UseAssignment: 'false' + cert-oop57-cpp.MemSetNames: '' + cppcoreguidelines-explicit-virtual-functions.FinalSpelling: final + readability-function-cognitive-complexity.DescribeBasicIncrements: 'true' + readability-suspicious-call-argument.MinimumIdentifierNameLength: '3' + modernize-loop-convert.NamingStyle: CamelCase + cppcoreguidelines-pro-type-member-init.UseAssignment: 'false' + readability-inconsistent-declaration-parameter-name.IgnoreMacros: 'true' + readability-suspicious-call-argument.SubstringDissimilarBelow: '40' + readability-identifier-naming.IgnoreFailedSplit: 'false' + modernize-pass-by-value.IncludeStyle: llvm + readability-qualified-auto.AddConstToQualified: 'true' + cppcoreguidelines-explicit-virtual-functions.OverrideSpelling: override + readability-simplify-boolean-expr.ChainedConditionalReturn: 'false' + readability-else-after-return.WarnOnConditionVariables: 'true' + readability-uppercase-literal-suffix.IgnoreMacros: 'true' + modernize-use-nullptr.NullMacros: 'NULL' + cert-dcl59-cpp.HeaderFileExtensions: ';h;hh;hpp;hxx' + readability-suspicious-call-argument.SuffixDissimilarBelow: '25' + cppcoreguidelines-macro-usage.AllowedRegexp: '^DEBUG_*' + readability-suspicious-call-argument.LevenshteinSimilarAbove: '66' + cppcoreguidelines-narrowing-conversions.PedanticMode: 'false' + readability-suspicious-call-argument.Levenshtein: 'true' + readability-suspicious-call-argument.JaroWinkler: 'true' + readability-suspicious-call-argument.Prefix: 'true' + readability-simplify-boolean-expr.ChainedConditionalAssignment: 'false' + cppcoreguidelines-avoid-magic-numbers.IgnoreAllFloatingPointValues: 'false' + cppcoreguidelines-special-member-functions.AllowMissingMoveFunctions: 'false' + cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField: 'false' + cert-err09-cpp.CheckThrowTemporaries: 'true' + cert-dcl51-cpp.Invert: 'false' + readability-function-size.LineThreshold: '4294967295' + modernize-loop-convert.MaxCopySize: '16' + readability-suspicious-call-argument.PrefixDissimilarBelow: '25' + portability-simd-intrinsics.Suggest: 'false' + cppcoreguidelines-pro-bounds-constant-array-index.GslHeader: '' + cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors: 'false' + readability-redundant-string-init.StringNames: '::std::basic_string_view;::std::basic_string' + readability-magic-numbers.IgnoreBitFieldsWidths: 'true' + readability-braces-around-statements.ShortStatementLines: '0' + readability-suspicious-call-argument.LevenshteinDissimilarBelow: '50' + readability-magic-numbers.IgnoredFloatingPointValues: '1.0;100.0;' + readability-redundant-declaration.IgnoreMacros: 'true' + readability-implicit-bool-conversion.AllowPointerConditions: 'false' + readability-identifier-length.IgnoredExceptionVariableNames: '^[e]$' + google-readability-braces-around-statements.ShortStatementLines: '1' + portability-restrict-system-includes.Includes: '*' + cppcoreguidelines-pro-type-member-init.IgnoreArrays: 'false' + readability-else-after-return.WarnOnUnfixable: 'true' + cert-dcl51-cpp.AllowedIdentifiers: '' + cppcoreguidelines-avoid-magic-numbers.IgnoredFloatingPointValues: '1.0;100.0;' + cert-oop57-cpp.MemCpyNames: '' + readability-suspicious-call-argument.SubstringSimilarAbove: '50' + cppcoreguidelines-macro-usage.IgnoreCommandLineMacros: 'true' + readability-suspicious-call-argument.Substring: 'true' + cppcoreguidelines-pro-bounds-constant-array-index.IncludeStyle: llvm + cppcoreguidelines-narrowing-conversions.WarnWithinTemplateInstantiation: 'false' + readability-identifier-length.IgnoredVariableNames: '' + readability-magic-numbers.IgnoreAllFloatingPointValues: 'false' + readability-identifier-length.MinimumVariableNameLength: '3' + readability-suspicious-call-argument.Abbreviations: 'arr=array;cnt=count;idx=index;src=source;stmt=statement;cpy=copy;dest=destination;dist=distancedst=distance;ptr=pointer;wdth=width;str=string;ln=line;srv=server;attr=attribute;ref=reference;buf=buffer;col=column;nr=number;vec=vector;len=length;elem=element;val=value;i=index;var=variable;hght=height;cl=client;num=number;pos=position;lst=list;addr=address' + cppcoreguidelines-narrowing-conversions.WarnOnEquivalentBitWidth: 'true' + cppcoreguidelines-avoid-magic-numbers.IgnoredIntegerValues: '1;2;3;4;' + cppcoreguidelines-non-private-member-variables-in-classes.IgnorePublicMemberVariables: 'false' + modernize-loop-convert.MinConfidence: reasonable + readability-uniqueptr-delete-release.PreferResetCall: 'false' + cppcoreguidelines-avoid-magic-numbers.IgnorePowersOf2IntegerValues: 'false' + readability-identifier-length.MinimumExceptionNameLength: '2' + cert-oop57-cpp.MemCmpNames: '' + google-readability-namespace-comments.SpacesBeforeComments: '2' + cppcoreguidelines-avoid-magic-numbers.IgnoreBitFieldsWidths: 'true' + cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic: 'true' + readability-uppercase-literal-suffix.NewSuffixes: '' + readability-function-cognitive-complexity.Threshold: '25' + cppcoreguidelines-no-malloc.Allocations: '::malloc;::calloc' + readability-simplify-boolean-expr.SimplifyDeMorganRelaxed: 'false' + cppcoreguidelines-narrowing-conversions.WarnOnIntegerToFloatingPointNarrowingConversion: 'true' + readability-function-size.BranchThreshold: '4294967295' + cert-err61-cpp.CheckThrowTemporaries: 'true' + readability-implicit-bool-conversion.AllowIntegerConditions: 'false' + readability-identifier-length.IgnoredParameterNames: '^[n]$' + readability-function-size.StatementThreshold: '800' + readability-identifier-naming.IgnoreMainLikeFunctions: 'false' + llvm-qualified-auto.AddConstToQualified: 'false' + cppcoreguidelines-special-member-functions.AllowMissingMoveFunctionsWhenCopyIsDeleted: 'false' + cppcoreguidelines-init-variables.MathHeader: '' + cert-str34-c.CharTypdefsToIgnore: '' + google-readability-function-size.StatementThreshold: '800' + llvm-else-after-return.WarnOnConditionVariables: 'false' + cert-msc51-cpp.DisallowedSeedTypes: 'time_t,std::time_t' + readability-suspicious-call-argument.DiceSimilarAbove: '70' + readability-suspicious-call-argument.Dice: 'true' + readability-suspicious-call-argument.Abbreviation: 'true' + cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor: 'false' + readability-identifier-length.IgnoredLoopCounterNames: '^[ijk_]$' + cert-dcl37-c.Invert: 'false' + cert-dcl37-c.AggressiveDependentMemberLookup: 'false' + readability-identifier-length.MinimumLoopCounterNameLength: '2' + cppcoreguidelines-avoid-do-while.IgnoreMacros: 'false' + cert-msc54-cpp.AsyncSafeFunctionSet: POSIX + cppcoreguidelines-no-malloc.Deallocations: '::free' + readability-magic-numbers.IgnoredIntegerValues: '1;2;3;4;' + readability-magic-numbers.IgnorePowersOf2IntegerValues: 'false' + portability-simd-intrinsics.Std: '' + readability-redundant-member-init.IgnoreBaseInCopyConstructors: 'false' + readability-suspicious-call-argument.JaroWinklerSimilarAbove: '85' + cert-dcl16-c.IgnoreMacros: 'true' + llvm-else-after-return.WarnOnUnfixable: 'false' + cert-msc32-c.DisallowedSeedTypes: 'time_t,std::time_t' +... + diff --git a/CMakeLists.txt b/CMakeLists.txt index c973386..362821f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,7 +114,16 @@ install( # Clang tidy add_custom_target(clang-tidy-check - # clang-tidy -checks=-*,clang-analyzer-*,clang-analyzer-cplusplus*,cert-*,cppcoreguidelines-*,portability-*,readability-*,clang-diagnostic-* -dump-config -p ${CMAKE_BINARY_DIR}/compile_commands.json ${SOURCE_FILES} ${HEADER_FILES} > ../.clang-tidy clang-tidy -p ${CMAKE_BINARY_DIR}/compile_commands.json ${SOURCE_FILES} ${HEADER_FILES} DEPENDS ${SOURCE_FILES} ${HEADER_FILES} - ) \ No newline at end of file +) + +add_custom_target(clang-tidy-dump + clang-tidy -checks=-*,clang-analyzer-*,clang-analyzer-cplusplus*,cert-*,cppcoreguidelines-*,portability-*,readability-*,clang-diagnostic-* -dump-config -p ${CMAKE_BINARY_DIR}/compile_commands.json ${SOURCE_FILES} ${HEADER_FILES} > ../.clang-tidy + DEPENDS ${SOURCE_FILES} ${HEADER_FILES} +) + +add_custom_target(clang-tidy-fix + clang-tidy -fix-notes -p ${CMAKE_BINARY_DIR}/compile_commands.json ${SOURCE_FILES} ${HEADER_FILES} + DEPENDS ${SOURCE_FILES} ${HEADER_FILES} +) \ No newline at end of file From f179a7e4ae4ae25d0c49bc90c211da7b8c789b29 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Thu, 29 Feb 2024 21:52:31 -0500 Subject: [PATCH 06/47] Bump cmake minimum version to version 3.23 #23 --- CMakeLists.txt | 242 ++++++++++++++++++++++++++----------------------- 1 file changed, 129 insertions(+), 113 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e3afc99..020425e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,113 +1,129 @@ -cmake_minimum_required(VERSION 3.16) - -# Keep this on one line for release checking -project(dbc VERSION 0.2.0 DESCRIPTION "C++ DBC Parser") - -# -- PROJECT OPTIONS -- # -option(DBC_ENABLE_TESTS "Enable Unittests" ON) -option(DBC_TEST_LOCALE_INDEPENDENCE "Used to deterime if the libary is locale agnostic when it comes to converting floats. You need `de_DE.UTF-8` locale installed for this testing." OFF) -option(DBC_GENERATE_DOCS "Use doxygen if installed to generated documentation files" OFF) -option(DBC_GENERATE_SINGLE_HEADER "This will run the generator for the single header file version. Default is OFF since we make a static build. Requires cargo installed." OFF) -# ---------------------- # - -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) - -# package -set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) -set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) -set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) -set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE) -set(CPACK_RESOURCE_FILE_README ${CMAKE_CURRENT_SOURCE_DIR}/README.md) -include(CPack) - -# specify the C++ standard -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED True) - -find_package(FastFloat QUIET) -if (NOT ${FastFloat_FOUND}) - include(FetchContent) - FetchContent_Declare( - FastFloat - GIT_REPOSITORY https://github.com/fastfloat/fast_float.git - GIT_TAG 1ea4f27b2aeee2859a1354a3c24cff52a116cad1 - ) - FetchContent_MakeAvailable(FastFloat) -endif() - -# add where to find the source files -list(APPEND SOURCE_FILES - ${PROJECT_SOURCE_DIR}/src/utils.cpp - ${PROJECT_SOURCE_DIR}/src/message.cpp - ${PROJECT_SOURCE_DIR}/src/signal.cpp - ${PROJECT_SOURCE_DIR}/src/dbc.cpp -) - -list(APPEND HEADER_FILES - ${PROJECT_SOURCE_DIR}/include/libdbc/dbc.hpp - ${PROJECT_SOURCE_DIR}/include/libdbc/message.hpp - ${PROJECT_SOURCE_DIR}/include/libdbc/signal.hpp - ${PROJECT_SOURCE_DIR}/include/libdbc/utils/utils.hpp - ${PROJECT_SOURCE_DIR}/include/libdbc/exceptions/error.hpp -) - -if(DBC_ENABLE_TESTS) - include(CTest) - add_subdirectory(test) -endif() - -if(DBC_GENERATE_DOCS) - add_subdirectory(doc) -endif() - -list(APPEND GCC_CLANG_COMPILE_FLAGS - -Wall -Wextra -Wpedantic - -Wconversion -Wint-in-bool-context - -Wmissing-declarations -Wmissing-field-initializers - -Werror -) - - -if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") - add_compile_options(/W4 /WX) -elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") - # Clang shadow warnings aren't as sensitive as gcc - add_compile_options(${GCC_CLANG_COMPILE_FLAGS} -Wshadow) -else() - add_compile_options(${GCC_CLANG_COMPILE_FLAGS}) -endif() - -add_library(${PROJECT_NAME} STATIC ${SOURCE_FILES}) -target_link_libraries(${PROJECT_NAME} FastFloat::fast_float) -target_include_directories(${PROJECT_NAME} PUBLIC - $ - $ -) -target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_11) - -target_sources(${PROJECT_NAME} INTERFACE FILE_SET HEADERS - TYPE HEADERS - BASE_DIRS ${PROJECT_SOURCE_DIR}/include/libdbc - FILES ${HEADER_FILES} -) - -if(DBC_GENERATE_SINGLE_HEADER) - add_custom_target(single_header ALL - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - COMMAND ${CMAKE_SOURCE_DIR}/scripts/create_single_header.sh - ) -endif() - -## Installation -# install lib -install(TARGETS ${PROJECT_NAME} - DESTINATION ${CMAKE_INSTALL_LIBDIR}) - -# install headers -install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/libdbc DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) - -# 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) +cmake_minimum_required(VERSION 3.23) + +# Keep this on one line for release checking +project(dbc VERSION 0.2.0 DESCRIPTION "C++ DBC Parser") + +# -- PROJECT OPTIONS -- # +option(DBC_ENABLE_TESTS "Enable Unittests" ON) +option(DBC_TEST_LOCALE_INDEPENDENCE "Used to deterime if the libary is locale agnostic when it comes to converting floats. You need `de_DE.UTF-8` locale installed for this testing." OFF) +option(DBC_GENERATE_DOCS "Use doxygen if installed to generated documentation files" OFF) +option(DBC_GENERATE_SINGLE_HEADER "This will run the generator for the single header file version. Default is OFF since we make a static build. Requires cargo installed." OFF) +# ---------------------- # + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# package +set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) +set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) +set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) +set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE) +set(CPACK_RESOURCE_FILE_README ${CMAKE_CURRENT_SOURCE_DIR}/README.md) +include(CPack) + +# specify the C++ standard +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED True) + +find_package(FastFloat QUIET) +if (NOT ${FastFloat_FOUND}) + include(FetchContent) + FetchContent_Declare( + FastFloat + GIT_REPOSITORY https://github.com/fastfloat/fast_float.git + GIT_TAG 1ea4f27b2aeee2859a1354a3c24cff52a116cad1 + ) + FetchContent_MakeAvailable(FastFloat) +endif() + +# add where to find the source files +list(APPEND SOURCE_FILES + ${PROJECT_SOURCE_DIR}/src/utils.cpp + ${PROJECT_SOURCE_DIR}/src/message.cpp + ${PROJECT_SOURCE_DIR}/src/signal.cpp + ${PROJECT_SOURCE_DIR}/src/dbc.cpp +) + +list(APPEND HEADER_FILES + ${PROJECT_SOURCE_DIR}/include/libdbc/dbc.hpp + ${PROJECT_SOURCE_DIR}/include/libdbc/message.hpp + ${PROJECT_SOURCE_DIR}/include/libdbc/signal.hpp + ${PROJECT_SOURCE_DIR}/include/libdbc/utils/utils.hpp + ${PROJECT_SOURCE_DIR}/include/libdbc/exceptions/error.hpp +) + +if(DBC_ENABLE_TESTS) + include(CTest) + add_subdirectory(test) +endif() + +if(DBC_GENERATE_DOCS) + add_subdirectory(doc) +endif() + +list(APPEND GCC_CLANG_COMPILE_FLAGS + -Wall -Wextra -Wpedantic + -Wconversion -Wint-in-bool-context + -Wmissing-declarations -Wmissing-field-initializers + -Werror +) + + +if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + add_compile_options(/W4 /WX) +elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + # Clang shadow warnings aren't as sensitive as gcc + add_compile_options(${GCC_CLANG_COMPILE_FLAGS} -Wshadow) +else() + add_compile_options(${GCC_CLANG_COMPILE_FLAGS}) +endif() + +add_library(${PROJECT_NAME} STATIC ${SOURCE_FILES}) +target_link_libraries(${PROJECT_NAME} FastFloat::fast_float) +target_include_directories(${PROJECT_NAME} PUBLIC + $ + $ +) +target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_11) + +target_sources(${PROJECT_NAME} INTERFACE FILE_SET HEADERS + TYPE HEADERS + BASE_DIRS ${PROJECT_SOURCE_DIR}/include/libdbc + FILES ${HEADER_FILES} +) + +if(DBC_GENERATE_SINGLE_HEADER) + add_custom_target(single_header ALL + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMAND ${CMAKE_SOURCE_DIR}/scripts/create_single_header.sh + ) +endif() + +## Installation +# install lib +install(TARGETS ${PROJECT_NAME} + DESTINATION ${CMAKE_INSTALL_LIBDIR}) + +# install headers +install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/libdbc DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + +# 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) + +# Clang tidy +add_custom_target(clang-tidy-check + clang-tidy -p ${CMAKE_BINARY_DIR}/compile_commands.json ${SOURCE_FILES} ${HEADER_FILES} + DEPENDS ${SOURCE_FILES} ${HEADER_FILES} +) + +add_custom_target(clang-tidy-dump + clang-tidy -checks=-*,clang-analyzer-*,clang-analyzer-cplusplus*,cert-*,cppcoreguidelines-*,portability-*,readability-*,clang-diagnostic-* -dump-config -p ${CMAKE_BINARY_DIR}/compile_commands.json ${SOURCE_FILES} ${HEADER_FILES} > ../.clang-tidy + DEPENDS ${SOURCE_FILES} ${HEADER_FILES} +) + +add_custom_target(clang-tidy-fix + clang-tidy -fix-notes -p ${CMAKE_BINARY_DIR}/compile_commands.json ${SOURCE_FILES} ${HEADER_FILES} + DEPENDS ${SOURCE_FILES} ${HEADER_FILES} +) From 5343d15d1dcd62cb9d99beb4ef54287debcfe2ac Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Thu, 29 Feb 2024 22:10:53 -0500 Subject: [PATCH 07/47] Standardize line endings to LF only (unix) and fix clang tidy errors about reserved define includes guards --- .clang-format | 1 + include/libdbc/dbc.hpp | 110 ++--- include/libdbc/exceptions/error.hpp | 48 +-- include/libdbc/message.hpp | 98 ++--- include/libdbc/signal.hpp | 108 ++--- include/libdbc/utils/utils.hpp | 102 ++--- src/dbc.cpp | 616 ++++++++++++++-------------- src/message.cpp | 230 +++++------ src/signal.cpp | 110 ++--- src/utils.cpp | 162 ++++---- test/test_dbc.cpp | 440 ++++++++++---------- test/test_utils.cpp | 168 ++++---- 12 files changed, 1097 insertions(+), 1096 deletions(-) diff --git a/.clang-format b/.clang-format index c409644..350cdc2 100644 --- a/.clang-format +++ b/.clang-format @@ -106,3 +106,4 @@ AllowShortLambdasOnASingleLine: Empty AllowAllArgumentsOnNextLine: false InsertNewlineAtEOF: true +LineEnding: LF diff --git a/include/libdbc/dbc.hpp b/include/libdbc/dbc.hpp index bff9c4e..109b89f 100644 --- a/include/libdbc/dbc.hpp +++ b/include/libdbc/dbc.hpp @@ -1,55 +1,55 @@ -#ifndef __DBC_HPP__ -#define __DBC_HPP__ - -#include -#include -#include -#include - -#include - -namespace libdbc { - -class Parser { -public: - virtual ~Parser() = default; - - virtual void parse_file(const std::string& file) = 0; - -protected: -}; - -class DbcParser : public Parser { -public: - DbcParser(); - - virtual ~DbcParser() = default; - - virtual void parse_file(const std::string& file) final override; - - std::string get_version() const; - std::vector get_nodes() const; - std::vector get_messages() const; - - Message::ParseSignalsStatus parseMessage(const uint32_t id, const std::vector& data, std::vector& out_values); - -private: - std::string version; - std::vector nodes; - std::vector messages; - - 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); -}; - -} - -#endif // __DBC_HPP__ +#ifndef DBC_HPP +#define DBC_HPP + +#include +#include +#include +#include + +#include + +namespace libdbc { + +class Parser { +public: + virtual ~Parser() = default; + + virtual void parse_file(const std::string& file) = 0; + +protected: +}; + +class DbcParser : public Parser { +public: + DbcParser(); + + virtual ~DbcParser() = default; + + virtual void parse_file(const std::string& file) final override; + + std::string get_version() const; + std::vector get_nodes() const; + std::vector get_messages() const; + + Message::ParseSignalsStatus parseMessage(const uint32_t id, const std::vector& data, std::vector& out_values); + +private: + std::string version; + std::vector nodes; + std::vector messages; + + 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); +}; + +} + +#endif // DBC_HPP diff --git a/include/libdbc/exceptions/error.hpp b/include/libdbc/exceptions/error.hpp index 175cac7..a6a3653 100644 --- a/include/libdbc/exceptions/error.hpp +++ b/include/libdbc/exceptions/error.hpp @@ -1,24 +1,24 @@ -#ifndef __ERROR_HPP__ -#define __ERROR_HPP__ - -#include - -namespace libdbc { - -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"; - } -}; - -} // libdbc - -#endif // __ERROR_HPP__ +#ifndef ERROR_HPP +#define ERROR_HPP + +#include + +namespace libdbc { + +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"; + } +}; + +} // libdbc + +#endif // ERROR_HPP diff --git a/include/libdbc/message.hpp b/include/libdbc/message.hpp index f3b0b66..a018a31 100644 --- a/include/libdbc/message.hpp +++ b/include/libdbc/message.hpp @@ -1,49 +1,49 @@ -#ifndef __MESSAGE_HPP__ -#define __MESSAGE_HPP__ - -#include -#include -#include -#include -#include - -namespace libdbc { -struct Message { - Message() = delete; - virtual ~Message() = default; - explicit Message(uint32_t id, const std::string& name, uint8_t size, const std::string& node); - - enum class ParseSignalsStatus { - Success, - ErrorMessageToLong, - ErrorBigEndian, - ErrorUnknownID, - ErrorInvalidConversion, - }; - - ParseSignalsStatus parseSignals(const std::vector& data, std::vector& values) const; - - void appendSignal(const Signal& signal); - const std::vector getSignals() const; - uint32_t id() const; - uint8_t size() const; - const std::string& name() const; - void addValueDescription(const std::string& signal_name, const std::vector&); - - 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); - -} - -#endif // __MESSAGE_HPP__ +#ifndef MESSAGE_HPP +#define MESSAGE_HPP + +#include +#include +#include +#include +#include + +namespace libdbc { +struct Message { + Message() = delete; + virtual ~Message() = default; + explicit Message(uint32_t id, const std::string& name, uint8_t size, const std::string& node); + + enum class ParseSignalsStatus { + Success, + ErrorMessageToLong, + ErrorBigEndian, + ErrorUnknownID, + ErrorInvalidConversion, + }; + + ParseSignalsStatus parseSignals(const std::vector& data, std::vector& values) const; + + void appendSignal(const Signal& signal); + const std::vector getSignals() const; + uint32_t id() const; + uint8_t size() const; + const std::string& name() const; + void addValueDescription(const std::string& signal_name, const std::vector&); + + 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); + +} + +#endif // MESSAGE_HPP diff --git a/include/libdbc/signal.hpp b/include/libdbc/signal.hpp index c7311cb..cdfd018 100644 --- a/include/libdbc/signal.hpp +++ b/include/libdbc/signal.hpp @@ -1,54 +1,54 @@ - -#ifndef __SIGNAL_HPP__ -#define __SIGNAL_HPP__ - -#include -#include -#include -#include - -namespace libdbc { -struct Signal { - struct SignalValueDescriptions { - uint32_t value; - std::string description; - }; - - 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; - std::vector svDescriptions; - - Signal() = delete; - virtual ~Signal() = default; - 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); - -} - -#endif // __SIGNAL_HPP__ + +#ifndef SIGNAL_HPP +#define SIGNAL_HPP + +#include +#include +#include +#include + +namespace libdbc { +struct Signal { + struct SignalValueDescriptions { + uint32_t value; + std::string description; + }; + + 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; + std::vector svDescriptions; + + Signal() = delete; + virtual ~Signal() = default; + 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); + +} + +#endif // SIGNAL_HPP diff --git a/include/libdbc/utils/utils.hpp b/include/libdbc/utils/utils.hpp index 21ff540..8763af6 100644 --- a/include/libdbc/utils/utils.hpp +++ b/include/libdbc/utils/utils.hpp @@ -1,51 +1,51 @@ - -#ifndef __UTILS_HPP__ -#define __UTILS_HPP__ - -#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); - } - } - - static double convert_to_double(const std::string& value, double default_value = 0); -}; - -} - -#endif // __UTILS_HPP__ + +#ifndef UTILS_HPP +#define UTILS_HPP + +#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); + } + } + + static double convert_to_double(const std::string& value, double default_value = 0); +}; + +} + +#endif // UTILS_HPP diff --git a/src/dbc.cpp b/src/dbc.cpp index 7ea7ce3..d78c32e 100644 --- a/src/dbc.cpp +++ b/src/dbc.cpp @@ -1,308 +1,308 @@ -#include -#include -#include -#include - -#include - -namespace libdbc { - -const auto floatPattern = "(-?\\d+\\.?(\\d+)?)"; // Can be negative - -const auto signalIdentifierPattern = "(SG_)"; -const auto namePattern = "(\\w+)"; -const auto bitStartPattern = "(\\d+)"; // Cannot be negative -const auto lengthPattern = "(\\d+)"; // Cannot be negative -const auto byteOrderPattern = "([0-1])"; -const auto signPattern = "(\\+|\\-)"; -const auto scalePattern = "(\\d+\\.?(\\d+)?)"; // Non negative float -const auto offsetPattern = floatPattern; -const auto offsetScalePattern = std::string("\\(") + scalePattern + "\\," + offsetPattern + "\\)"; -const auto minPattern = floatPattern; -const auto maxPattern = floatPattern; -const auto minMaxPattern = std::string("\\[") + minPattern + "\\|" + maxPattern + "\\]"; -const auto unitPattern = "\"(.*)\""; // Random string -const auto receiverPattern = "([\\w\\,]+|Vector__XXX)*"; -const auto whiteSpace = "\\s"; - -enum VALToken { Identifier = 0, CANId, SignalName, Value, Description }; - -struct VALObject { - uint32_t can_id; - std::string signal_name; - std::vector vd; -}; - -static bool parseVal(const std::string& str, VALObject& obj); -bool parseVal(const std::string& str, VALObject& obj) { - obj.signal_name = ""; - obj.vd.clear(); - auto state = Identifier; - const char* a = str.data(); - Signal::SignalValueDescriptions vd; - for (;;) { - switch (state) { - case Identifier: { - if (*a != 'V') { - return false; - } - a++; - if (*a != 'A') { - return false; - } - a++; - if (*a != 'L') { - return false; - } - a++; - if (*a != '_') { - return false; - } - a++; - if (*a != ' ') { - return false; - } - a++; // skip whitespace - state = CANId; - break; - } - case CANId: { - std::string can_id_str; - while (*a >= '0' && *a <= '9') { - can_id_str += *a; - a++; - } - if (can_id_str.empty()) { - return false; - } - obj.can_id = static_cast(std::stoul(can_id_str)); - if (*a != ' ') { - return false; - } - a++; // skip whitespace - state = SignalName; - break; - } - case SignalName: { - if ((*a >= 'a' && *a <= 'z') || (*a >= 'A' && *a <= 'Z') || *a == '_') { - obj.signal_name += *a; - } else { - return false; - } - a++; - while ((*a >= 'a' && *a <= 'z') || (*a >= 'A' && *a <= 'Z') || *a == '_' || (*a >= '0' && *a <= '9')) { - obj.signal_name += *a; - a++; - } - if (*a != ' ') { - return false; - } - a++; // skip whitespace - state = Value; - break; - } - case Value: { - std::string value_str; - while (*a >= '0' && *a <= '9') { - value_str += *a; - a++; - } - if (*a == ';') { - if (value_str.empty()) { - return true; - } - return false; - } - if (value_str.empty()) { - return false; - } - - if (*a != ' ') { - return false; - } - a++; // skip whitespace - vd.value = (uint32_t)std::stoul(value_str); - state = Description; - break; - } - case Description: { - std::string desc; - if (*a != '"') { - return false; - } - a++; - while (*a != '"' && *a != 0) { - desc += *a; - a++; - } - if (*a == 0) { - return false; - } - a++; - if (*a != ' ') { - return false; - } - a++; // skip whitespace - - vd.description = desc; - obj.vd.push_back(vd); - - state = Value; - break; - } - } - } - return false; -} - -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; - - messages.clear(); - - parse_dbc_header(s); - - parse_dbc_nodes(s); - - while (!s.eof()) { - utils::StreamHandler::get_next_non_blank_line(s, line); - lines.push_back(line); - } - - parse_dbc_messages(lines); -} - -std::string DbcParser::get_version() const { - return version; -} - -std::vector DbcParser::get_nodes() const { - return nodes; -} - -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; -} - -void DbcParser::parse_dbc_header(std::istream& file_stream) { - std::string line; - std::smatch match; - - utils::StreamHandler::get_line(file_stream, line); - - if (!std::regex_search(line, match, version_re)) { - throw validity_error(); - } - - version = match.str(2); - - utils::StreamHandler::get_next_non_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); - - 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); - - if (!std::regex_search(line, match, node_re)) { - throw validity_error(); - } - - if (match.length() > 2) { - std::string n = match.str(2); - utils::String::split(n, nodes); - } -} - -void DbcParser::parse_dbc_messages(const std::vector& lines) { - std::smatch match; - - std::vector sv; - - VALObject obj{}; - for (const auto& line : lines) { - if (std::regex_search(line, match, message_re)) { - uint32_t id = static_cast(std::stoul(match.str(2))); - std::string name = match.str(3); - uint8_t size = static_cast(std::stoul(match.str(4))); - std::string node = match.str(5); - - Message msg(id, name, size, node); - - messages.push_back(msg); - continue; - } - - 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 = static_cast(std::stoul(match.str(3))); - uint32_t size = static_cast(std::stoul(match.str(4))); - bool is_bigendian = (std::stoul(match.str(5)) == 0); - bool is_signed = (match.str(6) == "-"); - - double factor = utils::String::convert_to_double(match.str(7).data()); - double offset = utils::String::convert_to_double(match.str(9).data()); - double min = utils::String::convert_to_double(match.str(11).data()); - double max = utils::String::convert_to_double(match.str(13).data()); - - 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); - continue; - } - - if (parseVal(line, obj)) { - sv.push_back(obj); - continue; - } - } - - for (const auto& signal : sv) { - for (auto& msg : messages) { - if (msg.id() == signal.can_id) { - msg.addValueDescription(signal.signal_name, signal.vd); - break; - } - } - } -} - -} +#include +#include +#include +#include + +#include + +namespace libdbc { + +const auto floatPattern = "(-?\\d+\\.?(\\d+)?)"; // Can be negative + +const auto signalIdentifierPattern = "(SG_)"; +const auto namePattern = "(\\w+)"; +const auto bitStartPattern = "(\\d+)"; // Cannot be negative +const auto lengthPattern = "(\\d+)"; // Cannot be negative +const auto byteOrderPattern = "([0-1])"; +const auto signPattern = "(\\+|\\-)"; +const auto scalePattern = "(\\d+\\.?(\\d+)?)"; // Non negative float +const auto offsetPattern = floatPattern; +const auto offsetScalePattern = std::string("\\(") + scalePattern + "\\," + offsetPattern + "\\)"; +const auto minPattern = floatPattern; +const auto maxPattern = floatPattern; +const auto minMaxPattern = std::string("\\[") + minPattern + "\\|" + maxPattern + "\\]"; +const auto unitPattern = "\"(.*)\""; // Random string +const auto receiverPattern = "([\\w\\,]+|Vector__XXX)*"; +const auto whiteSpace = "\\s"; + +enum VALToken { Identifier = 0, CANId, SignalName, Value, Description }; + +struct VALObject { + uint32_t can_id; + std::string signal_name; + std::vector vd; +}; + +static bool parseVal(const std::string& str, VALObject& obj); +bool parseVal(const std::string& str, VALObject& obj) { + obj.signal_name = ""; + obj.vd.clear(); + auto state = Identifier; + const char* a = str.data(); + Signal::SignalValueDescriptions vd; + for (;;) { + switch (state) { + case Identifier: { + if (*a != 'V') { + return false; + } + a++; + if (*a != 'A') { + return false; + } + a++; + if (*a != 'L') { + return false; + } + a++; + if (*a != '_') { + return false; + } + a++; + if (*a != ' ') { + return false; + } + a++; // skip whitespace + state = CANId; + break; + } + case CANId: { + std::string can_id_str; + while (*a >= '0' && *a <= '9') { + can_id_str += *a; + a++; + } + if (can_id_str.empty()) { + return false; + } + obj.can_id = static_cast(std::stoul(can_id_str)); + if (*a != ' ') { + return false; + } + a++; // skip whitespace + state = SignalName; + break; + } + case SignalName: { + if ((*a >= 'a' && *a <= 'z') || (*a >= 'A' && *a <= 'Z') || *a == '_') { + obj.signal_name += *a; + } else { + return false; + } + a++; + while ((*a >= 'a' && *a <= 'z') || (*a >= 'A' && *a <= 'Z') || *a == '_' || (*a >= '0' && *a <= '9')) { + obj.signal_name += *a; + a++; + } + if (*a != ' ') { + return false; + } + a++; // skip whitespace + state = Value; + break; + } + case Value: { + std::string value_str; + while (*a >= '0' && *a <= '9') { + value_str += *a; + a++; + } + if (*a == ';') { + if (value_str.empty()) { + return true; + } + return false; + } + if (value_str.empty()) { + return false; + } + + if (*a != ' ') { + return false; + } + a++; // skip whitespace + vd.value = (uint32_t)std::stoul(value_str); + state = Description; + break; + } + case Description: { + std::string desc; + if (*a != '"') { + return false; + } + a++; + while (*a != '"' && *a != 0) { + desc += *a; + a++; + } + if (*a == 0) { + return false; + } + a++; + if (*a != ' ') { + return false; + } + a++; // skip whitespace + + vd.description = desc; + obj.vd.push_back(vd); + + state = Value; + break; + } + } + } + return false; +} + +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; + + messages.clear(); + + parse_dbc_header(s); + + parse_dbc_nodes(s); + + while (!s.eof()) { + utils::StreamHandler::get_next_non_blank_line(s, line); + lines.push_back(line); + } + + parse_dbc_messages(lines); +} + +std::string DbcParser::get_version() const { + return version; +} + +std::vector DbcParser::get_nodes() const { + return nodes; +} + +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; +} + +void DbcParser::parse_dbc_header(std::istream& file_stream) { + std::string line; + std::smatch match; + + utils::StreamHandler::get_line(file_stream, line); + + if (!std::regex_search(line, match, version_re)) { + throw validity_error(); + } + + version = match.str(2); + + utils::StreamHandler::get_next_non_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); + + 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); + + if (!std::regex_search(line, match, node_re)) { + throw validity_error(); + } + + if (match.length() > 2) { + std::string n = match.str(2); + utils::String::split(n, nodes); + } +} + +void DbcParser::parse_dbc_messages(const std::vector& lines) { + std::smatch match; + + std::vector sv; + + VALObject obj{}; + for (const auto& line : lines) { + if (std::regex_search(line, match, message_re)) { + uint32_t id = static_cast(std::stoul(match.str(2))); + std::string name = match.str(3); + uint8_t size = static_cast(std::stoul(match.str(4))); + std::string node = match.str(5); + + Message msg(id, name, size, node); + + messages.push_back(msg); + continue; + } + + 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 = static_cast(std::stoul(match.str(3))); + uint32_t size = static_cast(std::stoul(match.str(4))); + bool is_bigendian = (std::stoul(match.str(5)) == 0); + bool is_signed = (match.str(6) == "-"); + + double factor = utils::String::convert_to_double(match.str(7).data()); + double offset = utils::String::convert_to_double(match.str(9).data()); + double min = utils::String::convert_to_double(match.str(11).data()); + double max = utils::String::convert_to_double(match.str(13).data()); + + 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); + continue; + } + + if (parseVal(line, obj)) { + sv.push_back(obj); + continue; + } + } + + for (const auto& signal : sv) { + for (auto& msg : messages) { + if (msg.id() == signal.can_id) { + msg.addValueDescription(signal.signal_name, signal.vd); + break; + } + } + } +} + +} diff --git a/src/message.cpp b/src/message.cpp index f16677a..89b47ac 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -1,115 +1,115 @@ -#include -#include -#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) { -} - -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 { - auto 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 (size_t 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? - - const auto 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 { - v = data_little_endian >> signal.start_bit; - } - - if (signal.is_signed && signal.size > 1) { - switch (signal.size) { - case 8: - values.push_back(static_cast(v) * signal.factor + signal.offset); - break; - case 16: - values.push_back(static_cast(v) * signal.factor + signal.offset); - break; - case 32: - values.push_back(static_cast(v) * signal.factor + signal.offset); - break; - case 64: - values.push_back(static_cast(v) * signal.factor + signal.offset); - break; - default: { - // 2 complement -> decimal - const int negative = (v & (1ull << (signal.size - 1))) != 0; - int64_t nativeInt; - if (negative) { - nativeInt = static_cast(v | ~((1ull << signal.size) - 1)); // invert all bits above signal.size - } else { - nativeInt = static_cast(v & ((1ull << signal.size) - 1)); // masking - } - values.push_back(static_cast(nativeInt) * signal.factor + signal.offset); - break; - } - } - } else { - // use only the relevant bits - v = v & ((1 << signal.size) - 1); // masking - values.push_back(static_cast(v) * signal.factor + signal.offset); - } - } - return ParseSignalsStatus::Success; -} - -void Message::appendSignal(const Signal& signal) { - m_signals.push_back(signal); -} - -const std::vector Message::getSignals() const { - return m_signals; -} - -uint32_t Message::id() const { - return m_id; -} - -uint8_t Message::size() const { - return m_size; -} - -const std::string& Message::name() const { - return m_name; -} - -void Message::addValueDescription(const std::string& signal_name, const std::vector& vd) { - for (auto& s : m_signals) { - if (s.name.compare(signal_name) == 0) { - s.svDescriptions = vd; - return; - } - } -} - -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; -} -} +#include +#include +#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) { +} + +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 { + auto 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 (size_t 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? + + const auto 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 { + v = data_little_endian >> signal.start_bit; + } + + if (signal.is_signed && signal.size > 1) { + switch (signal.size) { + case 8: + values.push_back(static_cast(v) * signal.factor + signal.offset); + break; + case 16: + values.push_back(static_cast(v) * signal.factor + signal.offset); + break; + case 32: + values.push_back(static_cast(v) * signal.factor + signal.offset); + break; + case 64: + values.push_back(static_cast(v) * signal.factor + signal.offset); + break; + default: { + // 2 complement -> decimal + const int negative = (v & (1ull << (signal.size - 1))) != 0; + int64_t nativeInt; + if (negative) { + nativeInt = static_cast(v | ~((1ull << signal.size) - 1)); // invert all bits above signal.size + } else { + nativeInt = static_cast(v & ((1ull << signal.size) - 1)); // masking + } + values.push_back(static_cast(nativeInt) * signal.factor + signal.offset); + break; + } + } + } else { + // use only the relevant bits + v = v & ((1 << signal.size) - 1); // masking + values.push_back(static_cast(v) * signal.factor + signal.offset); + } + } + return ParseSignalsStatus::Success; +} + +void Message::appendSignal(const Signal& signal) { + m_signals.push_back(signal); +} + +const std::vector Message::getSignals() const { + return m_signals; +} + +uint32_t Message::id() const { + return m_id; +} + +uint8_t Message::size() const { + return m_size; +} + +const std::string& Message::name() const { + return m_name; +} + +void Message::addValueDescription(const std::string& signal_name, const std::vector& vd) { + for (auto& s : m_signals) { + if (s.name.compare(signal_name) == 0) { + s.svDescriptions = vd; + return; + } + } +} + +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 d1ab7d8..b9ce591 100644 --- a/src/signal.cpp +++ b/src/signal.cpp @@ -1,55 +1,55 @@ -#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) { -} - -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; -} - -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 << "}"; -} -} +#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) { +} + +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; +} + +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 << "}"; +} +} diff --git a/src/utils.cpp b/src/utils.cpp index f39cc81..ed715cb 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -1,81 +1,81 @@ -#include -#include -#include -#include - -#include - -namespace utils { - -std::istream& StreamHandler::get_line(std::istream& stream, std::string& line) { - std::string newline; - - std::getline(stream, newline); - - // 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; -} - -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; - - while (is_blank) { - utils::StreamHandler::get_line(stream, line); - - std::regex_search(line, match, whitespace_re); - - 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; - - const std::regex whitespace_re("\\s*(.*)"); - std::smatch match; - - while (!line_is_empty) { - utils::StreamHandler::get_line(stream, line); - - std::regex_search(line, match, whitespace_re); - - 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); -} - -double String::convert_to_double(const std::string& value, double default_value) { - double converted_value = default_value; - fast_float::from_chars(value.data(), value.data() + value.size(), converted_value); - return converted_value; -} - -} // Namespace Utils +#include +#include +#include +#include + +#include + +namespace utils { + +std::istream& StreamHandler::get_line(std::istream& stream, std::string& line) { + std::string newline; + + std::getline(stream, newline); + + // 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; +} + +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; + + while (is_blank) { + utils::StreamHandler::get_line(stream, line); + + std::regex_search(line, match, whitespace_re); + + 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; + + const std::regex whitespace_re("\\s*(.*)"); + std::smatch match; + + while (!line_is_empty) { + utils::StreamHandler::get_line(stream, line); + + std::regex_search(line, match, whitespace_re); + + 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); +} + +double String::convert_to_double(const std::string& value, double default_value) { + double converted_value = default_value; + fast_float::from_chars(value.data(), value.data() + value.size(), converted_value); + return converted_value; +} + +} // Namespace Utils diff --git a/test/test_dbc.cpp b/test/test_dbc.cpp index 508df5c..ff0645f 100644 --- a/test/test_dbc.cpp +++ b/test/test_dbc.cpp @@ -1,207 +1,207 @@ -#include "testing_utils/common.hpp" -#include "testing_utils/defines.hpp" -#include -#include -#include -#include -#include - -TEST_CASE("Testing dbc file loading error issues", "[fileio][error]") { - auto parser = std::unique_ptr(new libdbc::DbcParser()); - - SECTION("Loading a non dbc file should throw an error", "[error]") { - REQUIRE_THROWS_AS(parser->parse_file(TEXT_FILE), libdbc::validity_error); - } - - SECTION("Loading a dbc with bad headers throws an error", "[error]") { - REQUIRE_THROWS_AS(parser->parse_file(MISSING_VERSION_DBC_FILE), libdbc::validity_error); - } - - SECTION("Loading a dbc without the required bit timing section (BS_:)", "[error]") { - REQUIRE_THROWS_AS(parser->parse_file(MISSING_BIT_TIMING_DBC_FILE), libdbc::validity_error); - } - - SECTION("Loading a dbc with some missing namespace section tags (NS_ :)", "[error]") { - // Confusion about this type of error. it appears that the header isn't - // very well standardized for now we ignore this type of error. - CHECK_NOTHROW(parser->parse_file(MISSING_NEW_SYMBOLS_DBC_FILE)); - } - - SECTION("Verify that what() method is accessible for all exceptions", "[error]") { - auto generic_error = libdbc::exception(); - REQUIRE(std::string{generic_error.what()} == "libdbc exception occurred"); - - auto validity_check = libdbc::validity_error(); - REQUIRE(std::string{validity_check.what()} == "Invalid DBC file"); - } -} - -TEST_CASE("Testing dbc file loading", "[fileio]") { - auto parser = std::unique_ptr(new libdbc::DbcParser()); - - SECTION("Loading a single simple dbc file", "[dbc]") { - std::vector nodes = {"DBG", "DRIVER", "IO", "MOTOR", "SENSOR"}; - - libdbc::Message msg(500, "IO_DEBUG", 4, "IO"); - - std::vector receivers{"DBG"}; - libdbc::Signal sig("IO_DEBUG_test_unsigned", false, 0, 8, false, false, 1, 0, 0, 0, "", receivers); - msg.appendSignal(sig); - - std::vector msgs = {msg}; - - parser->parse_file(SIMPLE_DBC_FILE); - - REQUIRE(parser->get_version() == "1.0.0"); - - REQUIRE(parser->get_nodes() == nodes); - - REQUIRE(parser->get_messages() == msgs); - - REQUIRE(parser->get_messages().front().getSignals() == msg.getSignals()); - } -} - -TEST_CASE("Testing big endian, little endian") { +#include "testing_utils/common.hpp" +#include "testing_utils/defines.hpp" +#include +#include +#include +#include +#include + +TEST_CASE("Testing dbc file loading error issues", "[fileio][error]") { + auto parser = std::unique_ptr(new libdbc::DbcParser()); + + SECTION("Loading a non dbc file should throw an error", "[error]") { + REQUIRE_THROWS_AS(parser->parse_file(TEXT_FILE), libdbc::validity_error); + } + + SECTION("Loading a dbc with bad headers throws an error", "[error]") { + REQUIRE_THROWS_AS(parser->parse_file(MISSING_VERSION_DBC_FILE), libdbc::validity_error); + } + + SECTION("Loading a dbc without the required bit timing section (BS_:)", "[error]") { + REQUIRE_THROWS_AS(parser->parse_file(MISSING_BIT_TIMING_DBC_FILE), libdbc::validity_error); + } + + SECTION("Loading a dbc with some missing namespace section tags (NS_ :)", "[error]") { + // Confusion about this type of error. it appears that the header isn't + // very well standardized for now we ignore this type of error. + CHECK_NOTHROW(parser->parse_file(MISSING_NEW_SYMBOLS_DBC_FILE)); + } + + SECTION("Verify that what() method is accessible for all exceptions", "[error]") { + auto generic_error = libdbc::exception(); + REQUIRE(std::string{generic_error.what()} == "libdbc exception occurred"); + + auto validity_check = libdbc::validity_error(); + REQUIRE(std::string{validity_check.what()} == "Invalid DBC file"); + } +} + +TEST_CASE("Testing dbc file loading", "[fileio]") { + auto parser = std::unique_ptr(new libdbc::DbcParser()); + + SECTION("Loading a single simple dbc file", "[dbc]") { + std::vector nodes = {"DBG", "DRIVER", "IO", "MOTOR", "SENSOR"}; + + libdbc::Message msg(500, "IO_DEBUG", 4, "IO"); + + std::vector receivers{"DBG"}; + libdbc::Signal sig("IO_DEBUG_test_unsigned", false, 0, 8, false, false, 1, 0, 0, 0, "", receivers); + msg.appendSignal(sig); + + std::vector msgs = {msg}; + + parser->parse_file(SIMPLE_DBC_FILE); + + REQUIRE(parser->get_version() == "1.0.0"); + + REQUIRE(parser->get_nodes() == nodes); + + REQUIRE(parser->get_messages() == msgs); + + REQUIRE(parser->get_messages().front().getSignals() == msg.getSignals()); + } +} + +TEST_CASE("Testing big endian, little endian") { std::string dbc_contents = PRIMITIVE_DBC + 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)"; - const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); - - auto parser = libdbc::DbcParser(); - parser.parse_file(filename.c_str()); - - REQUIRE(parser.get_messages().size() == 1); - REQUIRE(parser.get_messages().at(0).name() == "MSG1"); - REQUIRE(parser.get_messages().at(0).size() == 8); - REQUIRE(parser.get_messages().at(0).getSignals().size() == 2); - { - const auto signal = parser.get_messages().at(0).getSignals().at(0); - REQUIRE(signal.is_bigendian == true); - } - { - const auto signal = parser.get_messages().at(0).getSignals().at(1); - REQUIRE(signal.is_bigendian == false); - } -} - -TEST_CASE("Testing negative values") { + SG_ Sig2 : 39|16@1- (0.1,0) [-3276.8|-3276.7] "C" Vector__XXX)"; + const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); + + auto parser = libdbc::DbcParser(); + parser.parse_file(filename.c_str()); + + REQUIRE(parser.get_messages().size() == 1); + REQUIRE(parser.get_messages().at(0).name() == "MSG1"); + REQUIRE(parser.get_messages().at(0).size() == 8); + REQUIRE(parser.get_messages().at(0).getSignals().size() == 2); + { + const auto signal = parser.get_messages().at(0).getSignals().at(0); + REQUIRE(signal.is_bigendian == true); + } + { + const auto signal = parser.get_messages().at(0).getSignals().at(1); + REQUIRE(signal.is_bigendian == false); + } +} + +TEST_CASE("Testing negative values") { std::string dbc_contents = PRIMITIVE_DBC + R"(BO_ 234 MSG1: 58 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)"; - const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); - - auto parser = libdbc::DbcParser(); - parser.parse_file(filename.c_str()); - - REQUIRE(parser.get_messages().size() == 1); - REQUIRE(parser.get_messages().at(0).name() == "MSG1"); - REQUIRE(parser.get_messages().at(0).size() == 58); - REQUIRE(parser.get_messages().at(0).getSignals().size() == 4); - - SECTION("Evaluating first message") { - const auto signal = parser.get_messages().at(0).getSignals().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).getSignals().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).getSignals().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).getSignals().at(3); - REQUIRE(signal.factor == 1); - REQUIRE(signal.offset == -10); - REQUIRE(signal.min == 0); - REQUIRE(signal.max == 32767); - } -} - -TEST_CASE("Special characters in unit") { + SG_ Sig4 : 7|16@0- (1,-10) [0|32767] "" Vector__XXX)"; + const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); + + auto parser = libdbc::DbcParser(); + parser.parse_file(filename.c_str()); + + REQUIRE(parser.get_messages().size() == 1); + REQUIRE(parser.get_messages().at(0).name() == "MSG1"); + REQUIRE(parser.get_messages().at(0).size() == 58); + REQUIRE(parser.get_messages().at(0).getSignals().size() == 4); + + SECTION("Evaluating first message") { + const auto signal = parser.get_messages().at(0).getSignals().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).getSignals().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).getSignals().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).getSignals().at(3); + REQUIRE(signal.factor == 1); + REQUIRE(signal.offset == -10); + REQUIRE(signal.min == 0); + REQUIRE(signal.max == 32767); + } +} + +TEST_CASE("Special characters in unit") { std::string dbc_contents = PRIMITIVE_DBC + R"(BO_ 234 MSG1: 255 Vector__XXX - SG_ Speed : 0|8@1+ (1,0) [0|204] "Km/h" DEVICE1,DEVICE2,DEVICE3)"; - const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); - - auto parser = libdbc::DbcParser(); - parser.parse_file(filename.c_str()); - - REQUIRE(parser.get_messages().size() == 1); - REQUIRE(parser.get_messages().at(0).name() == "MSG1"); - REQUIRE(parser.get_messages().at(0).size() == 255); - 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); - REQUIRE(signal.unit.compare("Km/h") == 0); - } -} - -TEST_CASE("Signal Value Description") { + SG_ Speed : 0|8@1+ (1,0) [0|204] "Km/h" DEVICE1,DEVICE2,DEVICE3)"; + const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); + + auto parser = libdbc::DbcParser(); + parser.parse_file(filename.c_str()); + + REQUIRE(parser.get_messages().size() == 1); + REQUIRE(parser.get_messages().at(0).name() == "MSG1"); + REQUIRE(parser.get_messages().at(0).size() == 255); + 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); + REQUIRE(signal.unit.compare("Km/h") == 0); + } +} + +TEST_CASE("Signal Value Description") { std::string dbc_contents = PRIMITIVE_DBC + R"(BO_ 234 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 -VAL_ 234 State1 123 "Description 1" 0 "Description 2" 90903489 "Big value and special characters &$§())!" ;)"; - const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); - - auto parser = libdbc::DbcParser(); - parser.parse_file(filename.c_str()); - - 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); - REQUIRE(parser.get_messages().at(0).getSignals().at(1).svDescriptions.size() == 0); - - const auto signal = parser.get_messages().at(0).getSignals().at(0); - REQUIRE(signal.svDescriptions.at(0).value == 123); - REQUIRE(signal.svDescriptions.at(0).description == "Description 1"); - REQUIRE(signal.svDescriptions.at(1).value == 0); - REQUIRE(signal.svDescriptions.at(1).description == "Description 2"); - REQUIRE(signal.svDescriptions.at(2).value == 90903489); - REQUIRE(signal.svDescriptions.at(2).description == "Big value and special characters &$§())!"); -} - -TEST_CASE("Signal Value Description Extended CAN id") { +VAL_ 234 State1 123 "Description 1" 0 "Description 2" 90903489 "Big value and special characters &$§())!" ;)"; + const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); + + auto parser = libdbc::DbcParser(); + parser.parse_file(filename.c_str()); + + 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); + REQUIRE(parser.get_messages().at(0).getSignals().at(1).svDescriptions.size() == 0); + + const auto signal = parser.get_messages().at(0).getSignals().at(0); + REQUIRE(signal.svDescriptions.at(0).value == 123); + REQUIRE(signal.svDescriptions.at(0).description == "Description 1"); + REQUIRE(signal.svDescriptions.at(1).value == 0); + REQUIRE(signal.svDescriptions.at(1).description == "Description 2"); + REQUIRE(signal.svDescriptions.at(2).value == 90903489); + REQUIRE(signal.svDescriptions.at(2).description == "Big value and special characters &$§())!"); +} + +TEST_CASE("Signal Value Description Extended CAN id") { std::string dbc_contents = PRIMITIVE_DBC + 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 -VAL_ 3221225472 State1 123 "Description 1" 0 "Description 2" 4000000000 "Big value and special characters &$§())!" ;)"; - const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); - - auto parser = libdbc::DbcParser(); - parser.parse_file(filename.c_str()); - - 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); - REQUIRE(parser.get_messages().at(0).getSignals().at(1).svDescriptions.size() == 0); - - const auto signal = parser.get_messages().at(0).getSignals().at(0); - REQUIRE(signal.svDescriptions.at(0).value == 123); - REQUIRE(signal.svDescriptions.at(0).description == "Description 1"); - REQUIRE(signal.svDescriptions.at(1).value == 0); - REQUIRE(signal.svDescriptions.at(1).description == "Description 2"); - REQUIRE(signal.svDescriptions.at(2).value == 4000000000); - REQUIRE(signal.svDescriptions.at(2).description == "Big value and special characters &$§())!"); -} - -TEST_CASE("Signal Value Multiple VAL_") { +VAL_ 3221225472 State1 123 "Description 1" 0 "Description 2" 4000000000 "Big value and special characters &$§())!" ;)"; + const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); + + auto parser = libdbc::DbcParser(); + parser.parse_file(filename.c_str()); + + 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); + REQUIRE(parser.get_messages().at(0).getSignals().at(1).svDescriptions.size() == 0); + + const auto signal = parser.get_messages().at(0).getSignals().at(0); + REQUIRE(signal.svDescriptions.at(0).value == 123); + REQUIRE(signal.svDescriptions.at(0).description == "Description 1"); + REQUIRE(signal.svDescriptions.at(1).value == 0); + REQUIRE(signal.svDescriptions.at(1).description == "Description 2"); + REQUIRE(signal.svDescriptions.at(2).value == 4000000000); + REQUIRE(signal.svDescriptions.at(2).description == "Big value and special characters &$§())!"); +} + +TEST_CASE("Signal Value Multiple VAL_") { std::string dbc_contents = PRIMITIVE_DBC + 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" @@ -209,32 +209,32 @@ 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" ; -VAL_ 123 State1 123 "Description 3" 0 "Description 4" ;)"; - const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); - - auto parser = libdbc::DbcParser(); - parser.parse_file(filename.c_str()); - - 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); - REQUIRE(parser.get_messages().at(0).getSignals().at(1).svDescriptions.size() == 0); - REQUIRE(parser.get_messages().at(1).getSignals().at(0).svDescriptions.size() == 2); - REQUIRE(parser.get_messages().at(1).getSignals().at(1).svDescriptions.size() == 0); - - const auto signal = parser.get_messages().at(0).getSignals().at(0); - REQUIRE(signal.svDescriptions.at(0).value == 123); - REQUIRE(signal.svDescriptions.at(0).description == "Description 1"); - REQUIRE(signal.svDescriptions.at(1).value == 0); - REQUIRE(signal.svDescriptions.at(1).description == "Description 2"); - - const auto signal2 = parser.get_messages().at(1).getSignals().at(0); - REQUIRE(signal2.svDescriptions.at(0).value == 123); - REQUIRE(signal2.svDescriptions.at(0).description == "Description 3"); - REQUIRE(signal2.svDescriptions.at(1).value == 0); - REQUIRE(signal2.svDescriptions.at(1).description == "Description 4"); -} +VAL_ 123 State1 123 "Description 3" 0 "Description 4" ;)"; + const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); + + auto parser = libdbc::DbcParser(); + parser.parse_file(filename.c_str()); + + 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); + REQUIRE(parser.get_messages().at(0).getSignals().at(1).svDescriptions.size() == 0); + REQUIRE(parser.get_messages().at(1).getSignals().at(0).svDescriptions.size() == 2); + REQUIRE(parser.get_messages().at(1).getSignals().at(1).svDescriptions.size() == 0); + + const auto signal = parser.get_messages().at(0).getSignals().at(0); + REQUIRE(signal.svDescriptions.at(0).value == 123); + REQUIRE(signal.svDescriptions.at(0).description == "Description 1"); + REQUIRE(signal.svDescriptions.at(1).value == 0); + REQUIRE(signal.svDescriptions.at(1).description == "Description 2"); + + const auto signal2 = parser.get_messages().at(1).getSignals().at(0); + REQUIRE(signal2.svDescriptions.at(0).value == 123); + REQUIRE(signal2.svDescriptions.at(0).description == "Description 3"); + REQUIRE(signal2.svDescriptions.at(1).value == 0); + REQUIRE(signal2.svDescriptions.at(1).description == "Description 4"); +} diff --git a/test/test_utils.cpp b/test/test_utils.cpp index ea3d594..fe7a064 100644 --- a/test/test_utils.cpp +++ b/test/test_utils.cpp @@ -1,37 +1,37 @@ -#include "testing_utils/defines.hpp" -#include -#include - -#include - -using namespace utils; - -TEST_CASE("Basic file input with safe get_line that is non line ending specific", "") { - SECTION("Verify various line ending input files") { - std::ifstream TextFile; - std::string test; - - TextFile.open(TEXT_FILE, std::ios::in); - CHECK(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); - REQUIRE(test == ""); - StreamHandler::get_line(TextFile, test); - REQUIRE(test == "Make sure things pass with this"); - StreamHandler::get_line(TextFile, test); - REQUIRE(test == "Who knows what might happen."); - - TextFile.close(); - } - } -} - -TEST_CASE("Test line finding utility functions", "") { - std::string line; - std::string test_string = +#include "testing_utils/defines.hpp" +#include +#include + +#include + +using namespace utils; + +TEST_CASE("Basic file input with safe get_line that is non line ending specific", "") { + SECTION("Verify various line ending input files") { + std::ifstream TextFile; + std::string test; + + TextFile.open(TEXT_FILE, std::ios::in); + CHECK(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); + REQUIRE(test == ""); + StreamHandler::get_line(TextFile, test); + REQUIRE(test == "Make sure things pass with this"); + StreamHandler::get_line(TextFile, test); + REQUIRE(test == "Who knows what might happen."); + + TextFile.close(); + } + } +} + +TEST_CASE("Test line finding utility functions", "") { + std::string line; + std::string test_string = "hello\n\ \n\ \n\ @@ -41,53 +41,53 @@ maybe not this one either\n\ \n\ Someone wrote something....\n\ b\n\ -end"; - - std::istringstream stream(test_string); - - SECTION("Test skipping empty lines") { - StreamHandler::get_line(stream, line); - - CHECK(line == "hello"); - - StreamHandler::get_next_non_blank_line(stream, line); - REQUIRE(line == "this is not blank"); - - StreamHandler::skip_to_next_blank_line(stream, line); - REQUIRE(line == ""); - - StreamHandler::get_next_non_blank_line(stream, line); - REQUIRE(line == "Someone wrote something...."); - - StreamHandler::get_next_non_blank_line(stream, line); - REQUIRE(line == " b"); - - StreamHandler::get_next_non_blank_line(stream, line); - REQUIRE(line == "end"); - - SECTION("Test end of the files", "[edge case]") { - StreamHandler::get_next_non_blank_line(stream, line); - REQUIRE(line == ""); - - StreamHandler::skip_to_next_blank_line(stream, line); - REQUIRE(line == ""); - } - } -} - -TEST_CASE("Test the string trim feature", "[string]") { - std::string s = " there might be some white space.... "; - - REQUIRE(String::trim(s) == "there might be some white space...."); -} - -TEST_CASE("Test string split feature", "[string]") { - std::string s = "name1 name2 name3 name4 name5 "; - std::vector vs = {"name1", "name2", "name3", "name4", "name5"}; - - std::vector v; - - String::split(s, v); - - REQUIRE(v == vs); -} +end"; + + std::istringstream stream(test_string); + + SECTION("Test skipping empty lines") { + StreamHandler::get_line(stream, line); + + CHECK(line == "hello"); + + StreamHandler::get_next_non_blank_line(stream, line); + REQUIRE(line == "this is not blank"); + + StreamHandler::skip_to_next_blank_line(stream, line); + REQUIRE(line == ""); + + StreamHandler::get_next_non_blank_line(stream, line); + REQUIRE(line == "Someone wrote something...."); + + StreamHandler::get_next_non_blank_line(stream, line); + REQUIRE(line == " b"); + + StreamHandler::get_next_non_blank_line(stream, line); + REQUIRE(line == "end"); + + SECTION("Test end of the files", "[edge case]") { + StreamHandler::get_next_non_blank_line(stream, line); + REQUIRE(line == ""); + + StreamHandler::skip_to_next_blank_line(stream, line); + REQUIRE(line == ""); + } + } +} + +TEST_CASE("Test the string trim feature", "[string]") { + std::string s = " there might be some white space.... "; + + REQUIRE(String::trim(s) == "there might be some white space...."); +} + +TEST_CASE("Test string split feature", "[string]") { + std::string s = "name1 name2 name3 name4 name5 "; + std::vector vs = {"name1", "name2", "name3", "name4", "name5"}; + + std::vector v; + + String::split(s, v); + + REQUIRE(v == vs); +} From 604fdafb4be8ddb8ae1b100b197d6464007a5939 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Fri, 15 Mar 2024 21:40:43 -0400 Subject: [PATCH 08/47] fix(utils): cleaned up clang-tidy warnings in utils.cpp --- src/utils.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/utils.cpp b/src/utils.cpp index ed715cb..d2ea6b7 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -13,10 +13,10 @@ std::istream& StreamHandler::get_line(std::istream& stream, std::string& line) { std::getline(stream, newline); // Windows CRLF (\r\n) - if (newline.size() && newline[newline.size() - 1] == '\r') { + if (!newline.empty() && newline[newline.size() - 1] == '\r') { line = newline.substr(0, newline.size() - 1); // MacOS LF (\r) - } else if (newline.size() && newline[newline.size()] == '\r') { + } else if (!newline.empty() && newline[newline.size()] == '\r') { line = newline.replace(newline.size(), 1, "\n"); } else { line = newline; @@ -74,7 +74,9 @@ std::string String::trim(const std::string& line) { double String::convert_to_double(const std::string& value, double default_value) { double converted_value = default_value; - fast_float::from_chars(value.data(), value.data() + value.size(), converted_value); + auto begin = value.begin(); + auto end = value.end(); + fast_float::from_chars(&(*begin), &(*end), converted_value); return converted_value; } From b138a2f0ad2d40a50e3106b6ed9dac3f86a9b353 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Sat, 16 Mar 2024 12:07:19 -0400 Subject: [PATCH 09/47] fix(clang-tidy): Fixing the warning from clang-tidy of signal and message source files --- include/libdbc/message.hpp | 2 +- src/message.cpp | 69 +++++++++++++++++++++----------------- src/signal.cpp | 4 +-- 3 files changed, 41 insertions(+), 34 deletions(-) diff --git a/include/libdbc/message.hpp b/include/libdbc/message.hpp index a018a31..05bd022 100644 --- a/include/libdbc/message.hpp +++ b/include/libdbc/message.hpp @@ -24,7 +24,7 @@ struct Message { ParseSignalsStatus parseSignals(const std::vector& data, std::vector& values) const; void appendSignal(const Signal& signal); - const std::vector getSignals() const; + std::vector getSignals() const; uint32_t id() const; uint8_t size() const; const std::string& name() const; diff --git a/src/message.cpp b/src/message.cpp index 89b47ac..791ecc9 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -1,10 +1,17 @@ -#include #include #include namespace libdbc { -Message::Message(uint32_t id, const std::string& name, uint8_t size, const std::string& node) - : m_id(id) + +constexpr unsigned ONE_BYTE = 8; +constexpr unsigned TWO_BYTES = 16; +constexpr unsigned FOUR_BYTES = 32; +constexpr unsigned EIGHT_BYTES = 64; + +constexpr unsigned SEVEN_BITS = 7; + +Message::Message(uint32_t message_id, const std::string& name, uint8_t size, const std::string& node) + : m_id(message_id) , m_name(name) , m_size(size) , m_node(node) { @@ -16,52 +23,52 @@ bool Message::operator==(const Message& rhs) const { Message::ParseSignalsStatus Message::parseSignals(const std::vector& data, std::vector& values) const { auto size = data.size(); - if (size > 8) { + if (size > ONE_BYTE) { return ParseSignalsStatus::ErrorMessageToLong; // not supported yet } uint64_t data_little_endian = 0; uint64_t data_big_endian = 0; for (size_t 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]; + data_little_endian |= ((uint64_t)data[i]) << i * ONE_BYTE; + data_big_endian = (data_big_endian << ONE_BYTE) | (uint64_t)data[i]; } // TODO: does this also work on a big endian machine? const auto len = size * 8; - uint64_t v = 0; + uint64_t value = 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); + uint32_t start_bit = ONE_BYTE * (signal.start_bit / ONE_BYTE) + (SEVEN_BITS - (signal.start_bit % ONE_BYTE)); // Calculation taken from python CAN + value = data_big_endian << start_bit; + value = value >> (len - signal.size); } else { - v = data_little_endian >> signal.start_bit; + value = data_little_endian >> signal.start_bit; } if (signal.is_signed && signal.size > 1) { switch (signal.size) { - case 8: - values.push_back(static_cast(v) * signal.factor + signal.offset); + case ONE_BYTE: + values.push_back(static_cast(value) * signal.factor + signal.offset); break; - case 16: - values.push_back(static_cast(v) * signal.factor + signal.offset); + case TWO_BYTES: + values.push_back(static_cast(value) * signal.factor + signal.offset); break; - case 32: - values.push_back(static_cast(v) * signal.factor + signal.offset); + case FOUR_BYTES: + values.push_back(static_cast(value) * signal.factor + signal.offset); break; - case 64: - values.push_back(static_cast(v) * signal.factor + signal.offset); + case EIGHT_BYTES: + values.push_back(static_cast(value) * signal.factor + signal.offset); break; default: { // 2 complement -> decimal - const int negative = (v & (1ull << (signal.size - 1))) != 0; - int64_t nativeInt; - if (negative) { - nativeInt = static_cast(v | ~((1ull << signal.size) - 1)); // invert all bits above signal.size + const bool is_negative = (value & (1ULL << (signal.size - 1))) != 0; + int64_t nativeInt = 0; + if (is_negative) { + nativeInt = static_cast(value | ~((1ULL << signal.size) - 1)); // invert all bits above signal.size } else { - nativeInt = static_cast(v & ((1ull << signal.size) - 1)); // masking + nativeInt = static_cast(value & ((1ULL << signal.size) - 1)); // masking } values.push_back(static_cast(nativeInt) * signal.factor + signal.offset); break; @@ -69,8 +76,8 @@ Message::ParseSignalsStatus Message::parseSignals(const std::vector& da } } else { // use only the relevant bits - v = v & ((1 << signal.size) - 1); // masking - values.push_back(static_cast(v) * signal.factor + signal.offset); + value = value & ((1 << signal.size) - 1); // masking + values.push_back(static_cast(value) * signal.factor + signal.offset); } } return ParseSignalsStatus::Success; @@ -80,7 +87,7 @@ void Message::appendSignal(const Signal& signal) { m_signals.push_back(signal); } -const std::vector Message::getSignals() const { +std::vector Message::getSignals() const { return m_signals; } @@ -96,10 +103,10 @@ const std::string& Message::name() const { return m_name; } -void Message::addValueDescription(const std::string& signal_name, const std::vector& vd) { - for (auto& s : m_signals) { - if (s.name.compare(signal_name) == 0) { - s.svDescriptions = vd; +void Message::addValueDescription(const std::string& signal_name, const std::vector& value_descriptor) { + for (auto& signal : m_signals) { + if (signal.name == signal_name) { + signal.svDescriptions = value_descriptor; return; } } diff --git a/src/signal.cpp b/src/signal.cpp index b9ce591..edb8407 100644 --- a/src/signal.cpp +++ b/src/signal.cpp @@ -47,8 +47,8 @@ std::ostream& operator<<(std::ostream& out, const Signal& sig) { out << "Min: " << sig.min << ", Max: " << sig.max << ", "; out << "Unit: (" << sig.unit << "), "; out << "receivers: "; - for (const auto& r : sig.receivers) { - out << r; + for (const auto& reciever : sig.receivers) { + out << reciever; } return out << "}"; } From 694a835a295dcd888a28b45dc2cdfa5daf4e8849 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Sat, 16 Mar 2024 12:28:15 -0400 Subject: [PATCH 10/47] fix(dbc): cleaning up magic numbers and short variable names in dbc.cpp --- src/dbc.cpp | 173 +++++++++++++++++++++++++++++----------------------- 1 file changed, 96 insertions(+), 77 deletions(-) diff --git a/src/dbc.cpp b/src/dbc.cpp index d78c32e..7eec99a 100644 --- a/src/dbc.cpp +++ b/src/dbc.cpp @@ -17,14 +17,33 @@ const auto byteOrderPattern = "([0-1])"; const auto signPattern = "(\\+|\\-)"; const auto scalePattern = "(\\d+\\.?(\\d+)?)"; // Non negative float const auto offsetPattern = floatPattern; +// NOLINTNEXTLINE -- Disable warning for runtime initialization and can throw. Can't fix until newer c++ version with constexpr const auto offsetScalePattern = std::string("\\(") + scalePattern + "\\," + offsetPattern + "\\)"; const auto minPattern = floatPattern; const auto maxPattern = floatPattern; +// NOLINTNEXTLINE -- Disable warning for runtime initialization and can throw. Can't fix until newer c++ version with constexpr const auto minMaxPattern = std::string("\\[") + minPattern + "\\|" + maxPattern + "\\]"; const auto unitPattern = "\"(.*)\""; // Random string const auto receiverPattern = "([\\w\\,]+|Vector__XXX)*"; const auto whiteSpace = "\\s"; +constexpr unsigned SIGNAL_NAME_GROUP = 2; +constexpr unsigned SIGNAL_START_BIT_GROUP = 3; +constexpr unsigned SIGNAL_SIZE_GROUP = 4; +constexpr unsigned SIGNAL_ENDIAN_GROUP = 5; +constexpr unsigned SIGNAL_SIGNED_GROUP = 6; +constexpr unsigned SIGNAL_FACTOR_GROUP = 7; +constexpr unsigned SIGNAL_OFFSET_GROUP = 9; +constexpr unsigned SIGNAL_MIN_GROUP = 11; +constexpr unsigned SIGNAL_MAX_GROUP = 13; +constexpr unsigned SIGNAL_UNIT_GROUP = 15; +constexpr unsigned SIGNAL_RECIEVER_GROUP = 16; + +constexpr unsigned MESSAGE_ID_GROUP = 2; +constexpr unsigned MESSAGE_NAME_GROUP = 3; +constexpr unsigned MESSAGE_SIZE_GROUP = 4; +constexpr unsigned MESSAGE_NODE_GROUP = 5; + enum VALToken { Identifier = 0, CANId, SignalName, Value, Description }; struct VALObject { @@ -33,81 +52,83 @@ struct VALObject { std::vector vd; }; -static bool parseVal(const std::string& str, VALObject& obj); -bool parseVal(const std::string& str, VALObject& obj) { +static bool parse_value(const std::string& str, VALObject& obj); + +bool parse_value(const std::string& str, VALObject& obj) { obj.signal_name = ""; obj.vd.clear(); auto state = Identifier; - const char* a = str.data(); - Signal::SignalValueDescriptions vd; + const char* value_data = str.data(); + Signal::SignalValueDescriptions value_description; for (;;) { switch (state) { case Identifier: { - if (*a != 'V') { + if (*value_data != 'V') { return false; } - a++; - if (*a != 'A') { + value_data++; + if (*value_data != 'A') { return false; } - a++; - if (*a != 'L') { + value_data++; + if (*value_data != 'L') { return false; } - a++; - if (*a != '_') { + value_data++; + if (*value_data != '_') { return false; } - a++; - if (*a != ' ') { + value_data++; + if (*value_data != ' ') { return false; } - a++; // skip whitespace + value_data++; // skip whitespace state = CANId; break; } case CANId: { std::string can_id_str; - while (*a >= '0' && *a <= '9') { - can_id_str += *a; - a++; + while (*value_data >= '0' && *value_data <= '9') { + can_id_str += *value_data; + value_data++; } if (can_id_str.empty()) { return false; } obj.can_id = static_cast(std::stoul(can_id_str)); - if (*a != ' ') { + if (*value_data != ' ') { return false; } - a++; // skip whitespace + value_data++; // skip whitespace state = SignalName; break; } case SignalName: { - if ((*a >= 'a' && *a <= 'z') || (*a >= 'A' && *a <= 'Z') || *a == '_') { - obj.signal_name += *a; + if ((*value_data >= 'a' && *value_data <= 'z') || (*value_data >= 'A' && *value_data <= 'Z') || *value_data == '_') { + obj.signal_name += *value_data; } else { return false; } - a++; - while ((*a >= 'a' && *a <= 'z') || (*a >= 'A' && *a <= 'Z') || *a == '_' || (*a >= '0' && *a <= '9')) { - obj.signal_name += *a; - a++; + value_data++; + while ((*value_data >= 'a' && *value_data <= 'z') || (*value_data >= 'A' && *value_data <= 'Z') || *value_data == '_' + || (*value_data >= '0' && *value_data <= '9')) { + obj.signal_name += *value_data; + value_data++; } - if (*a != ' ') { + if (*value_data != ' ') { return false; } - a++; // skip whitespace + value_data++; // skip whitespace state = Value; break; } case Value: { std::string value_str; - while (*a >= '0' && *a <= '9') { - value_str += *a; - a++; + while (*value_data >= '0' && *value_data <= '9') { + value_str += *value_data; + value_data++; } - if (*a == ';') { + if (*value_data == ';') { if (value_str.empty()) { return true; } @@ -117,35 +138,35 @@ bool parseVal(const std::string& str, VALObject& obj) { return false; } - if (*a != ' ') { + if (*value_data != ' ') { return false; } - a++; // skip whitespace - vd.value = (uint32_t)std::stoul(value_str); + value_data++; // skip whitespace + value_description.value = (uint32_t)std::stoul(value_str); state = Description; break; } case Description: { std::string desc; - if (*a != '"') { + if (*value_data != '"') { return false; } - a++; - while (*a != '"' && *a != 0) { - desc += *a; - a++; + value_data++; + while (*value_data != '"' && *value_data != 0) { + desc += *value_data; + value_data++; } - if (*a == 0) { + if (*value_data == 0) { return false; } - a++; - if (*a != ' ') { + value_data++; + if (*value_data != ' ') { return false; } - a++; // skip whitespace + value_data++; // skip whitespace - vd.description = desc; - obj.vd.push_back(vd); + value_description.description = desc; + obj.vd.push_back(value_description); state = Value; break; @@ -156,9 +177,7 @@ bool parseVal(const std::string& str, VALObject& obj) { } DbcParser::DbcParser() - : version("") - , nodes() - , version_re("^(VERSION)\\s\"(.*)\"") + : version_re("^(VERSION)\\s\"(.*)\"") , bit_timing_re("^(BS_:)") , name_space_re("^(NS_)\\s\\:") , node_re("^(BU_:)\\s((?:[\\w]+?\\s?)*)") @@ -171,18 +190,18 @@ DbcParser::DbcParser() } void DbcParser::parse_file(const std::string& file) { - std::ifstream s(file.c_str()); + std::ifstream stream(file.c_str()); std::string line; std::vector lines; messages.clear(); - parse_dbc_header(s); + parse_dbc_header(stream); - parse_dbc_nodes(s); + parse_dbc_nodes(stream); - while (!s.eof()) { - utils::StreamHandler::get_next_non_blank_line(s, line); + while (!stream.eof()) { + utils::StreamHandler::get_next_non_blank_line(stream, line); lines.push_back(line); } @@ -201,9 +220,9 @@ std::vector DbcParser::get_messages() const { return messages; } -Message::ParseSignalsStatus DbcParser::parseMessage(const uint32_t id, const std::vector& data, std::vector& out_values) { +Message::ParseSignalsStatus DbcParser::parseMessage(const uint32_t message_id, const std::vector& data, std::vector& out_values) { for (const auto& message : messages) { - if (message.id() == id) { + if (message.id() == message_id) { return message.parseSignals(data, out_values); } } @@ -242,60 +261,60 @@ void DbcParser::parse_dbc_nodes(std::istream& file_stream) { } if (match.length() > 2) { - std::string n = match.str(2); - utils::String::split(n, nodes); + std::string node = match.str(2); + utils::String::split(node, nodes); } } void DbcParser::parse_dbc_messages(const std::vector& lines) { std::smatch match; - std::vector sv; + std::vector signal_value; VALObject obj{}; for (const auto& line : lines) { if (std::regex_search(line, match, message_re)) { - uint32_t id = static_cast(std::stoul(match.str(2))); - std::string name = match.str(3); - uint8_t size = static_cast(std::stoul(match.str(4))); - std::string node = match.str(5); + uint32_t message_id = static_cast(std::stoul(match.str(MESSAGE_ID_GROUP))); + std::string name = match.str(MESSAGE_NAME_GROUP); + uint8_t size = static_cast(std::stoul(match.str(MESSAGE_SIZE_GROUP))); + std::string node = match.str(MESSAGE_NODE_GROUP); - Message msg(id, name, size, node); + Message msg(message_id, name, size, node); messages.push_back(msg); continue; } if (std::regex_search(line, match, signal_re)) { - std::string name = match.str(2); + std::string name = match.str(SIGNAL_NAME_GROUP); bool is_multiplexed = false; // No support yet - uint32_t start_bit = static_cast(std::stoul(match.str(3))); - uint32_t size = static_cast(std::stoul(match.str(4))); - bool is_bigendian = (std::stoul(match.str(5)) == 0); - bool is_signed = (match.str(6) == "-"); + uint32_t start_bit = static_cast(std::stoul(match.str(SIGNAL_START_BIT_GROUP))); + uint32_t size = static_cast(std::stoul(match.str(SIGNAL_SIZE_GROUP))); + bool is_bigendian = (std::stoul(match.str(SIGNAL_ENDIAN_GROUP)) == 0); + bool is_signed = (match.str(SIGNAL_SIGNED_GROUP) == "-"); - double factor = utils::String::convert_to_double(match.str(7).data()); - double offset = utils::String::convert_to_double(match.str(9).data()); - double min = utils::String::convert_to_double(match.str(11).data()); - double max = utils::String::convert_to_double(match.str(13).data()); + double factor = utils::String::convert_to_double(match.str(SIGNAL_FACTOR_GROUP)); + double offset = utils::String::convert_to_double(match.str(SIGNAL_OFFSET_GROUP)); + double min = utils::String::convert_to_double(match.str(SIGNAL_MIN_GROUP)); + double max = utils::String::convert_to_double(match.str(SIGNAL_MAX_GROUP)); - std::string unit = match.str(15); + std::string unit = match.str(SIGNAL_UNIT_GROUP); std::vector receivers; - utils::String::split(match.str(16), receivers, ','); + utils::String::split(match.str(SIGNAL_RECIEVER_GROUP), receivers, ','); Signal sig(name, is_multiplexed, start_bit, size, is_bigendian, is_signed, factor, offset, min, max, unit, receivers); messages.back().appendSignal(sig); continue; } - if (parseVal(line, obj)) { - sv.push_back(obj); + if (parse_value(line, obj)) { + signal_value.push_back(obj); continue; } } - for (const auto& signal : sv) { + for (const auto& signal : signal_value) { for (auto& msg : messages) { if (msg.id() == signal.can_id) { msg.addValueDescription(signal.signal_name, signal.vd); From 78629e447bbcae6ca27e378555da0031fbe60ca1 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Sat, 16 Mar 2024 13:19:37 -0400 Subject: [PATCH 11/47] refactor(value_parsing): removed the state machine based parsing in favor of regex expressions --- include/libdbc/dbc.hpp | 1 + src/dbc.cpp | 151 +++++++---------------------------------- 2 files changed, 26 insertions(+), 126 deletions(-) diff --git a/include/libdbc/dbc.hpp b/include/libdbc/dbc.hpp index 109b89f..7486db3 100644 --- a/include/libdbc/dbc.hpp +++ b/include/libdbc/dbc.hpp @@ -43,6 +43,7 @@ class DbcParser : public Parser { const std::regex name_space_re; const std::regex node_re; const std::regex message_re; + const std::regex value_re; const std::regex signal_re; void parse_dbc_header(std::istream& file_stream); diff --git a/src/dbc.cpp b/src/dbc.cpp index 7eec99a..4ad8780 100644 --- a/src/dbc.cpp +++ b/src/dbc.cpp @@ -4,6 +4,7 @@ #include #include +#include namespace libdbc { @@ -52,136 +53,13 @@ struct VALObject { std::vector vd; }; -static bool parse_value(const std::string& str, VALObject& obj); - -bool parse_value(const std::string& str, VALObject& obj) { - obj.signal_name = ""; - obj.vd.clear(); - auto state = Identifier; - const char* value_data = str.data(); - Signal::SignalValueDescriptions value_description; - for (;;) { - switch (state) { - case Identifier: { - if (*value_data != 'V') { - return false; - } - value_data++; - if (*value_data != 'A') { - return false; - } - value_data++; - if (*value_data != 'L') { - return false; - } - value_data++; - if (*value_data != '_') { - return false; - } - value_data++; - if (*value_data != ' ') { - return false; - } - value_data++; // skip whitespace - state = CANId; - break; - } - case CANId: { - std::string can_id_str; - while (*value_data >= '0' && *value_data <= '9') { - can_id_str += *value_data; - value_data++; - } - if (can_id_str.empty()) { - return false; - } - obj.can_id = static_cast(std::stoul(can_id_str)); - if (*value_data != ' ') { - return false; - } - value_data++; // skip whitespace - state = SignalName; - break; - } - case SignalName: { - if ((*value_data >= 'a' && *value_data <= 'z') || (*value_data >= 'A' && *value_data <= 'Z') || *value_data == '_') { - obj.signal_name += *value_data; - } else { - return false; - } - value_data++; - while ((*value_data >= 'a' && *value_data <= 'z') || (*value_data >= 'A' && *value_data <= 'Z') || *value_data == '_' - || (*value_data >= '0' && *value_data <= '9')) { - obj.signal_name += *value_data; - value_data++; - } - if (*value_data != ' ') { - return false; - } - value_data++; // skip whitespace - state = Value; - break; - } - case Value: { - std::string value_str; - while (*value_data >= '0' && *value_data <= '9') { - value_str += *value_data; - value_data++; - } - if (*value_data == ';') { - if (value_str.empty()) { - return true; - } - return false; - } - if (value_str.empty()) { - return false; - } - - if (*value_data != ' ') { - return false; - } - value_data++; // skip whitespace - value_description.value = (uint32_t)std::stoul(value_str); - state = Description; - break; - } - case Description: { - std::string desc; - if (*value_data != '"') { - return false; - } - value_data++; - while (*value_data != '"' && *value_data != 0) { - desc += *value_data; - value_data++; - } - if (*value_data == 0) { - return false; - } - value_data++; - if (*value_data != ' ') { - return false; - } - value_data++; // skip whitespace - - value_description.description = desc; - obj.vd.push_back(value_description); - - state = Value; - break; - } - } - } - return false; -} - DbcParser::DbcParser() : 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)") + , value_re("^(VAL_)\\s(\\d+)\\s(\\w+)((?:\\s(\\d+)\\s\"([^\"]*)\")+)\\s;$") , // NOTE: No multiplex support yet signal_re(std::string("^") + whiteSpace + signalIdentifierPattern + whiteSpace + namePattern + whiteSpace + "\\:" + whiteSpace + bitStartPattern + "\\|" @@ -271,7 +149,6 @@ void DbcParser::parse_dbc_messages(const std::vector& lines) { std::vector signal_value; - VALObject obj{}; for (const auto& line : lines) { if (std::regex_search(line, match, message_re)) { uint32_t message_id = static_cast(std::stoul(match.str(MESSAGE_ID_GROUP))); @@ -308,7 +185,29 @@ void DbcParser::parse_dbc_messages(const std::vector& lines) { continue; } - if (parse_value(line, obj)) { + if (std::regex_search(line, match, value_re)) { + uint32_t message_id = static_cast(std::stoul(match.str(2))); + std::string signal_name = match.str(3); + + // Loop over the rest of the descriptions + std::string rest_of_descriptions = match.str(4); + std::regex description_re("\\s(\\d+)\\s\"([^\"]*)\""); + + std::sregex_iterator desc_iter(rest_of_descriptions.begin(), rest_of_descriptions.end(), description_re); + std::sregex_iterator desc_end; + + std::vector values{}; + while (desc_iter != desc_end) { + std::smatch desc_match = *desc_iter; + uint32_t number = static_cast(std::stoul(desc_match.str(1))); + std::string text = desc_match.str(2); + + values.push_back(Signal::SignalValueDescriptions{number, text}); + ++desc_iter; + } + + VALObject obj{message_id, signal_name, values}; + signal_value.push_back(obj); continue; } From df07224827d98843c185cfd0502a8307a0bc47a0 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Sat, 16 Mar 2024 13:35:18 -0400 Subject: [PATCH 12/47] fix(clang-tidy): fixed all clang-tidy warnings within the library. Added exception for default destructor of special member functions in clang tidy. --- .clang-tidy | 2 +- include/libdbc/dbc.hpp | 20 +++++++++----------- include/libdbc/exceptions/error.hpp | 6 +++--- include/libdbc/message.hpp | 4 ++-- include/libdbc/signal.hpp | 2 +- include/libdbc/utils/utils.hpp | 4 ++-- 6 files changed, 18 insertions(+), 20 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index cc7ef80..4b627d2 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -140,7 +140,7 @@ CheckOptions: readability-suspicious-call-argument.DiceSimilarAbove: '70' readability-suspicious-call-argument.Dice: 'true' readability-suspicious-call-argument.Abbreviation: 'true' - cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor: 'false' + cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor: 'true' readability-identifier-length.IgnoredLoopCounterNames: '^[ijk_]$' cert-dcl37-c.Invert: 'false' cert-dcl37-c.AggressiveDependentMemberLookup: 'false' diff --git a/include/libdbc/dbc.hpp b/include/libdbc/dbc.hpp index 7486db3..50178f8 100644 --- a/include/libdbc/dbc.hpp +++ b/include/libdbc/dbc.hpp @@ -23,28 +23,26 @@ class DbcParser : public Parser { public: DbcParser(); - virtual ~DbcParser() = default; - - virtual void parse_file(const std::string& file) final override; + void parse_file(const std::string& file) override; std::string get_version() const; std::vector get_nodes() const; std::vector get_messages() const; - Message::ParseSignalsStatus parseMessage(const uint32_t id, const std::vector& data, std::vector& out_values); + Message::ParseSignalsStatus parseMessage(uint32_t message_id, const std::vector& data, std::vector& out_values); private: std::string version; std::vector nodes; std::vector messages; - 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 value_re; - const std::regex signal_re; + std::regex version_re; + std::regex bit_timing_re; + std::regex name_space_re; + std::regex node_re; + std::regex message_re; + std::regex value_re; + std::regex signal_re; void parse_dbc_header(std::istream& file_stream); void parse_dbc_nodes(std::istream& file_stream); diff --git a/include/libdbc/exceptions/error.hpp b/include/libdbc/exceptions/error.hpp index a6a3653..4749d2d 100644 --- a/include/libdbc/exceptions/error.hpp +++ b/include/libdbc/exceptions/error.hpp @@ -1,20 +1,20 @@ #ifndef ERROR_HPP #define ERROR_HPP -#include +#include namespace libdbc { class exception : public std::exception { public: - const char* what() const throw() { + const char* what() const throw() override { return "libdbc exception occurred"; } }; class validity_error : public exception { public: - const char* what() const throw() { + const char* what() const throw() override { return "Invalid DBC file"; } }; diff --git a/include/libdbc/message.hpp b/include/libdbc/message.hpp index 05bd022..21527bf 100644 --- a/include/libdbc/message.hpp +++ b/include/libdbc/message.hpp @@ -11,7 +11,7 @@ namespace libdbc { struct Message { Message() = delete; virtual ~Message() = default; - explicit Message(uint32_t id, const std::string& name, uint8_t size, const std::string& node); + explicit Message(uint32_t message_id, const std::string& name, uint8_t size, const std::string& node); enum class ParseSignalsStatus { Success, @@ -39,7 +39,7 @@ struct Message { std::string m_node; std::vector m_signals; - friend std::ostream& operator<<(std::ostream& os, const Message& dt); + friend std::ostream& operator<<(std::ostream& out, const Message& msg); }; std::ostream& operator<<(std::ostream& out, const Message& msg); diff --git a/include/libdbc/signal.hpp b/include/libdbc/signal.hpp index cdfd018..4694f1e 100644 --- a/include/libdbc/signal.hpp +++ b/include/libdbc/signal.hpp @@ -41,7 +41,7 @@ struct Signal { double min, double max, std::string unit, - std::vector recievers); + std::vector receivers); virtual bool operator==(const Signal& rhs) const; bool operator<(const Signal& rhs) const; diff --git a/include/libdbc/utils/utils.hpp b/include/libdbc/utils/utils.hpp index 8763af6..6ab2292 100644 --- a/include/libdbc/utils/utils.hpp +++ b/include/libdbc/utils/utils.hpp @@ -35,10 +35,10 @@ class String { template static void split(const std::string& str, Container& cont, char delim = ' ') { - std::stringstream ss(str); + std::stringstream stream(str); std::string token; - while (std::getline(ss, token, delim)) { + while (std::getline(stream, token, delim)) { cont.push_back(token); } } From 8ad386ef359859d0a321678344a755647031e6d7 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Sat, 16 Mar 2024 16:37:00 -0400 Subject: [PATCH 13/47] feat(clang-tidy): Add warnings into errors for cmake command. Add naming conventions. --- .clang-tidy | 13 ++- CMakeLists.txt | 258 ++++++++++++++++++++++++------------------------- 2 files changed, 140 insertions(+), 131 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 4b627d2..2b65fe4 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -17,7 +17,7 @@ CheckOptions: cert-dcl16-c.NewSuffixes: 'L;LL;LU;LLU' cert-dcl51-cpp.AggressiveDependentMemberLookup: 'false' readability-identifier-naming.GetConfigPerFile: 'true' - cert-err61-cpp.MaxSize: '-1' + cert-err61-cpp.MaxSize: '10' cert-sig30-c.AsyncSafeFunctionSet: POSIX readability-inconsistent-declaration-parameter-name.Strict: 'false' cppcoreguidelines-macro-usage.CheckCapsOnly: 'false' @@ -45,7 +45,7 @@ CheckOptions: readability-suspicious-call-argument.JaroWinklerDissimilarBelow: '75' readability-suspicious-call-argument.SuffixSimilarAbove: '30' readability-suspicious-call-argument.Suffix: 'true' - cert-err09-cpp.MaxSize: '-1' + cert-err09-cpp.MaxSize: '10' cppcoreguidelines-narrowing-conversions.WarnOnIntegerNarrowingConversion: 'true' cppcoreguidelines-prefer-member-initializer.UseAssignment: 'false' cert-oop57-cpp.MemSetNames: '' @@ -156,5 +156,14 @@ CheckOptions: cert-dcl16-c.IgnoreMacros: 'true' llvm-else-after-return.WarnOnUnfixable: 'false' cert-msc32-c.DisallowedSeedTypes: 'time_t,std::time_t' + readability-identifier-naming.NamespaceCase: 'CamelCase' + readability-identifier-naming.UnionCase: 'CamelCase' + readability-identifier-naming.ClassCase: 'CamelCase' + readability-identifier-naming.ClassMemberCase: 'lower_case' + readability-identifier-naming.ClassMethodCase: 'lower_case' + readability-identifier-naming.StructCase: 'CamelCase' + readability-identifier-naming.MemberCase: 'lower_case' + readability-identifier-naming.MethodCase: 'lower_case' + readability-identifier-naming.FunctionCase: 'lower_case' ... diff --git a/CMakeLists.txt b/CMakeLists.txt index 362821f..539e72b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,129 +1,129 @@ -cmake_minimum_required(VERSION 3.16) - -# Keep this on one line for release checking -project(dbc VERSION 0.2.0 DESCRIPTION "C++ DBC Parser") - -# -- PROJECT OPTIONS -- # -option(DBC_ENABLE_TESTS "Enable Unittests" ON) -option(DBC_TEST_LOCALE_INDEPENDENCE "Used to deterime if the libary is locale agnostic when it comes to converting floats. You need `de_DE.UTF-8` locale installed for this testing." OFF) -option(DBC_GENERATE_DOCS "Use doxygen if installed to generated documentation files" OFF) -option(DBC_GENERATE_SINGLE_HEADER "This will run the generator for the single header file version. Default is OFF since we make a static build. Requires cargo installed." OFF) -# ---------------------- # - -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) - -# package -set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) -set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) -set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) -set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE) -set(CPACK_RESOURCE_FILE_README ${CMAKE_CURRENT_SOURCE_DIR}/README.md) -include(CPack) - -# specify the C++ standard -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED True) - -find_package(FastFloat QUIET) -if (NOT ${FastFloat_FOUND}) - include(FetchContent) - FetchContent_Declare( - FastFloat - GIT_REPOSITORY https://github.com/fastfloat/fast_float.git - GIT_TAG 1ea4f27b2aeee2859a1354a3c24cff52a116cad1 - ) - FetchContent_MakeAvailable(FastFloat) -endif() - -# add where to find the source files -list(APPEND SOURCE_FILES - ${PROJECT_SOURCE_DIR}/src/utils.cpp - ${PROJECT_SOURCE_DIR}/src/message.cpp - ${PROJECT_SOURCE_DIR}/src/signal.cpp - ${PROJECT_SOURCE_DIR}/src/dbc.cpp -) - -list(APPEND HEADER_FILES - ${PROJECT_SOURCE_DIR}/include/libdbc/dbc.hpp - ${PROJECT_SOURCE_DIR}/include/libdbc/message.hpp - ${PROJECT_SOURCE_DIR}/include/libdbc/signal.hpp - ${PROJECT_SOURCE_DIR}/include/libdbc/utils/utils.hpp - ${PROJECT_SOURCE_DIR}/include/libdbc/exceptions/error.hpp -) - -if(DBC_ENABLE_TESTS) - include(CTest) - add_subdirectory(test) -endif() - -if(DBC_GENERATE_DOCS) - add_subdirectory(doc) -endif() - -list(APPEND GCC_CLANG_COMPILE_FLAGS - -Wall -Wextra -Wpedantic - -Wconversion -Wint-in-bool-context - -Wmissing-declarations -Wmissing-field-initializers - -Werror -) - - -if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") - add_compile_options(/W4 /WX) -elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") - # Clang shadow warnings aren't as sensitive as gcc - add_compile_options(${GCC_CLANG_COMPILE_FLAGS} -Wshadow) -else() - add_compile_options(${GCC_CLANG_COMPILE_FLAGS}) -endif() - -add_library(${PROJECT_NAME} STATIC ${SOURCE_FILES}) -target_link_libraries(${PROJECT_NAME} FastFloat::fast_float) -target_include_directories(${PROJECT_NAME} PUBLIC - $ - $ -) -target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_11) - -target_sources(${PROJECT_NAME} INTERFACE FILE_SET HEADERS - TYPE HEADERS - BASE_DIRS ${PROJECT_SOURCE_DIR}/include/libdbc - FILES ${HEADER_FILES} -) - -if(DBC_GENERATE_SINGLE_HEADER) - add_custom_target(single_header ALL - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - COMMAND ${CMAKE_SOURCE_DIR}/scripts/create_single_header.sh - ) -endif() - -## Installation -# install lib -install(TARGETS ${PROJECT_NAME} - DESTINATION ${CMAKE_INSTALL_LIBDIR}) - -# install headers -install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/libdbc DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) - -# 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) - -# Clang tidy -add_custom_target(clang-tidy-check - clang-tidy -p ${CMAKE_BINARY_DIR}/compile_commands.json ${SOURCE_FILES} ${HEADER_FILES} - DEPENDS ${SOURCE_FILES} ${HEADER_FILES} -) - -add_custom_target(clang-tidy-dump - clang-tidy -checks=-*,clang-analyzer-*,clang-analyzer-cplusplus*,cert-*,cppcoreguidelines-*,portability-*,readability-*,clang-diagnostic-* -dump-config -p ${CMAKE_BINARY_DIR}/compile_commands.json ${SOURCE_FILES} ${HEADER_FILES} > ../.clang-tidy - DEPENDS ${SOURCE_FILES} ${HEADER_FILES} -) - -add_custom_target(clang-tidy-fix - clang-tidy -fix-notes -p ${CMAKE_BINARY_DIR}/compile_commands.json ${SOURCE_FILES} ${HEADER_FILES} - DEPENDS ${SOURCE_FILES} ${HEADER_FILES} -) \ No newline at end of file +cmake_minimum_required(VERSION 3.16) + +# Keep this on one line for release checking +project(dbc VERSION 0.2.0 DESCRIPTION "C++ DBC Parser") + +# -- PROJECT OPTIONS -- # +option(DBC_ENABLE_TESTS "Enable Unittests" ON) +option(DBC_TEST_LOCALE_INDEPENDENCE "Used to deterime if the libary is locale agnostic when it comes to converting floats. You need `de_DE.UTF-8` locale installed for this testing." OFF) +option(DBC_GENERATE_DOCS "Use doxygen if installed to generated documentation files" OFF) +option(DBC_GENERATE_SINGLE_HEADER "This will run the generator for the single header file version. Default is OFF since we make a static build. Requires cargo installed." OFF) +# ---------------------- # + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# package +set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) +set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) +set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) +set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE) +set(CPACK_RESOURCE_FILE_README ${CMAKE_CURRENT_SOURCE_DIR}/README.md) +include(CPack) + +# specify the C++ standard +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED True) + +find_package(FastFloat QUIET) +if (NOT ${FastFloat_FOUND}) + include(FetchContent) + FetchContent_Declare( + FastFloat + GIT_REPOSITORY https://github.com/fastfloat/fast_float.git + GIT_TAG 1ea4f27b2aeee2859a1354a3c24cff52a116cad1 + ) + FetchContent_MakeAvailable(FastFloat) +endif() + +# add where to find the source files +list(APPEND SOURCE_FILES + ${PROJECT_SOURCE_DIR}/src/utils.cpp + ${PROJECT_SOURCE_DIR}/src/message.cpp + ${PROJECT_SOURCE_DIR}/src/signal.cpp + ${PROJECT_SOURCE_DIR}/src/dbc.cpp +) + +list(APPEND HEADER_FILES + ${PROJECT_SOURCE_DIR}/include/libdbc/dbc.hpp + ${PROJECT_SOURCE_DIR}/include/libdbc/message.hpp + ${PROJECT_SOURCE_DIR}/include/libdbc/signal.hpp + ${PROJECT_SOURCE_DIR}/include/libdbc/utils/utils.hpp + ${PROJECT_SOURCE_DIR}/include/libdbc/exceptions/error.hpp +) + +if(DBC_ENABLE_TESTS) + include(CTest) + add_subdirectory(test) +endif() + +if(DBC_GENERATE_DOCS) + add_subdirectory(doc) +endif() + +list(APPEND GCC_CLANG_COMPILE_FLAGS + -Wall -Wextra -Wpedantic + -Wconversion -Wint-in-bool-context + -Wmissing-declarations -Wmissing-field-initializers + -Werror +) + + +if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + add_compile_options(/W4 /WX) +elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + # Clang shadow warnings aren't as sensitive as gcc + add_compile_options(${GCC_CLANG_COMPILE_FLAGS} -Wshadow) +else() + add_compile_options(${GCC_CLANG_COMPILE_FLAGS}) +endif() + +add_library(${PROJECT_NAME} STATIC ${SOURCE_FILES}) +target_link_libraries(${PROJECT_NAME} FastFloat::fast_float) +target_include_directories(${PROJECT_NAME} PUBLIC + $ + $ +) +target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_11) + +target_sources(${PROJECT_NAME} INTERFACE FILE_SET HEADERS + TYPE HEADERS + BASE_DIRS ${PROJECT_SOURCE_DIR}/include/libdbc + FILES ${HEADER_FILES} +) + +if(DBC_GENERATE_SINGLE_HEADER) + add_custom_target(single_header ALL + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMAND ${CMAKE_SOURCE_DIR}/scripts/create_single_header.sh + ) +endif() + +## Installation +# install lib +install(TARGETS ${PROJECT_NAME} + DESTINATION ${CMAKE_INSTALL_LIBDIR}) + +# install headers +install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/libdbc DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + +# 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) + +# Clang tidy +add_custom_target(clang-tidy-check + clang-tidy -p ${CMAKE_BINARY_DIR}/compile_commands.json -warnings-as-errors=* ${SOURCE_FILES} ${HEADER_FILES} + DEPENDS ${SOURCE_FILES} ${HEADER_FILES} +) + +add_custom_target(clang-tidy-dump + clang-tidy -checks=-*,clang-analyzer-*,clang-analyzer-cplusplus*,cert-*,cppcoreguidelines-*,portability-*,readability-*,clang-diagnostic-* -dump-config -p ${CMAKE_BINARY_DIR}/compile_commands.json ${SOURCE_FILES} ${HEADER_FILES} > ../.clang-tidy + DEPENDS ${SOURCE_FILES} ${HEADER_FILES} +) + +add_custom_target(clang-tidy-fix + clang-tidy -fix-notes -p ${CMAKE_BINARY_DIR}/compile_commands.json ${SOURCE_FILES} ${HEADER_FILES} + DEPENDS ${SOURCE_FILES} ${HEADER_FILES} +) From 62ab43912eacb11b07fa385bf3bc8906927a3582 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Sat, 16 Mar 2024 16:41:46 -0400 Subject: [PATCH 14/47] Adding timeout after finding out some windows debug builds were timing out --- .github/workflows/pipeline.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index b630847..af193f2 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -62,6 +62,7 @@ jobs: run: cmake --build build --parallel `nproc` - name: Run tests + timeout-minutes: 3 env: CTEST_OUTPUT_ON_FAILURE: 1 run: ctest --output-on-failure --test-dir build -j `nproc` @@ -98,6 +99,7 @@ jobs: shell: cmd - name: Run tests + timeout-minutes: 3 env: CTEST_OUTPUT_ON_FAILURE: 1 working-directory: ${{runner.workspace}} @@ -142,10 +144,11 @@ jobs: run: cmake --build build --parallel `sysctl -n hw.ncpu` - name: Run tests + timeout-minutes: 3 env: CTEST_OUTPUT_ON_FAILURE: 1 working-directory: ${{runner.workspace}} - run: ctest --output-on-failure --test-dir build -j `sysctl -n hw.ncpu` + run: ctest --output-on-failure --test-dir build -j `sysctl -n hw.ncpu` -V format-check: runs-on: ubuntu-latest From 20259bcc2b889d518c9cef104c736695a5ebd907 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Sat, 16 Mar 2024 16:50:25 -0400 Subject: [PATCH 15/47] fix(test): change while loop of the iterator for value description to for loop to try and prevent windows debug build from infinite loops --- src/dbc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dbc.cpp b/src/dbc.cpp index 4ad8780..385c9fb 100644 --- a/src/dbc.cpp +++ b/src/dbc.cpp @@ -194,10 +194,10 @@ void DbcParser::parse_dbc_messages(const std::vector& lines) { std::regex description_re("\\s(\\d+)\\s\"([^\"]*)\""); std::sregex_iterator desc_iter(rest_of_descriptions.begin(), rest_of_descriptions.end(), description_re); - std::sregex_iterator desc_end; + std::sregex_iterator desc_end = std::sregex_iterator(); std::vector values{}; - while (desc_iter != desc_end) { + for (std::sregex_iterator i = desc_iter; i != desc_end; ++i) { std::smatch desc_match = *desc_iter; uint32_t number = static_cast(std::stoul(desc_match.str(1))); std::string text = desc_match.str(2); From 048779b9f7f4db7f6c0a84de21f6c4c61940a5bf Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Sat, 16 Mar 2024 16:59:17 -0400 Subject: [PATCH 16/47] debug: Comment out the infinite loop that is hanging up the test in debug for windows builds --- src/dbc.cpp | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/dbc.cpp b/src/dbc.cpp index 385c9fb..9c10913 100644 --- a/src/dbc.cpp +++ b/src/dbc.cpp @@ -185,32 +185,32 @@ void DbcParser::parse_dbc_messages(const std::vector& lines) { continue; } - if (std::regex_search(line, match, value_re)) { - uint32_t message_id = static_cast(std::stoul(match.str(2))); - std::string signal_name = match.str(3); + // if (std::regex_search(line, match, value_re)) { + // uint32_t message_id = static_cast(std::stoul(match.str(2))); + // std::string signal_name = match.str(3); - // Loop over the rest of the descriptions - std::string rest_of_descriptions = match.str(4); - std::regex description_re("\\s(\\d+)\\s\"([^\"]*)\""); + // // Loop over the rest of the descriptions + // std::string rest_of_descriptions = match.str(4); + // std::regex description_re("\\s(\\d+)\\s\"([^\"]*)\""); - std::sregex_iterator desc_iter(rest_of_descriptions.begin(), rest_of_descriptions.end(), description_re); - std::sregex_iterator desc_end = std::sregex_iterator(); + // std::sregex_iterator desc_iter(rest_of_descriptions.begin(), rest_of_descriptions.end(), description_re); + // std::sregex_iterator desc_end = std::sregex_iterator(); - std::vector values{}; - for (std::sregex_iterator i = desc_iter; i != desc_end; ++i) { - std::smatch desc_match = *desc_iter; - uint32_t number = static_cast(std::stoul(desc_match.str(1))); - std::string text = desc_match.str(2); + // std::vector values{}; + // for (std::sregex_iterator i = desc_iter; i != desc_end; ++i) { + // std::smatch desc_match = *desc_iter; + // uint32_t number = static_cast(std::stoul(desc_match.str(1))); + // std::string text = desc_match.str(2); - values.push_back(Signal::SignalValueDescriptions{number, text}); - ++desc_iter; - } + // values.push_back(Signal::SignalValueDescriptions{number, text}); + // ++desc_iter; + // } - VALObject obj{message_id, signal_name, values}; + // VALObject obj{message_id, signal_name, values}; - signal_value.push_back(obj); - continue; - } + // signal_value.push_back(obj); + // continue; + // } } for (const auto& signal : signal_value) { From fd74751073595bf7657e2b8ae66024bee3415bd4 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Sat, 16 Mar 2024 17:05:07 -0400 Subject: [PATCH 17/47] debug(test): reverting commented out code. Attempting to set env of the build type in windows --- .github/workflows/pipeline.yml | 3 +++ src/dbc.cpp | 40 +++++++++++++++++----------------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index af193f2..d3f1440 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -78,6 +78,9 @@ jobs: build_type: [Debug, Release] std: [11] + env: + BUILD_TYPE: ${{matrix.build_type}} + steps: - uses: actions/checkout@v4 diff --git a/src/dbc.cpp b/src/dbc.cpp index 9c10913..385c9fb 100644 --- a/src/dbc.cpp +++ b/src/dbc.cpp @@ -185,32 +185,32 @@ void DbcParser::parse_dbc_messages(const std::vector& lines) { continue; } - // if (std::regex_search(line, match, value_re)) { - // uint32_t message_id = static_cast(std::stoul(match.str(2))); - // std::string signal_name = match.str(3); + if (std::regex_search(line, match, value_re)) { + uint32_t message_id = static_cast(std::stoul(match.str(2))); + std::string signal_name = match.str(3); - // // Loop over the rest of the descriptions - // std::string rest_of_descriptions = match.str(4); - // std::regex description_re("\\s(\\d+)\\s\"([^\"]*)\""); + // Loop over the rest of the descriptions + std::string rest_of_descriptions = match.str(4); + std::regex description_re("\\s(\\d+)\\s\"([^\"]*)\""); - // std::sregex_iterator desc_iter(rest_of_descriptions.begin(), rest_of_descriptions.end(), description_re); - // std::sregex_iterator desc_end = std::sregex_iterator(); + std::sregex_iterator desc_iter(rest_of_descriptions.begin(), rest_of_descriptions.end(), description_re); + std::sregex_iterator desc_end = std::sregex_iterator(); - // std::vector values{}; - // for (std::sregex_iterator i = desc_iter; i != desc_end; ++i) { - // std::smatch desc_match = *desc_iter; - // uint32_t number = static_cast(std::stoul(desc_match.str(1))); - // std::string text = desc_match.str(2); + std::vector values{}; + for (std::sregex_iterator i = desc_iter; i != desc_end; ++i) { + std::smatch desc_match = *desc_iter; + uint32_t number = static_cast(std::stoul(desc_match.str(1))); + std::string text = desc_match.str(2); - // values.push_back(Signal::SignalValueDescriptions{number, text}); - // ++desc_iter; - // } + values.push_back(Signal::SignalValueDescriptions{number, text}); + ++desc_iter; + } - // VALObject obj{message_id, signal_name, values}; + VALObject obj{message_id, signal_name, values}; - // signal_value.push_back(obj); - // continue; - // } + signal_value.push_back(obj); + continue; + } } for (const auto& signal : signal_value) { From 04a381dd996c6c393e8a1e54679860b051663bd9 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Sat, 16 Mar 2024 17:11:59 -0400 Subject: [PATCH 18/47] feat(ci): adding clang-tidy check to pipeline. --- .github/workflows/pipeline.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index d3f1440..5d6c79c 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -25,6 +25,8 @@ jobs: cc: clang-16 llvm_version: 16 + env: + steps: - uses: actions/checkout@v4 @@ -126,6 +128,9 @@ jobs: - cxx: clang++ cc: clang + env: + BUILD_TYPE: ${{matrix.build_type}} + steps: - uses: actions/checkout@v4 @@ -173,3 +178,15 @@ jobs: - name: Test format with clang format run: ./scripts/fmt.sh + clang-tidy-check: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Make build directory + run: cmake -Bbuild -H$GITHUB_WORKSPACE + + - name: Run clang-tidy check + run: cmake --build build --target clang-tidy-check + From bbe7f3a756cfd2ffcce9d0605e96af843654f708 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Sat, 16 Mar 2024 17:15:09 -0400 Subject: [PATCH 19/47] fix(ci): missing env section for linux --- .github/workflows/pipeline.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 5d6c79c..dec1ac8 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -26,6 +26,7 @@ jobs: llvm_version: 16 env: + BUILD_TYPE: ${{matrix.build_type}} steps: - uses: actions/checkout@v4 From db271871570c09e08c8367da11e1edea44a9951e Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Sat, 16 Mar 2024 17:27:26 -0400 Subject: [PATCH 20/47] fix(test): Attempting to remove the variables to see if the debug windows build is a compiler issue --- src/utils.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/utils.cpp b/src/utils.cpp index d2ea6b7..2f671d5 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -74,9 +74,7 @@ std::string String::trim(const std::string& line) { double String::convert_to_double(const std::string& value, double default_value) { double converted_value = default_value; - auto begin = value.begin(); - auto end = value.end(); - fast_float::from_chars(&(*begin), &(*end), converted_value); + fast_float::from_chars(&(*value.begin()), &(*value.end()), converted_value); return converted_value; } From 67a7b3655cb7fffbca582f28200b6c2f778dbe60 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Sat, 16 Mar 2024 17:34:54 -0400 Subject: [PATCH 21/47] fix(test): Fixed the fast_float to original arithmetic in an attempt to fix the windows debug build --- src/utils.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/utils.cpp b/src/utils.cpp index 2f671d5..8960e15 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -74,7 +74,9 @@ std::string String::trim(const std::string& line) { double String::convert_to_double(const std::string& value, double default_value) { double converted_value = default_value; - fast_float::from_chars(&(*value.begin()), &(*value.end()), converted_value); + fast_float::from_chars(value.data(), + value.data() + value.size(), + converted_value); // NOLINT -- Trying to iterators on the value causes the test to infinitly hang on windows builds return converted_value; } From b90af2d3d8cfb38ba7b42992de50cd8427b32791 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Sat, 16 Mar 2024 17:36:21 -0400 Subject: [PATCH 22/47] feat(ci): update to clang-format 17and install clang-tidy 17. The server version is too old --- .github/workflows/pipeline.yml | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index dec1ac8..d63a1e1 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -169,12 +169,12 @@ jobs: run: | wget https://apt.llvm.org/llvm.sh chmod +x llvm.sh - sudo ./llvm.sh 16 + sudo ./llvm.sh 17 - sudo apt update && sudo apt install -y clang-format-16 - sudo ln -sf $(which clang-format-16) $(which clang-format) + sudo apt update && sudo apt install -y clang-format-17 + sudo ln -sf $(which clang-format-17) $(which clang-format) - test "$(clang-format --version)" == "$(clang-format-16 --version)" + test "$(clang-format --version)" == "$(clang-format-17 --version)" - name: Test format with clang format run: ./scripts/fmt.sh @@ -185,6 +185,17 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Install clang-tidy version + run: | + wget https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + sudo ./llvm.sh 17 + + sudo apt update && sudo apt install -y clang-tidy-17 + sudo ln -sf $(which clang-tidy-17) $(which clang-tidy) + + test "$(clang-tidy --version)" == "$(clang-tidy-17 --version)" + - name: Make build directory run: cmake -Bbuild -H$GITHUB_WORKSPACE From 089c1e5fd7c1f19684a6e2052a7e9fb345d821bd Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Sat, 16 Mar 2024 18:09:01 -0400 Subject: [PATCH 23/47] refactor(naming)!: Breaking interface to follow standard naming convention. * Namespace `libdbc` -> `Libdbc` * Message method `parseMessage` -> `parse_message` * Exception class names `exception` -> `Exception`, `validity_error` -> `ValidityError` * Signal method names `parseSignals` -> `parse_signals`, `appendSignal` -> `append_signal`, -> `getSignals` -> `get_signals`, `addValueDescription` -> `add_value_description` * Signal class name change `SignalValueDescriptions` -> `ValueDescription` * Utils name space `utils` -> `Utils` Using naming scheme of CamelCase for classes, structs, and namespaces. Snake case for everything else --- include/libdbc/dbc.hpp | 8 +- include/libdbc/exceptions/error.hpp | 6 +- include/libdbc/message.hpp | 10 +- include/libdbc/signal.hpp | 6 +- include/libdbc/utils/utils.hpp | 2 +- src/dbc.cpp | 58 +++--- src/message.cpp | 12 +- src/signal.cpp | 2 +- src/utils.cpp | 11 +- test/locale_testing/test_locale_main.cpp | 14 +- .../test_single_header.cpp | 20 +- test/test_dbc.cpp | 175 +++++++++--------- test/test_parse_message.cpp | 28 +-- test/test_utils.cpp | 22 ++- 14 files changed, 187 insertions(+), 187 deletions(-) diff --git a/include/libdbc/dbc.hpp b/include/libdbc/dbc.hpp index 50178f8..060e9f7 100644 --- a/include/libdbc/dbc.hpp +++ b/include/libdbc/dbc.hpp @@ -8,7 +8,7 @@ #include -namespace libdbc { +namespace Libdbc { class Parser { public: @@ -27,14 +27,14 @@ class DbcParser : public Parser { std::string get_version() const; std::vector get_nodes() const; - std::vector get_messages() const; + std::vector get_messages() const; - Message::ParseSignalsStatus parseMessage(uint32_t message_id, const std::vector& data, std::vector& out_values); + Message::ParseSignalsStatus parse_message(uint32_t message_id, const std::vector& data, std::vector& out_values); private: std::string version; std::vector nodes; - std::vector messages; + std::vector messages; std::regex version_re; std::regex bit_timing_re; diff --git a/include/libdbc/exceptions/error.hpp b/include/libdbc/exceptions/error.hpp index 4749d2d..27e2fa4 100644 --- a/include/libdbc/exceptions/error.hpp +++ b/include/libdbc/exceptions/error.hpp @@ -3,16 +3,16 @@ #include -namespace libdbc { +namespace Libdbc { -class exception : public std::exception { +class Exception : public std::exception { public: const char* what() const throw() override { return "libdbc exception occurred"; } }; -class validity_error : public exception { +class ValidityError : public Exception { public: const char* what() const throw() override { return "Invalid DBC file"; diff --git a/include/libdbc/message.hpp b/include/libdbc/message.hpp index 21527bf..9ef29a5 100644 --- a/include/libdbc/message.hpp +++ b/include/libdbc/message.hpp @@ -7,7 +7,7 @@ #include #include -namespace libdbc { +namespace Libdbc { struct Message { Message() = delete; virtual ~Message() = default; @@ -21,14 +21,14 @@ struct Message { ErrorInvalidConversion, }; - ParseSignalsStatus parseSignals(const std::vector& data, std::vector& values) const; + ParseSignalsStatus parse_signals(const std::vector& data, std::vector& values) const; - void appendSignal(const Signal& signal); - std::vector getSignals() const; + void append_signal(const Signal& signal); + std::vector get_signals() const; uint32_t id() const; uint8_t size() const; const std::string& name() const; - void addValueDescription(const std::string& signal_name, const std::vector&); + void add_value_description(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 4694f1e..18ed3da 100644 --- a/include/libdbc/signal.hpp +++ b/include/libdbc/signal.hpp @@ -7,9 +7,9 @@ #include #include -namespace libdbc { +namespace Libdbc { struct Signal { - struct SignalValueDescriptions { + struct ValueDescription { uint32_t value; std::string description; }; @@ -26,7 +26,7 @@ struct Signal { double max; std::string unit; std::vector receivers; - std::vector svDescriptions; + std::vector value_descriptions; Signal() = delete; virtual ~Signal() = default; diff --git a/include/libdbc/utils/utils.hpp b/include/libdbc/utils/utils.hpp index 6ab2292..d626d83 100644 --- a/include/libdbc/utils/utils.hpp +++ b/include/libdbc/utils/utils.hpp @@ -9,7 +9,7 @@ #include #include -namespace utils { +namespace Utils { class StreamHandler { public: diff --git a/src/dbc.cpp b/src/dbc.cpp index 385c9fb..75e607d 100644 --- a/src/dbc.cpp +++ b/src/dbc.cpp @@ -6,7 +6,7 @@ #include #include -namespace libdbc { +namespace Libdbc { const auto floatPattern = "(-?\\d+\\.?(\\d+)?)"; // Can be negative @@ -45,12 +45,10 @@ constexpr unsigned MESSAGE_NAME_GROUP = 3; constexpr unsigned MESSAGE_SIZE_GROUP = 4; constexpr unsigned MESSAGE_NODE_GROUP = 5; -enum VALToken { Identifier = 0, CANId, SignalName, Value, Description }; - -struct VALObject { +struct Value { uint32_t can_id; std::string signal_name; - std::vector vd; + std::vector value_descriptions; }; DbcParser::DbcParser() @@ -79,7 +77,7 @@ void DbcParser::parse_file(const std::string& file) { parse_dbc_nodes(stream); while (!stream.eof()) { - utils::StreamHandler::get_next_non_blank_line(stream, line); + Utils::StreamHandler::get_next_non_blank_line(stream, line); lines.push_back(line); } @@ -94,14 +92,14 @@ std::vector DbcParser::get_nodes() const { return nodes; } -std::vector DbcParser::get_messages() const { +std::vector DbcParser::get_messages() const { return messages; } -Message::ParseSignalsStatus DbcParser::parseMessage(const uint32_t message_id, const std::vector& data, std::vector& out_values) { +Message::ParseSignalsStatus DbcParser::parse_message(const uint32_t message_id, const std::vector& data, std::vector& out_values) { for (const auto& message : messages) { if (message.id() == message_id) { - return message.parseSignals(data, out_values); + return message.parse_signals(data, out_values); } } return Message::ParseSignalsStatus::ErrorUnknownID; @@ -111,20 +109,20 @@ 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(); + throw ValidityError(); } version = match.str(2); - utils::StreamHandler::get_next_non_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); + Utils::StreamHandler::skip_to_next_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(); + throw ValidityError(); } } @@ -132,22 +130,22 @@ 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); + Utils::StreamHandler::get_next_non_blank_line(file_stream, line); if (!std::regex_search(line, match, node_re)) { - throw validity_error(); + throw ValidityError(); } if (match.length() > 2) { std::string node = match.str(2); - utils::String::split(node, nodes); + Utils::String::split(node, nodes); } } void DbcParser::parse_dbc_messages(const std::vector& lines) { std::smatch match; - std::vector signal_value; + std::vector signal_value; for (const auto& line : lines) { if (std::regex_search(line, match, message_re)) { @@ -170,18 +168,18 @@ void DbcParser::parse_dbc_messages(const std::vector& lines) { bool is_bigendian = (std::stoul(match.str(SIGNAL_ENDIAN_GROUP)) == 0); bool is_signed = (match.str(SIGNAL_SIGNED_GROUP) == "-"); - double factor = utils::String::convert_to_double(match.str(SIGNAL_FACTOR_GROUP)); - double offset = utils::String::convert_to_double(match.str(SIGNAL_OFFSET_GROUP)); - double min = utils::String::convert_to_double(match.str(SIGNAL_MIN_GROUP)); - double max = utils::String::convert_to_double(match.str(SIGNAL_MAX_GROUP)); + double factor = Utils::String::convert_to_double(match.str(SIGNAL_FACTOR_GROUP)); + double offset = Utils::String::convert_to_double(match.str(SIGNAL_OFFSET_GROUP)); + double min = Utils::String::convert_to_double(match.str(SIGNAL_MIN_GROUP)); + double max = Utils::String::convert_to_double(match.str(SIGNAL_MAX_GROUP)); std::string unit = match.str(SIGNAL_UNIT_GROUP); std::vector receivers; - utils::String::split(match.str(SIGNAL_RECIEVER_GROUP), receivers, ','); + Utils::String::split(match.str(SIGNAL_RECIEVER_GROUP), receivers, ','); Signal sig(name, is_multiplexed, start_bit, size, is_bigendian, is_signed, factor, offset, min, max, unit, receivers); - messages.back().appendSignal(sig); + messages.back().append_signal(sig); continue; } @@ -196,19 +194,19 @@ void DbcParser::parse_dbc_messages(const std::vector& lines) { std::sregex_iterator desc_iter(rest_of_descriptions.begin(), rest_of_descriptions.end(), description_re); std::sregex_iterator desc_end = std::sregex_iterator(); - std::vector values{}; + std::vector values{}; for (std::sregex_iterator i = desc_iter; i != desc_end; ++i) { std::smatch desc_match = *desc_iter; uint32_t number = static_cast(std::stoul(desc_match.str(1))); std::string text = desc_match.str(2); - values.push_back(Signal::SignalValueDescriptions{number, text}); + values.push_back(Signal::ValueDescription{number, text}); ++desc_iter; } - VALObject obj{message_id, signal_name, values}; + Value val{message_id, signal_name, values}; - signal_value.push_back(obj); + signal_value.push_back(val); continue; } } @@ -216,7 +214,7 @@ void DbcParser::parse_dbc_messages(const std::vector& lines) { for (const auto& signal : signal_value) { for (auto& msg : messages) { if (msg.id() == signal.can_id) { - msg.addValueDescription(signal.signal_name, signal.vd); + msg.add_value_description(signal.signal_name, signal.value_descriptions); break; } } diff --git a/src/message.cpp b/src/message.cpp index 791ecc9..6bfdd23 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -1,7 +1,7 @@ #include #include -namespace libdbc { +namespace Libdbc { constexpr unsigned ONE_BYTE = 8; constexpr unsigned TWO_BYTES = 16; @@ -21,7 +21,7 @@ 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 { +Message::ParseSignalsStatus Message::parse_signals(const std::vector& data, std::vector& values) const { auto size = data.size(); if (size > ONE_BYTE) { return ParseSignalsStatus::ErrorMessageToLong; // not supported yet @@ -83,11 +83,11 @@ Message::ParseSignalsStatus Message::parseSignals(const std::vector& da return ParseSignalsStatus::Success; } -void Message::appendSignal(const Signal& signal) { +void Message::append_signal(const Signal& signal) { m_signals.push_back(signal); } -std::vector Message::getSignals() const { +std::vector Message::get_signals() const { return m_signals; } @@ -103,10 +103,10 @@ const std::string& Message::name() const { return m_name; } -void Message::addValueDescription(const std::string& signal_name, const std::vector& value_descriptor) { +void Message::add_value_description(const std::string& signal_name, const std::vector& value_descriptor) { for (auto& signal : m_signals) { if (signal.name == signal_name) { - signal.svDescriptions = value_descriptor; + signal.value_descriptions = value_descriptor; return; } } diff --git a/src/signal.cpp b/src/signal.cpp index edb8407..e75c457 100644 --- a/src/signal.cpp +++ b/src/signal.cpp @@ -1,6 +1,6 @@ #include -namespace libdbc { +namespace Libdbc { Signal::Signal(std::string name, bool is_multiplexed, uint32_t start_bit, diff --git a/src/utils.cpp b/src/utils.cpp index 8960e15..0519541 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -5,7 +5,7 @@ #include -namespace utils { +namespace Utils { std::istream& StreamHandler::get_line(std::istream& stream, std::string& line) { std::string newline; @@ -32,7 +32,7 @@ std::istream& StreamHandler::get_next_non_blank_line(std::istream& stream, std:: std::smatch match; while (is_blank) { - utils::StreamHandler::get_line(stream, line); + Utils::StreamHandler::get_line(stream, line); std::regex_search(line, match, whitespace_re); @@ -53,7 +53,7 @@ std::istream& StreamHandler::skip_to_next_blank_line(std::istream& stream, std:: std::smatch match; while (!line_is_empty) { - utils::StreamHandler::get_line(stream, line); + Utils::StreamHandler::get_line(stream, line); std::regex_search(line, match, whitespace_re); @@ -74,9 +74,8 @@ std::string String::trim(const std::string& line) { double String::convert_to_double(const std::string& value, double default_value) { double converted_value = default_value; - fast_float::from_chars(value.data(), - value.data() + value.size(), - converted_value); // NOLINT -- Trying to iterators on the value causes the test to infinitly hang on windows builds + // NOLINTNEXTLINE -- Trying to iterators on the value causes the test to infinitly hang on windows builds + fast_float::from_chars(value.data(), value.data() + value.size(), converted_value); return converted_value; } diff --git a/test/locale_testing/test_locale_main.cpp b/test/locale_testing/test_locale_main.cpp index 7336545..537a81f 100644 --- a/test/locale_testing/test_locale_main.cpp +++ b/test/locale_testing/test_locale_main.cpp @@ -31,7 +31,7 @@ class testRunListener : public Catch::EventListenerBase { CATCH_REGISTER_LISTENER(testRunListener) TEST_CASE("Should parse doubld string locale independently") { - REQUIRE(Catch::Approx(utils::String::convert_to_double("6.82")) == 6.82); + REQUIRE(Catch::Approx(Utils::String::convert_to_double("6.82")) == 6.82); } TEST_CASE("Should process message with floats locale indpendently") { @@ -42,36 +42,36 @@ TEST_CASE("Should process message with floats locale indpendently") { SG_ Sig4 : 7|16@0- (1,-10) [0|32767] "" Vector__XXX)"; const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); - auto parser = libdbc::DbcParser(); + auto parser = Libdbc::DbcParser(); 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); + REQUIRE(parser.get_messages().at(0).get_signals().size() == 4); SECTION("Evaluating first message") { - const auto signal = parser.get_messages().at(0).getSignals().at(0); + const auto signal = parser.get_messages().at(0).get_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).getSignals().at(1); + const auto signal = parser.get_messages().at(0).get_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).getSignals().at(2); + const auto signal = parser.get_messages().at(0).get_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).getSignals().at(3); + const auto signal = parser.get_messages().at(0).get_signals().at(3); REQUIRE(signal.factor == 1); REQUIRE(signal.offset == -10); REQUIRE(signal.min == 0); diff --git a/test/single_header_testing/test_single_header.cpp b/test/single_header_testing/test_single_header.cpp index d61dac6..e4abc6c 100644 --- a/test/single_header_testing/test_single_header.cpp +++ b/test/single_header_testing/test_single_header.cpp @@ -7,18 +7,18 @@ #include TEST_CASE("Testing dbc file loading", "[fileio]") { - auto parser = std::unique_ptr(new libdbc::DbcParser()); + auto parser = std::unique_ptr(new Libdbc::DbcParser()); SECTION("Loading a single simple dbc file", "[dbc]") { std::vector nodes = {"DBG", "DRIVER", "IO", "MOTOR", "SENSOR"}; - libdbc::Message msg(500, "IO_DEBUG", 4, "IO"); + Libdbc::Message msg(500, "IO_DEBUG", 4, "IO"); std::vector receivers{"DBG"}; - libdbc::Signal sig("IO_DEBUG_test_unsigned", false, 0, 8, false, false, 1, 0, 0, 0, "", receivers); - msg.appendSignal(sig); + Libdbc::Signal sig("IO_DEBUG_test_unsigned", false, 0, 8, false, false, 1, 0, 0, 0, "", receivers); + msg.append_signal(sig); - std::vector msgs = {msg}; + std::vector msgs = {msg}; parser->parse_file(SIMPLE_DBC_FILE); @@ -28,7 +28,7 @@ TEST_CASE("Testing dbc file loading", "[fileio]") { REQUIRE(parser->get_messages() == msgs); - REQUIRE(parser->get_messages().front().getSignals() == msg.getSignals()); + REQUIRE(parser->get_messages().front().get_signals() == msg.get_signals()); } } @@ -38,19 +38,19 @@ TEST_CASE("Testing big endian, little endian") { SG_ Sig2 : 39|16@1- (0.1,0) [-3276.8|-3276.7] "C" Vector__XXX)"; const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); - auto parser = libdbc::DbcParser(); + auto parser = Libdbc::DbcParser(); parser.parse_file(filename.c_str()); REQUIRE(parser.get_messages().size() == 1); REQUIRE(parser.get_messages().at(0).name() == "MSG1"); REQUIRE(parser.get_messages().at(0).size() == 8); - REQUIRE(parser.get_messages().at(0).getSignals().size() == 2); + REQUIRE(parser.get_messages().at(0).get_signals().size() == 2); { - const auto signal = parser.get_messages().at(0).getSignals().at(0); + const auto signal = parser.get_messages().at(0).get_signals().at(0); REQUIRE(signal.is_bigendian == true); } { - const auto signal = parser.get_messages().at(0).getSignals().at(1); + const auto signal = parser.get_messages().at(0).get_signals().at(1); REQUIRE(signal.is_bigendian == false); } } diff --git a/test/test_dbc.cpp b/test/test_dbc.cpp index ff0645f..c539dc5 100644 --- a/test/test_dbc.cpp +++ b/test/test_dbc.cpp @@ -1,3 +1,4 @@ +#include "exceptions/error.hpp" #include "testing_utils/common.hpp" #include "testing_utils/defines.hpp" #include @@ -7,18 +8,18 @@ #include TEST_CASE("Testing dbc file loading error issues", "[fileio][error]") { - auto parser = std::unique_ptr(new libdbc::DbcParser()); + auto parser = std::unique_ptr(new Libdbc::DbcParser()); SECTION("Loading a non dbc file should throw an error", "[error]") { - REQUIRE_THROWS_AS(parser->parse_file(TEXT_FILE), libdbc::validity_error); + REQUIRE_THROWS_AS(parser->parse_file(TEXT_FILE), Libdbc::ValidityError); } SECTION("Loading a dbc with bad headers throws an error", "[error]") { - REQUIRE_THROWS_AS(parser->parse_file(MISSING_VERSION_DBC_FILE), libdbc::validity_error); + REQUIRE_THROWS_AS(parser->parse_file(MISSING_VERSION_DBC_FILE), Libdbc::ValidityError); } SECTION("Loading a dbc without the required bit timing section (BS_:)", "[error]") { - REQUIRE_THROWS_AS(parser->parse_file(MISSING_BIT_TIMING_DBC_FILE), libdbc::validity_error); + REQUIRE_THROWS_AS(parser->parse_file(MISSING_BIT_TIMING_DBC_FILE), Libdbc::ValidityError); } SECTION("Loading a dbc with some missing namespace section tags (NS_ :)", "[error]") { @@ -28,27 +29,27 @@ TEST_CASE("Testing dbc file loading error issues", "[fileio][error]") { } SECTION("Verify that what() method is accessible for all exceptions", "[error]") { - auto generic_error = libdbc::exception(); + auto generic_error = Libdbc::Exception(); REQUIRE(std::string{generic_error.what()} == "libdbc exception occurred"); - auto validity_check = libdbc::validity_error(); + auto validity_check = Libdbc::ValidityError(); REQUIRE(std::string{validity_check.what()} == "Invalid DBC file"); } } TEST_CASE("Testing dbc file loading", "[fileio]") { - auto parser = std::unique_ptr(new libdbc::DbcParser()); + auto parser = std::unique_ptr(new Libdbc::DbcParser()); SECTION("Loading a single simple dbc file", "[dbc]") { std::vector nodes = {"DBG", "DRIVER", "IO", "MOTOR", "SENSOR"}; - libdbc::Message msg(500, "IO_DEBUG", 4, "IO"); + Libdbc::Message msg(500, "IO_DEBUG", 4, "IO"); std::vector receivers{"DBG"}; - libdbc::Signal sig("IO_DEBUG_test_unsigned", false, 0, 8, false, false, 1, 0, 0, 0, "", receivers); - msg.appendSignal(sig); + Libdbc::Signal sig("IO_DEBUG_test_unsigned", false, 0, 8, false, false, 1, 0, 0, 0, "", receivers); + msg.append_signal(sig); - std::vector msgs = {msg}; + std::vector msgs = {msg}; parser->parse_file(SIMPLE_DBC_FILE); @@ -58,72 +59,72 @@ TEST_CASE("Testing dbc file loading", "[fileio]") { REQUIRE(parser->get_messages() == msgs); - REQUIRE(parser->get_messages().front().getSignals() == msg.getSignals()); + REQUIRE(parser->get_messages().front().get_signals() == msg.get_signals()); } } TEST_CASE("Testing big endian, little endian") { - std::string dbc_contents = PRIMITIVE_DBC + R"(BO_ 234 MSG1: 8 Vector__XXX - SG_ Sig1 : 55|16@0- (0.1,0) [-3276.8|-3276.7] "C" Vector__XXX + std::string dbc_contents = PRIMITIVE_DBC + 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)"; const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); - auto parser = libdbc::DbcParser(); + auto parser = Libdbc::DbcParser(); parser.parse_file(filename.c_str()); REQUIRE(parser.get_messages().size() == 1); REQUIRE(parser.get_messages().at(0).name() == "MSG1"); REQUIRE(parser.get_messages().at(0).size() == 8); - REQUIRE(parser.get_messages().at(0).getSignals().size() == 2); + REQUIRE(parser.get_messages().at(0).get_signals().size() == 2); { - const auto signal = parser.get_messages().at(0).getSignals().at(0); + const auto signal = parser.get_messages().at(0).get_signals().at(0); REQUIRE(signal.is_bigendian == true); } { - const auto signal = parser.get_messages().at(0).getSignals().at(1); + const auto signal = parser.get_messages().at(0).get_signals().at(1); REQUIRE(signal.is_bigendian == false); } } TEST_CASE("Testing negative values") { - std::string dbc_contents = PRIMITIVE_DBC + R"(BO_ 234 MSG1: 58 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 + std::string dbc_contents = PRIMITIVE_DBC + R"(BO_ 234 MSG1: 58 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)"; const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); - auto parser = libdbc::DbcParser(); + auto parser = Libdbc::DbcParser(); parser.parse_file(filename.c_str()); REQUIRE(parser.get_messages().size() == 1); REQUIRE(parser.get_messages().at(0).name() == "MSG1"); REQUIRE(parser.get_messages().at(0).size() == 58); - REQUIRE(parser.get_messages().at(0).getSignals().size() == 4); + REQUIRE(parser.get_messages().at(0).get_signals().size() == 4); SECTION("Evaluating first message") { - const auto signal = parser.get_messages().at(0).getSignals().at(0); + const auto signal = parser.get_messages().at(0).get_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).getSignals().at(1); + const auto signal = parser.get_messages().at(0).get_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).getSignals().at(2); + const auto signal = parser.get_messages().at(0).get_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).getSignals().at(3); + const auto signal = parser.get_messages().at(0).get_signals().at(3); REQUIRE(signal.factor == 1); REQUIRE(signal.offset == -10); REQUIRE(signal.min == 0); @@ -132,109 +133,109 @@ TEST_CASE("Testing negative values") { } TEST_CASE("Special characters in unit") { - std::string dbc_contents = PRIMITIVE_DBC + R"(BO_ 234 MSG1: 255 Vector__XXX + std::string dbc_contents = PRIMITIVE_DBC + R"(BO_ 234 MSG1: 255 Vector__XXX SG_ Speed : 0|8@1+ (1,0) [0|204] "Km/h" DEVICE1,DEVICE2,DEVICE3)"; const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); - auto parser = libdbc::DbcParser(); + auto parser = Libdbc::DbcParser(); parser.parse_file(filename.c_str()); REQUIRE(parser.get_messages().size() == 1); REQUIRE(parser.get_messages().at(0).name() == "MSG1"); REQUIRE(parser.get_messages().at(0).size() == 255); - REQUIRE(parser.get_messages().at(0).getSignals().size() == 1); + REQUIRE(parser.get_messages().at(0).get_signals().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); + const auto signal = parser.get_messages().at(0).get_signals().at(0); REQUIRE(signal.unit.compare("Km/h") == 0); } } TEST_CASE("Signal Value Description") { - std::string dbc_contents = PRIMITIVE_DBC + R"(BO_ 234 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 + std::string dbc_contents = PRIMITIVE_DBC + R"(BO_ 234 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 VAL_ 234 State1 123 "Description 1" 0 "Description 2" 90903489 "Big value and special characters &$§())!" ;)"; const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); - auto parser = libdbc::DbcParser(); + auto parser = Libdbc::DbcParser(); parser.parse_file(filename.c_str()); 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); - REQUIRE(parser.get_messages().at(0).getSignals().at(1).svDescriptions.size() == 0); - - const auto signal = parser.get_messages().at(0).getSignals().at(0); - REQUIRE(signal.svDescriptions.at(0).value == 123); - REQUIRE(signal.svDescriptions.at(0).description == "Description 1"); - REQUIRE(signal.svDescriptions.at(1).value == 0); - REQUIRE(signal.svDescriptions.at(1).description == "Description 2"); - REQUIRE(signal.svDescriptions.at(2).value == 90903489); - REQUIRE(signal.svDescriptions.at(2).description == "Big value and special characters &$§())!"); + REQUIRE(parser.get_messages().at(0).get_signals().size() == 2); + + REQUIRE(parser.get_messages().at(0).get_signals().at(0).value_descriptions.size() == 3); + REQUIRE(parser.get_messages().at(0).get_signals().at(1).value_descriptions.size() == 0); + + const auto signal = parser.get_messages().at(0).get_signals().at(0); + REQUIRE(signal.value_descriptions.at(0).value == 123); + REQUIRE(signal.value_descriptions.at(0).description == "Description 1"); + REQUIRE(signal.value_descriptions.at(1).value == 0); + REQUIRE(signal.value_descriptions.at(1).description == "Description 2"); + REQUIRE(signal.value_descriptions.at(2).value == 90903489); + REQUIRE(signal.value_descriptions.at(2).description == "Big value and special characters &$§())!"); } TEST_CASE("Signal Value Description Extended CAN id") { - std::string dbc_contents = PRIMITIVE_DBC + 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 + std::string dbc_contents = PRIMITIVE_DBC + 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 VAL_ 3221225472 State1 123 "Description 1" 0 "Description 2" 4000000000 "Big value and special characters &$§())!" ;)"; const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); - auto parser = libdbc::DbcParser(); + auto parser = Libdbc::DbcParser(); parser.parse_file(filename.c_str()); 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); - REQUIRE(parser.get_messages().at(0).getSignals().at(1).svDescriptions.size() == 0); - - const auto signal = parser.get_messages().at(0).getSignals().at(0); - REQUIRE(signal.svDescriptions.at(0).value == 123); - REQUIRE(signal.svDescriptions.at(0).description == "Description 1"); - REQUIRE(signal.svDescriptions.at(1).value == 0); - REQUIRE(signal.svDescriptions.at(1).description == "Description 2"); - REQUIRE(signal.svDescriptions.at(2).value == 4000000000); - REQUIRE(signal.svDescriptions.at(2).description == "Big value and special characters &$§())!"); + REQUIRE(parser.get_messages().at(0).get_signals().size() == 2); + + REQUIRE(parser.get_messages().at(0).get_signals().at(0).value_descriptions.size() == 3); + REQUIRE(parser.get_messages().at(0).get_signals().at(1).value_descriptions.size() == 0); + + const auto signal = parser.get_messages().at(0).get_signals().at(0); + REQUIRE(signal.value_descriptions.at(0).value == 123); + REQUIRE(signal.value_descriptions.at(0).description == "Description 1"); + REQUIRE(signal.value_descriptions.at(1).value == 0); + REQUIRE(signal.value_descriptions.at(1).description == "Description 2"); + REQUIRE(signal.value_descriptions.at(2).value == 4000000000); + REQUIRE(signal.value_descriptions.at(2).description == "Big value and special characters &$§())!"); } TEST_CASE("Signal Value Multiple VAL_") { - std::string dbc_contents = PRIMITIVE_DBC + 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 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" ; + std::string dbc_contents = PRIMITIVE_DBC + 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 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" ; VAL_ 123 State1 123 "Description 3" 0 "Description 4" ;)"; const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); - auto parser = libdbc::DbcParser(); + auto parser = Libdbc::DbcParser(); parser.parse_file(filename.c_str()); 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).get_signals().size() == 2); - REQUIRE(parser.get_messages().at(0).getSignals().at(0).svDescriptions.size() == 2); - REQUIRE(parser.get_messages().at(0).getSignals().at(1).svDescriptions.size() == 0); - REQUIRE(parser.get_messages().at(1).getSignals().at(0).svDescriptions.size() == 2); - REQUIRE(parser.get_messages().at(1).getSignals().at(1).svDescriptions.size() == 0); + REQUIRE(parser.get_messages().at(0).get_signals().at(0).value_descriptions.size() == 2); + REQUIRE(parser.get_messages().at(0).get_signals().at(1).value_descriptions.size() == 0); + REQUIRE(parser.get_messages().at(1).get_signals().at(0).value_descriptions.size() == 2); + REQUIRE(parser.get_messages().at(1).get_signals().at(1).value_descriptions.size() == 0); - const auto signal = parser.get_messages().at(0).getSignals().at(0); - REQUIRE(signal.svDescriptions.at(0).value == 123); - REQUIRE(signal.svDescriptions.at(0).description == "Description 1"); - REQUIRE(signal.svDescriptions.at(1).value == 0); - REQUIRE(signal.svDescriptions.at(1).description == "Description 2"); + const auto signal = parser.get_messages().at(0).get_signals().at(0); + REQUIRE(signal.value_descriptions.at(0).value == 123); + REQUIRE(signal.value_descriptions.at(0).description == "Description 1"); + REQUIRE(signal.value_descriptions.at(1).value == 0); + REQUIRE(signal.value_descriptions.at(1).description == "Description 2"); - const auto signal2 = parser.get_messages().at(1).getSignals().at(0); - REQUIRE(signal2.svDescriptions.at(0).value == 123); - REQUIRE(signal2.svDescriptions.at(0).description == "Description 3"); - REQUIRE(signal2.svDescriptions.at(1).value == 0); - REQUIRE(signal2.svDescriptions.at(1).description == "Description 4"); + const auto signal2 = parser.get_messages().at(1).get_signals().at(0); + REQUIRE(signal2.value_descriptions.at(0).value == 123); + REQUIRE(signal2.value_descriptions.at(0).description == "Description 3"); + REQUIRE(signal2.value_descriptions.at(1).value == 0); + REQUIRE(signal2.value_descriptions.at(1).description == "Description 4"); } diff --git a/test/test_parse_message.cpp b/test/test_parse_message.cpp index 3c3c301..aad3b1c 100644 --- a/test/test_parse_message.cpp +++ b/test/test_parse_message.cpp @@ -19,12 +19,12 @@ BO_ 123 MSG2: 8 Vector__XXX )"; const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); - libdbc::DbcParser parser; + Libdbc::DbcParser parser; parser.parse_file(filename.c_str()); SECTION("Evaluating unknown` message id") { std::vector out_values; - CHECK(parser.parseMessage(578, std::vector({0xFF, 0xA2}), out_values) == libdbc::Message::ParseSignalsStatus::ErrorUnknownID); + CHECK(parser.parse_message(578, std::vector({0xFF, 0xA2}), out_values) == Libdbc::Message::ParseSignalsStatus::ErrorUnknownID); } } @@ -40,12 +40,12 @@ TEST_CASE("Parse Message Big Number not aligned little endian") { )"; const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); - libdbc::DbcParser parser; + Libdbc::DbcParser parser; 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); + CHECK(parser.parse_message(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()); @@ -56,7 +56,7 @@ TEST_CASE("Parse Message Big Number not aligned little endian") { 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); + CHECK(parser.parse_message(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()); @@ -67,7 +67,7 @@ TEST_CASE("Parse Message Big Number not aligned little endian") { 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); + CHECK(parser.parse_message(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()); @@ -85,12 +85,12 @@ TEST_CASE("Parse Message little endian") { SG_ SOC : 16|16@1+ (0.01,0) [0|100] "%" DEVICE1)"; const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); - libdbc::DbcParser parser; + Libdbc::DbcParser parser; parser.parse_file(filename); std::vector data{0x08, 0x27, 0xa3, 0x22, 0xe5, 0x1f, 0x45, 0x14}; // little endian std::vector result_values; - REQUIRE(parser.parseMessage(0x21d, data, result_values) == libdbc::Message::ParseSignalsStatus::Success); + REQUIRE(parser.parse_message(0x21d, data, result_values) == Libdbc::Message::ParseSignalsStatus::Success); REQUIRE(result_values.size() == 4); REQUIRE(Catch::Approx(result_values.at(0)) == 11.89); @@ -115,12 +115,12 @@ TEST_CASE("Parse Message big endian signed values") { SG_ Sig12 : 23|16@0+ (0.1,0) [0|6553.5] "A" Vector__XXX)"; const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); - libdbc::DbcParser p; + Libdbc::DbcParser p; p.parse_file(filename.c_str()); 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(p.parse_message(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); @@ -144,12 +144,12 @@ TEST_CASE("Parse Message with non byte aligned values") { SG_ Id_Current : 0|10@1- (1,0) [-512|512] "A" Vector__XXX)"; const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); - libdbc::DbcParser p; + 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(p.parse_message(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); @@ -163,12 +163,12 @@ TEST_CASE("Parse Message data length < 8 unsigned") { SG_ Msg1Sig2 : 15|8@0+ (1,0) [-3276.8|-3276.7] "km/h" Vector__XXX)"; const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); - libdbc::DbcParser p; + 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(p.parse_message(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); diff --git a/test/test_utils.cpp b/test/test_utils.cpp index fe7a064..c03dcd7 100644 --- a/test/test_utils.cpp +++ b/test/test_utils.cpp @@ -4,7 +4,7 @@ #include -using namespace utils; +namespace Utils { TEST_CASE("Basic file input with safe get_line that is non line ending specific", "") { SECTION("Verify various line ending input files") { @@ -32,15 +32,15 @@ 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\ - \n\ - \n\ - \n\ -this is not blank\n\ -maybe not this one either\n\ -\n\ -Someone wrote something....\n\ - b\n\ + "hello\n\ + \n\ + \n\ + \n\ +this is not blank\n\ +maybe not this one either\n\ +\n\ +Someone wrote something....\n\ + b\n\ end"; std::istringstream stream(test_string); @@ -91,3 +91,5 @@ TEST_CASE("Test string split feature", "[string]") { REQUIRE(v == vs); } + +} // Utils From 120927ae7e6fbb4bbc8c47c31668b19c323a023b Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Sat, 16 Mar 2024 18:34:49 -0400 Subject: [PATCH 24/47] fix: Adding include checks in clang-tidy and fixing all the issues --- .clang-tidy | 2 +- include/libdbc/dbc.hpp | 10 +++++----- include/libdbc/message.hpp | 2 +- include/libdbc/utils/utils.hpp | 3 --- src/dbc.cpp | 6 +++++- src/message.cpp | 7 ++++++- src/signal.cpp | 4 ++++ src/utils.cpp | 6 +++--- test/test_utils.cpp | 2 +- 9 files changed, 26 insertions(+), 16 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 2b65fe4..3f85e19 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,5 +1,5 @@ --- -Checks: 'clang-diagnostic-*,clang-analyzer-*,-*,clang-analyzer-*,clang-analyzer-cplusplus*,cert-*,cppcoreguidelines-*,portability-*,readability-*,clang-diagnostic-*' +Checks: 'clang-diagnostic-*,clang-analyzer-*,-*,clang-analyzer-*,clang-analyzer-cplusplus*,cert-*,cppcoreguidelines-*,portability-*,readability-*,clang-diagnostic-*,misc-include-cleaner' WarningsAsErrors: '' HeaderFilterRegex: '' AnalyzeTemporaryDtors: false diff --git a/include/libdbc/dbc.hpp b/include/libdbc/dbc.hpp index 060e9f7..d58c8c0 100644 --- a/include/libdbc/dbc.hpp +++ b/include/libdbc/dbc.hpp @@ -1,12 +1,12 @@ #ifndef DBC_HPP #define DBC_HPP -#include -#include -#include -#include - +#include #include +#include +#include +#include +#include namespace Libdbc { diff --git a/include/libdbc/message.hpp b/include/libdbc/message.hpp index 9ef29a5..edfd7c1 100644 --- a/include/libdbc/message.hpp +++ b/include/libdbc/message.hpp @@ -1,11 +1,11 @@ #ifndef MESSAGE_HPP #define MESSAGE_HPP -#include #include #include #include #include +#include namespace Libdbc { struct Message { diff --git a/include/libdbc/utils/utils.hpp b/include/libdbc/utils/utils.hpp index d626d83..fd2fba2 100644 --- a/include/libdbc/utils/utils.hpp +++ b/include/libdbc/utils/utils.hpp @@ -2,10 +2,7 @@ #ifndef UTILS_HPP #define UTILS_HPP -#include -#include #include -#include #include #include diff --git a/src/dbc.cpp b/src/dbc.cpp index 75e607d..360f05c 100644 --- a/src/dbc.cpp +++ b/src/dbc.cpp @@ -1,9 +1,13 @@ #include +#include +#include #include #include +#include +#include #include - #include +#include #include namespace Libdbc { diff --git a/src/message.cpp b/src/message.cpp index 6bfdd23..ffe4526 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -1,5 +1,10 @@ +#include #include #include +#include +#include +#include +#include namespace Libdbc { @@ -29,7 +34,7 @@ Message::ParseSignalsStatus Message::parse_signals(const std::vector& d uint64_t data_little_endian = 0; uint64_t data_big_endian = 0; - for (size_t i = 0; i < size; i++) { + for (std::size_t i = 0; i < size; i++) { data_little_endian |= ((uint64_t)data[i]) << i * ONE_BYTE; data_big_endian = (data_big_endian << ONE_BYTE) | (uint64_t)data[i]; } diff --git a/src/signal.cpp b/src/signal.cpp index e75c457..d40bf2f 100644 --- a/src/signal.cpp +++ b/src/signal.cpp @@ -1,4 +1,8 @@ +#include #include +#include +#include +#include namespace Libdbc { Signal::Signal(std::string name, diff --git a/src/utils.cpp b/src/utils.cpp index 0519541..eed3134 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -1,9 +1,9 @@ -#include -#include +#include #include +#include #include - #include +#include namespace Utils { diff --git a/test/test_utils.cpp b/test/test_utils.cpp index c03dcd7..af4929c 100644 --- a/test/test_utils.cpp +++ b/test/test_utils.cpp @@ -1,7 +1,7 @@ #include "testing_utils/defines.hpp" #include +#include #include - #include namespace Utils { From caa15c85f5a1ce52682433d34492b46d23fa2651 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Sat, 16 Mar 2024 18:38:40 -0400 Subject: [PATCH 25/47] fix(format): Formatting after adding / fixing includes --- include/libdbc/dbc.hpp | 4 ++-- include/libdbc/message.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/libdbc/dbc.hpp b/include/libdbc/dbc.hpp index d58c8c0..68e9789 100644 --- a/include/libdbc/dbc.hpp +++ b/include/libdbc/dbc.hpp @@ -2,11 +2,11 @@ #define DBC_HPP #include +#include +#include #include #include #include -#include -#include namespace Libdbc { diff --git a/include/libdbc/message.hpp b/include/libdbc/message.hpp index edfd7c1..438dc7f 100644 --- a/include/libdbc/message.hpp +++ b/include/libdbc/message.hpp @@ -1,11 +1,11 @@ #ifndef MESSAGE_HPP #define MESSAGE_HPP +#include #include #include #include #include -#include namespace Libdbc { struct Message { From cc1ec260d5e4979385f208d90fe669f8be1a1c25 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Sat, 16 Mar 2024 18:45:24 -0400 Subject: [PATCH 26/47] feat(ci): adding ubuntu 20.04 cmake test --- .github/workflows/pipeline.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index d63a1e1..7ab424b 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -202,3 +202,18 @@ jobs: - name: Run clang-tidy check run: cmake --build build --target clang-tidy-check + check-against-minimum-cmake: + runs-on: ubuntu-20.04 + + steps: + - uses: actions/checkout@v4 + + - name: Cmake version + run: cmake --version + + - name: Make build directory + run: cmake -Bbuild -H$GITHUB_WORKSPACE + + - name: Run clang-tidy check + run: cmake --build build + From e670522158f738b40fc1636bea2aff2b38f3c8e3 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Sat, 16 Mar 2024 18:52:04 -0400 Subject: [PATCH 27/47] fix(ci): install the specific cmake version of 16 --- .github/workflows/pipeline.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 7ab424b..71f9766 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -203,13 +203,17 @@ jobs: run: cmake --build build --target clang-tidy-check check-against-minimum-cmake: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Cmake version - run: cmake --version + - name: Cmake install + run: | + wget https://github.com/Kitware/CMake/releases/download/v3.16.9/cmake-3.16.9-linux-x86_64.sh + chmod +x cmake-3.16.9-linux-x86_64.sh + sudo ./cmake-3.16.9-linux-x86_64.sh --skip-license --prefix=/usr/local + cmake --version - name: Make build directory run: cmake -Bbuild -H$GITHUB_WORKSPACE From 8b366fe4c50c1759471c41a39e9b6aca79998a41 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Sat, 16 Mar 2024 18:54:50 -0400 Subject: [PATCH 28/47] fix(build): Removing incompatibilities of 3.16 cmake --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 539e72b..a53d602 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,7 +85,7 @@ target_include_directories(${PROJECT_NAME} PUBLIC ) target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_11) -target_sources(${PROJECT_NAME} INTERFACE FILE_SET HEADERS +target_sources(${PROJECT_NAME} INTERFACE HEADERS TYPE HEADERS BASE_DIRS ${PROJECT_SOURCE_DIR}/include/libdbc FILES ${HEADER_FILES} From 2d4c42c2fd7eec69accf6808dcff731b09568f9e Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Sat, 16 Mar 2024 18:59:09 -0400 Subject: [PATCH 29/47] fix(build): Fix the target_sources after removing FILE_SET --- CMakeLists.txt | 6 +----- test/test_dbc.cpp | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a53d602..079dc86 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,11 +85,7 @@ target_include_directories(${PROJECT_NAME} PUBLIC ) target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_11) -target_sources(${PROJECT_NAME} INTERFACE HEADERS - TYPE HEADERS - BASE_DIRS ${PROJECT_SOURCE_DIR}/include/libdbc - FILES ${HEADER_FILES} -) +target_sources(${PROJECT_NAME} INTERFACE ${HEADER_FILES}) if(DBC_GENERATE_SINGLE_HEADER) add_custom_target(single_header ALL diff --git a/test/test_dbc.cpp b/test/test_dbc.cpp index c539dc5..5fd2515 100644 --- a/test/test_dbc.cpp +++ b/test/test_dbc.cpp @@ -1,10 +1,10 @@ -#include "exceptions/error.hpp" #include "testing_utils/common.hpp" #include "testing_utils/defines.hpp" #include #include #include #include +#include #include TEST_CASE("Testing dbc file loading error issues", "[fileio][error]") { From 00df6ba442b28adbf333d700729cf310cfcf80e8 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Sat, 16 Mar 2024 19:09:34 -0400 Subject: [PATCH 30/47] feat: Bump version to 0.3.0 for release --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 079dc86..2d4fb58 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.16) # Keep this on one line for release checking -project(dbc VERSION 0.2.0 DESCRIPTION "C++ DBC Parser") +project(dbc VERSION 0.3.0 DESCRIPTION "C++ DBC Parser") # -- PROJECT OPTIONS -- # option(DBC_ENABLE_TESTS "Enable Unittests" ON) From 9d421415285222ee0cdbf7bd586a56cc58d7ecaf Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Sat, 16 Mar 2024 19:48:08 -0400 Subject: [PATCH 31/47] feat: Allow empty BU_: nodes --- .github/workflows/pipeline.yml | 2 +- src/dbc.cpp | 2 +- test/test_dbc.cpp | 27 +++++++++++++++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 71f9766..49c3b6e 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -218,6 +218,6 @@ jobs: - name: Make build directory run: cmake -Bbuild -H$GITHUB_WORKSPACE - - name: Run clang-tidy check + - name: Run build run: cmake --build build diff --git a/src/dbc.cpp b/src/dbc.cpp index 360f05c..bfbc177 100644 --- a/src/dbc.cpp +++ b/src/dbc.cpp @@ -59,7 +59,7 @@ DbcParser::DbcParser() : version_re("^(VERSION)\\s\"(.*)\"") , bit_timing_re("^(BS_:)") , name_space_re("^(NS_)\\s\\:") - , node_re("^(BU_:)\\s((?:[\\w]+?\\s?)*)") + , node_re("^(BU_:)\\s?((?:[\\w]+?\\s?)*)?") , message_re("^(BO_)\\s(\\d+)\\s(\\w+)\\:\\s(\\d+)\\s(\\w+|Vector__XXX)") , value_re("^(VAL_)\\s(\\d+)\\s(\\w+)((?:\\s(\\d+)\\s\"([^\"]*)\")+)\\s;$") , diff --git a/test/test_dbc.cpp b/test/test_dbc.cpp index 5fd2515..19e6b5e 100644 --- a/test/test_dbc.cpp +++ b/test/test_dbc.cpp @@ -239,3 +239,30 @@ VAL_ 123 State1 123 "Description 3" 0 "Description 4" ;)"; REQUIRE(signal2.value_descriptions.at(1).value == 0); REQUIRE(signal2.value_descriptions.at(1).description == "Description 4"); } + +TEST_CASE("Should parse DBC with empty BU_") { + std::string contents = R"(VERSION "" + + +NS_ : + +BS_: + +BU_: + + +BO_ 293 Msg1: 2 Vector__XXX + SG_ Wert7 : 0|16@1- (1,0) [0|0] "" Vector__XXX + +BO_ 292 Msg2: 8 Vector__XXX + SG_ Wert8 : 56|8@1- (1,0) [0|0] "" Vector__XXX +)"; + const auto filename = create_temporary_dbc_with(contents.c_str()); + + auto parser = Libdbc::DbcParser(); + parser.parse_file(filename.c_str()); + + REQUIRE(parser.get_messages().size() == 2); + REQUIRE(parser.get_messages().at(0).name() == "Msg1"); + REQUIRE(parser.get_messages().at(1).name() == "Msg2"); +} From 58669c99551f5be1831a1157b1bd562bf5d4932c Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Tue, 19 Mar 2024 16:22:51 -0400 Subject: [PATCH 32/47] Exception error cleanup (#24) * feat(error): Adding non dbc file format error (extension based), Missing version header error added Fixed the tests so that they now make .dbc files since we are checking the extensions. * feat(error): Adding a missing bit timing error class * feat(error): Adding lines we attempted to parse and more error messaging for the Exceptions * test: Updating tests names to be more clear at what is being validated. * feat(parsing): Adding a way to push and read all of the unused lines since we don't error out on unused * fix(format): Running code format * fix: Fixing clang-tidy warnings --- include/libdbc/dbc.hpp | 6 +++ include/libdbc/exceptions/error.hpp | 44 ++++++++++++++++++ src/dbc.cpp | 32 ++++++++++--- test/dbcs/MissingVersion.dbc | 72 ++++++++++++++--------------- test/test_dbc.cpp | 59 +++++++++++++++++++---- test/testing_utils/common.cpp | 2 +- 6 files changed, 164 insertions(+), 51 deletions(-) diff --git a/include/libdbc/dbc.hpp b/include/libdbc/dbc.hpp index 68e9789..2dfe7bf 100644 --- a/include/libdbc/dbc.hpp +++ b/include/libdbc/dbc.hpp @@ -31,6 +31,8 @@ class DbcParser : public Parser { Message::ParseSignalsStatus parse_message(uint32_t message_id, const std::vector& data, std::vector& out_values); + std::vector unused_lines() const; + private: std::string version; std::vector nodes; @@ -44,9 +46,13 @@ class DbcParser : public Parser { std::regex value_re; std::regex signal_re; + std::vector missed_lines; + void parse_dbc_header(std::istream& file_stream); void parse_dbc_nodes(std::istream& file_stream); void parse_dbc_messages(const std::vector& lines); + + static std::string get_extension(const std::string& file_name); }; } diff --git a/include/libdbc/exceptions/error.hpp b/include/libdbc/exceptions/error.hpp index 27e2fa4..03fd5a0 100644 --- a/include/libdbc/exceptions/error.hpp +++ b/include/libdbc/exceptions/error.hpp @@ -2,6 +2,7 @@ #define ERROR_HPP #include +#include namespace Libdbc { @@ -19,6 +20,49 @@ class ValidityError : public Exception { } }; +class NonDbcFileFormatError : public ValidityError { +public: + NonDbcFileFormatError(const std::string& path, const std::string& extension) { + error_msg = {"File is not of DBC format. Expected a .dbc extension. Cannot read this type of file (" + path + "). Found the extension (" + extension + + ")."}; + } + + const char* what() const throw() override { + return error_msg.c_str(); + } + +private: + std::string error_msg; +}; + +class DbcFileIsMissingVersion : public ValidityError { +public: + DbcFileIsMissingVersion(const std::string& line) { + error_msg = {"Invalid dbc file. Missing the required version header. Attempting to read line: (" + line + ")."}; + } + + const char* what() const throw() override { + return error_msg.c_str(); + } + +private: + std::string error_msg; +}; + +class DbcFileIsMissingBitTiming : public ValidityError { +public: + DbcFileIsMissingBitTiming(const std::string& line) { + error_msg = {"Invalid dbc file. Missing required bit timing in the header. Attempting to read line: (" + line + ")."}; + } + + const char* what() const throw() override { + return error_msg.c_str(); + } + +private: + std::string error_msg; +}; + } // libdbc #endif // ERROR_HPP diff --git a/src/dbc.cpp b/src/dbc.cpp index bfbc177..108ab7e 100644 --- a/src/dbc.cpp +++ b/src/dbc.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -76,8 +77,12 @@ void DbcParser::parse_file(const std::string& file) { messages.clear(); - parse_dbc_header(stream); + auto extension = get_extension(file); + if (extension != ".dbc") { + throw NonDbcFileFormatError(file, extension); + } + parse_dbc_header(stream); parse_dbc_nodes(stream); while (!stream.eof()) { @@ -88,6 +93,15 @@ void DbcParser::parse_file(const std::string& file) { parse_dbc_messages(lines); } +std::string DbcParser::get_extension(const std::string& file_name) { + std::size_t dot = file_name.find_last_of("."); + if (dot != std::string::npos) { + return file_name.substr(dot, file_name.size() - dot); + } + + return ""; +} + std::string DbcParser::get_version() const { return version; } @@ -116,7 +130,7 @@ void DbcParser::parse_dbc_header(std::istream& file_stream) { Utils::StreamHandler::get_line(file_stream, line); if (!std::regex_search(line, match, version_re)) { - throw ValidityError(); + throw DbcFileIsMissingVersion(line); } version = match.str(2); @@ -126,7 +140,7 @@ void DbcParser::parse_dbc_header(std::istream& file_stream) { Utils::StreamHandler::get_next_non_blank_line(file_stream, line); if (!std::regex_search(line, match, bit_timing_re)) { - throw ValidityError(); + throw DbcFileIsMissingBitTiming(line); } } @@ -136,9 +150,7 @@ void DbcParser::parse_dbc_nodes(std::istream& file_stream) { Utils::StreamHandler::get_next_non_blank_line(file_stream, line); - if (!std::regex_search(line, match, node_re)) { - throw ValidityError(); - } + std::regex_search(line, match, node_re); if (match.length() > 2) { std::string node = match.str(2); @@ -213,6 +225,10 @@ void DbcParser::parse_dbc_messages(const std::vector& lines) { signal_value.push_back(val); continue; } + + if (line.length() > 0) { + missed_lines.push_back(line); + } } for (const auto& signal : signal_value) { @@ -225,4 +241,8 @@ void DbcParser::parse_dbc_messages(const std::vector& lines) { } } +std::vector DbcParser::unused_lines() const { + return missed_lines; +} + } diff --git a/test/dbcs/MissingVersion.dbc b/test/dbcs/MissingVersion.dbc index 0db087a..40d5967 100644 --- a/test/dbcs/MissingVersion.dbc +++ b/test/dbcs/MissingVersion.dbc @@ -1,36 +1,36 @@ -NS_ : - BA_ - BA_DEF_ - BA_DEF_DEF_ - BA_DEF_DEF_REL_ - BA_DEF_REL_ - BA_DEF_SGTYPE_ - BA_REL_ - BA_SGTYPE_ - BO_TX_BU_ - BU_BO_REL_ - BU_EV_REL_ - BU_SG_REL_ - CAT_ - CAT_DEF_ - CM_ - ENVVAR_DATA_ - EV_DATA_ - FILTER - NS_DESC_ - SGTYPE_ - SGTYPE_VAL_ - SG_MUL_VAL_ - SIGTYPE_VALTYPE_ - SIG_GROUP_ - SIG_TYPE_REF_ - SIG_VALTYPE_ - VAL_ - VAL_TABLE_ - -BS_: - -BU_: DBG DRIVER IO MOTOR SENSOR - -BO_ 500 IO_DEBUG: 4 IO - SG_ IO_DEBUG_test_unsigned : 0|8@1+ (1,0) [0|0] "" DBG \ No newline at end of file +NS_ : + BA_ + BA_DEF_ + BA_DEF_DEF_ + BA_DEF_DEF_REL_ + BA_DEF_REL_ + BA_DEF_SGTYPE_ + BA_REL_ + BA_SGTYPE_ + BO_TX_BU_ + BU_BO_REL_ + BU_EV_REL_ + BU_SG_REL_ + CAT_ + CAT_DEF_ + CM_ + ENVVAR_DATA_ + EV_DATA_ + FILTER + NS_DESC_ + SGTYPE_ + SGTYPE_VAL_ + SG_MUL_VAL_ + SIGTYPE_VALTYPE_ + SIG_GROUP_ + SIG_TYPE_REF_ + SIG_VALTYPE_ + VAL_ + VAL_TABLE_ + +BS_: + +BU_: DBG DRIVER IO MOTOR SENSOR + +BO_ 500 IO_DEBUG: 4 IO + SG_ IO_DEBUG_test_unsigned : 0|8@1+ (1,0) [0|0] "" DBG diff --git a/test/test_dbc.cpp b/test/test_dbc.cpp index 19e6b5e..8ae1b54 100644 --- a/test/test_dbc.cpp +++ b/test/test_dbc.cpp @@ -3,29 +3,35 @@ #include #include #include +#include #include #include #include +using Catch::Matchers::ContainsSubstring; + TEST_CASE("Testing dbc file loading error issues", "[fileio][error]") { auto parser = std::unique_ptr(new Libdbc::DbcParser()); SECTION("Loading a non dbc file should throw an error", "[error]") { - REQUIRE_THROWS_AS(parser->parse_file(TEXT_FILE), Libdbc::ValidityError); + REQUIRE_THROWS_AS(parser->parse_file(TEXT_FILE), Libdbc::NonDbcFileFormatError); + REQUIRE_THROWS_WITH(parser->parse_file(TEXT_FILE), ContainsSubstring("TextFile.txt")); } - SECTION("Loading a dbc with bad headers throws an error", "[error]") { - REQUIRE_THROWS_AS(parser->parse_file(MISSING_VERSION_DBC_FILE), Libdbc::ValidityError); + SECTION("Loading a dbc with missing version header throws an error (VERSION)", "[error]") { + REQUIRE_THROWS_AS(parser->parse_file(MISSING_VERSION_DBC_FILE), Libdbc::DbcFileIsMissingVersion); + REQUIRE_THROWS_WITH(parser->parse_file(MISSING_VERSION_DBC_FILE), ContainsSubstring("line: (NS_ :)")); } SECTION("Loading a dbc without the required bit timing section (BS_:)", "[error]") { - REQUIRE_THROWS_AS(parser->parse_file(MISSING_BIT_TIMING_DBC_FILE), Libdbc::ValidityError); + REQUIRE_THROWS_AS(parser->parse_file(MISSING_BIT_TIMING_DBC_FILE), Libdbc::DbcFileIsMissingBitTiming); + REQUIRE_THROWS_WITH(parser->parse_file(MISSING_BIT_TIMING_DBC_FILE), ContainsSubstring("BU_: DBG DRIVER IO MOTOR SENSOR")); } SECTION("Loading a dbc with some missing namespace section tags (NS_ :)", "[error]") { // Confusion about this type of error. it appears that the header isn't // very well standardized for now we ignore this type of error. - CHECK_NOTHROW(parser->parse_file(MISSING_NEW_SYMBOLS_DBC_FILE)); + REQUIRE_NOTHROW(parser->parse_file(MISSING_NEW_SYMBOLS_DBC_FILE)); } SECTION("Verify that what() method is accessible for all exceptions", "[error]") { @@ -240,7 +246,7 @@ VAL_ 123 State1 123 "Description 3" 0 "Description 4" ;)"; REQUIRE(signal2.value_descriptions.at(1).description == "Description 4"); } -TEST_CASE("Should parse DBC with empty BU_") { +TEST_CASE("Should parse DBC with empty BU_", "[error][optional]") { std::string contents = R"(VERSION "" @@ -254,15 +260,52 @@ NS_ : BO_ 293 Msg1: 2 Vector__XXX SG_ Wert7 : 0|16@1- (1,0) [0|0] "" Vector__XXX -BO_ 292 Msg2: 8 Vector__XXX +BO_ 292 Msg2: 1 Vector__XXX SG_ Wert8 : 56|8@1- (1,0) [0|0] "" Vector__XXX )"; const auto filename = create_temporary_dbc_with(contents.c_str()); auto parser = Libdbc::DbcParser(); - parser.parse_file(filename.c_str()); + REQUIRE_NOTHROW(parser.parse_file(filename.c_str())); REQUIRE(parser.get_messages().size() == 2); REQUIRE(parser.get_messages().at(0).name() == "Msg1"); REQUIRE(parser.get_messages().at(1).name() == "Msg2"); } + +TEST_CASE("Should report unused lines since we don't have tracing.", "[parsing]") { + std::string contents = R"(VERSION "" + +NS_ : + +BS_: + +BU_: + + +BO_ 293 Msg1: 2 Vector__XXX + SG_ Whitespace: | 0|16@1- (1,0) [0|0] "" Vector__XXX + SG_ Wert7 : 0|16@1- (1,0) [0|0] "" Vector__XXX + SG_ Wert8 : 0|16@1- (1,0) [0|0] "" Vector__XXX + +BO_ 292 Msg2: 1 Vector__XXX + SG_ Wert8 : 56|8@1- (1,0) [0|0] "" Vector__XXX + SB_ not a correct line + +BO_ have a issue here: +)"; + + const auto filename = create_temporary_dbc_with(contents.c_str()); + + auto parser = Libdbc::DbcParser(); + REQUIRE_NOTHROW(parser.parse_file(filename.c_str())); + + REQUIRE(parser.get_messages().size() == 2); + REQUIRE(parser.get_messages()[0].size() == 2); + REQUIRE(parser.get_messages()[1].size() == 1); + + auto unused = parser.unused_lines(); + + // We could match them all here but i think just a check that the size is sufficent. + REQUIRE(unused.size() == 3); +} diff --git a/test/testing_utils/common.cpp b/test/testing_utils/common.cpp index e058054..4c3ef54 100644 --- a/test/testing_utils/common.cpp +++ b/test/testing_utils/common.cpp @@ -23,7 +23,7 @@ std::string generate_unique_filename() { int random_num = dis(gen); // Concatenate time and random number to create a unique filename - return "temp_file_" + std::to_string(milliseconds) + "_" + std::to_string(random_num) + ".txt"; + return "temp_file_" + std::to_string(milliseconds) + "_" + std::to_string(random_num) + ".dbc"; } std::string create_temporary_dbc_with(const char* contents) { From cc4e80c7b6e1f7a13cc47b45f226756f823888e2 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Tue, 19 Mar 2024 16:35:07 -0400 Subject: [PATCH 33/47] feat: Bump to version 0.4.0 for release --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2d4fb58..cbf2d37 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.16) # Keep this on one line for release checking -project(dbc VERSION 0.3.0 DESCRIPTION "C++ DBC Parser") +project(dbc VERSION 0.4.0 DESCRIPTION "C++ DBC Parser") # -- PROJECT OPTIONS -- # option(DBC_ENABLE_TESTS "Enable Unittests" ON) From 57da1f7aa29c09828a9835c02f4d9f8f69dcd3ad Mon Sep 17 00:00:00 2001 From: Stefan Gerlach Date: Fri, 10 May 2024 00:08:14 +0200 Subject: [PATCH 34/47] Update CMakeLists.txt (#26) Fix CMake error "install DIRECTORY given no DESTINATION!" --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index cbf2d37..ea27c35 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,6 +95,7 @@ if(DBC_GENERATE_SINGLE_HEADER) endif() ## Installation +include(GNUInstallDirs) # install lib install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}) From f08e688e6162fa227f0367d591ce9e15d99e7ee4 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Tue, 21 May 2024 17:32:38 -0400 Subject: [PATCH 35/47] fix: Set the ubuntu runner to 22.04 to keep the same compiler version Probably should setup the job to setup the gcc version instead but for now this works. --- .github/workflows/pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 49c3b6e..bb94b75 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -9,7 +9,7 @@ env: jobs: linux-builds: name: linux ${{matrix.cxx}}, C++${{matrix.std}}, ${{matrix.build_type}} - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 strategy: fail-fast: false matrix: From eea0184f4d919d364bec5b9b27e9d42f6121ec9c Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Tue, 21 May 2024 17:40:13 -0400 Subject: [PATCH 36/47] fix(CI): Bump gcc to 14, add debug print, and set the mac os to 12 --- .github/workflows/pipeline.yml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index bb94b75..29e1951 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -14,13 +14,13 @@ jobs: fail-fast: false matrix: cxx: - - g++-13 + - g++-14 - clang++-16 build_type: [Debug, Release] std: [11] include: - - cxx: g++-13 - cc: gcc-13 + - cxx: g++-14 + cc: gcc-14 - cxx: clang++-16 cc: clang-16 llvm_version: 16 @@ -48,6 +48,11 @@ jobs: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y source "$HOME/.cargo/env" + - name: Print gcc version + run: | + which gcc + gcc --version + - name: Configure build env: CC: ${{matrix.cc}} @@ -114,7 +119,7 @@ jobs: macos-builds: name: macos ${{matrix.cxx}}, C++${{matrix.std}}, ${{matrix.build_type}} - runs-on: macos-latest + runs-on: macos-12 strategy: fail-fast: false matrix: From c79a284ccf68947818130f467c50d02716244b24 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Tue, 21 May 2024 17:41:56 -0400 Subject: [PATCH 37/47] fix(CI): Change gcc to 11 which is default installed on ubuntu 22 --- .github/workflows/pipeline.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 29e1951..cc0cf9e 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -14,13 +14,13 @@ jobs: fail-fast: false matrix: cxx: - - g++-14 + - g++-11 - clang++-16 build_type: [Debug, Release] std: [11] include: - - cxx: g++-14 - cc: gcc-14 + - cxx: g++-11 + cc: gcc-11 - cxx: clang++-16 cc: clang-16 llvm_version: 16 @@ -49,9 +49,7 @@ jobs: source "$HOME/.cargo/env" - name: Print gcc version - run: | - which gcc - gcc --version + run: gcc --version - name: Configure build env: From a58f04c0448ba71d9b725fb3a2119df0f35d425b Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Tue, 21 May 2024 17:49:33 -0400 Subject: [PATCH 38/47] feat(CI): Run cmake install for all OS --- .github/workflows/pipeline.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index cc0cf9e..881138c 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -73,6 +73,10 @@ jobs: CTEST_OUTPUT_ON_FAILURE: 1 run: ctest --output-on-failure --test-dir build -j `nproc` + - name: Run install + run: cmake --install . + + windows-build: name: ${{matrix.os}}, ${{matrix.std}}, ${{matrix.build_type}}, ${{matrix.platform}} runs-on: ${{matrix.os}} @@ -115,6 +119,9 @@ jobs: run: ctest --output-on-failure --test-dir build -j %NUMBER_OF_PROCESSORS% shell: cmd + - name: Run install + run: cmake --install . + macos-builds: name: macos ${{matrix.cxx}}, C++${{matrix.std}}, ${{matrix.build_type}} runs-on: macos-12 @@ -162,6 +169,9 @@ jobs: working-directory: ${{runner.workspace}} run: ctest --output-on-failure --test-dir build -j `sysctl -n hw.ncpu` -V + - name: Run install + run: cmake --install . + format-check: runs-on: ubuntu-latest From 2e974178f598e615f65a6ad1a00f7d926823deb2 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Tue, 21 May 2024 17:53:50 -0400 Subject: [PATCH 39/47] fix(CI): fix the cmake build path for the install command --- .github/workflows/pipeline.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 881138c..15f21e4 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -74,7 +74,7 @@ jobs: run: ctest --output-on-failure --test-dir build -j `nproc` - name: Run install - run: cmake --install . + run: cmake --install build windows-build: @@ -120,7 +120,7 @@ jobs: shell: cmd - name: Run install - run: cmake --install . + run: cmake --install build macos-builds: name: macos ${{matrix.cxx}}, C++${{matrix.std}}, ${{matrix.build_type}} @@ -170,7 +170,7 @@ jobs: run: ctest --output-on-failure --test-dir build -j `sysctl -n hw.ncpu` -V - name: Run install - run: cmake --install . + run: cmake --install build format-check: runs-on: ubuntu-latest From 6d6288550fb0226c8b9c65a69c6421b25f4ab42f Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Tue, 21 May 2024 17:58:04 -0400 Subject: [PATCH 40/47] fix(CI): In the pipeline we only can install on linux and need to pass the prefix to avoid permission issues --- .github/workflows/pipeline.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 15f21e4..f36b26d 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -74,7 +74,7 @@ jobs: run: ctest --output-on-failure --test-dir build -j `nproc` - name: Run install - run: cmake --install build + run: cmake --install build --prefix . windows-build: @@ -119,9 +119,6 @@ jobs: run: ctest --output-on-failure --test-dir build -j %NUMBER_OF_PROCESSORS% shell: cmd - - name: Run install - run: cmake --install build - macos-builds: name: macos ${{matrix.cxx}}, C++${{matrix.std}}, ${{matrix.build_type}} runs-on: macos-12 @@ -169,9 +166,6 @@ jobs: working-directory: ${{runner.workspace}} run: ctest --output-on-failure --test-dir build -j `sysctl -n hw.ncpu` -V - - name: Run install - run: cmake --install build - format-check: runs-on: ubuntu-latest From 0dbe4541e99b81049ef7109d1670e37a67b41a8a Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Sun, 26 May 2024 16:38:42 -0400 Subject: [PATCH 41/47] feat: Parse dbc with istream (#30) * feat: Add an istream interface to the avoid the ifstream creation given a file name * fix: formatting the code base to fix checks and clang-tidy errors --- include/libdbc/dbc.hpp | 4 +++- src/dbc.cpp | 19 +++++++++------ .../test_single_header.cpp | 24 +++++++++++++++++++ 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/include/libdbc/dbc.hpp b/include/libdbc/dbc.hpp index 2dfe7bf..5e0e9e4 100644 --- a/include/libdbc/dbc.hpp +++ b/include/libdbc/dbc.hpp @@ -15,6 +15,7 @@ class Parser { virtual ~Parser() = default; virtual void parse_file(const std::string& file) = 0; + virtual void parse_file(std::istream& file) = 0; protected: }; @@ -23,7 +24,8 @@ class DbcParser : public Parser { public: DbcParser(); - void parse_file(const std::string& file) override; + void parse_file(const std::string& file_name) override; + void parse_file(std::istream& stream) override; std::string get_version() const; std::vector get_nodes() const; diff --git a/src/dbc.cpp b/src/dbc.cpp index 108ab7e..c6baae5 100644 --- a/src/dbc.cpp +++ b/src/dbc.cpp @@ -70,18 +70,12 @@ DbcParser::DbcParser() + whiteSpace + receiverPattern) { } -void DbcParser::parse_file(const std::string& file) { - std::ifstream stream(file.c_str()); +void DbcParser::parse_file(std::istream& stream) { std::string line; std::vector lines; messages.clear(); - auto extension = get_extension(file); - if (extension != ".dbc") { - throw NonDbcFileFormatError(file, extension); - } - parse_dbc_header(stream); parse_dbc_nodes(stream); @@ -93,6 +87,17 @@ void DbcParser::parse_file(const std::string& file) { parse_dbc_messages(lines); } +void DbcParser::parse_file(const std::string& file_name) { + auto extension = get_extension(file_name); + if (extension != ".dbc") { + throw NonDbcFileFormatError(file_name, extension); + } + + std::ifstream stream(file_name.c_str()); + + parse_file(stream); +} + std::string DbcParser::get_extension(const std::string& file_name) { std::size_t dot = file_name.find_last_of("."); if (dot != std::string::npos) { diff --git a/test/single_header_testing/test_single_header.cpp b/test/single_header_testing/test_single_header.cpp index e4abc6c..c512d35 100644 --- a/test/single_header_testing/test_single_header.cpp +++ b/test/single_header_testing/test_single_header.cpp @@ -54,3 +54,27 @@ TEST_CASE("Testing big endian, little endian") { REQUIRE(signal.is_bigendian == false); } } + +TEST_CASE("Testing file stream mirrors the filename interface") { + std::string dbc_contents = PRIMITIVE_DBC + 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)"; + const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); + std::ifstream file(filename.c_str()); + + auto parser = Libdbc::DbcParser(); + parser.parse_file(file); + + REQUIRE(parser.get_messages().size() == 1); + REQUIRE(parser.get_messages().at(0).name() == "MSG1"); + REQUIRE(parser.get_messages().at(0).size() == 8); + REQUIRE(parser.get_messages().at(0).get_signals().size() == 2); + { + const auto signal = parser.get_messages().at(0).get_signals().at(0); + REQUIRE(signal.is_bigendian == true); + } + { + const auto signal = parser.get_messages().at(0).get_signals().at(1); + REQUIRE(signal.is_bigendian == false); + } +} From 1bfead321ec4f10a5dd371c8d05769da6a0a78a2 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Sun, 26 May 2024 16:45:59 -0400 Subject: [PATCH 42/47] fix: Crashed when BO_ and the message content were on different lines --- src/dbc.cpp | 4 ++-- test/test_parse_message.cpp | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/dbc.cpp b/src/dbc.cpp index 108ab7e..f19fe25 100644 --- a/src/dbc.cpp +++ b/src/dbc.cpp @@ -176,7 +176,7 @@ void DbcParser::parse_dbc_messages(const std::vector& lines) { continue; } - if (std::regex_search(line, match, signal_re)) { + if (std::regex_search(line, match, signal_re) && messages.size() > 0) { std::string name = match.str(SIGNAL_NAME_GROUP); bool is_multiplexed = false; // No support yet uint32_t start_bit = static_cast(std::stoul(match.str(SIGNAL_START_BIT_GROUP))); @@ -199,7 +199,7 @@ void DbcParser::parse_dbc_messages(const std::vector& lines) { continue; } - if (std::regex_search(line, match, value_re)) { + if (std::regex_search(line, match, value_re) && messages.size() > 0) { uint32_t message_id = static_cast(std::stoul(match.str(2))); std::string signal_name = match.str(3); diff --git a/test/test_parse_message.cpp b/test/test_parse_message.cpp index aad3b1c..08d68f3 100644 --- a/test/test_parse_message.cpp +++ b/test/test_parse_message.cpp @@ -173,3 +173,39 @@ TEST_CASE("Parse Message data length < 8 unsigned") { REQUIRE(Catch::Approx(result_values.at(0)) == 0x1); REQUIRE(Catch::Approx(result_values.at(1)) == 0x2); } + +TEST_CASE("Parse message with BO_ on single line should fail.") { + std::string dbc_contents = PRIMITIVE_DBC + R"(BO_ +234 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 +VAL_ 234 State1 123 "Description 1" 0 "Description 2" 90903489 "Big value and special characters &$§())!")"; + const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); + + Libdbc::DbcParser p; + p.parse_file(filename); + + std::vector data{0x1, 0x2}; + std::vector result_values; + REQUIRE(p.get_messages().size() == 0); + REQUIRE(p.parse_message(234, data, result_values) == Libdbc::Message::ParseSignalsStatus::ErrorUnknownID); +} + +TEST_CASE("Parse signal with SG_ on single line should fail.") { + std::string dbc_contents = PRIMITIVE_DBC + R"(BO_ 234 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 +VAL_ 234 State1 123 "Description 1" 0 "Description 2" 90903489 "Big value and special characters &$§())!")"; + const auto filename = create_temporary_dbc_with(dbc_contents.c_str()); + + Libdbc::DbcParser p; + p.parse_file(filename); + + std::vector data{0x1, 0x2}; + std::vector result_values; + REQUIRE(p.get_messages().size() == 1); + REQUIRE(p.parse_message(234, data, result_values) == Libdbc::Message::ParseSignalsStatus::Success); + REQUIRE(result_values.size() == 1); + REQUIRE(Catch::Approx(result_values.at(0)) == 0x1); +} From ceeef752101dccfa045106592f17dedaf64c9656 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Thu, 27 Jun 2024 18:17:25 -0400 Subject: [PATCH 43/47] fix(checks): Fixing clang warnings about size comparison on the vector. Should have been just a empty check. --- src/dbc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dbc.cpp b/src/dbc.cpp index 2d999da..89e8c24 100644 --- a/src/dbc.cpp +++ b/src/dbc.cpp @@ -181,7 +181,7 @@ void DbcParser::parse_dbc_messages(const std::vector& lines) { continue; } - if (std::regex_search(line, match, signal_re) && messages.size() > 0) { + if (std::regex_search(line, match, signal_re) && !messages.empty()) { std::string name = match.str(SIGNAL_NAME_GROUP); bool is_multiplexed = false; // No support yet uint32_t start_bit = static_cast(std::stoul(match.str(SIGNAL_START_BIT_GROUP))); @@ -204,7 +204,7 @@ void DbcParser::parse_dbc_messages(const std::vector& lines) { continue; } - if (std::regex_search(line, match, value_re) && messages.size() > 0) { + if (std::regex_search(line, match, value_re) && !messages.empty()) { uint32_t message_id = static_cast(std::stoul(match.str(2))); std::string signal_name = match.str(3); From 887d779fbf416032f539675f74360a5a43a93f86 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Thu, 27 Jun 2024 18:19:17 -0400 Subject: [PATCH 44/47] chore(version): Version bump to v0.5.0 --- CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ea27c35..551af92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.16) # Keep this on one line for release checking -project(dbc VERSION 0.4.0 DESCRIPTION "C++ DBC Parser") +project(dbc VERSION 0.5.0 DESCRIPTION "C++ DBC Parser") # -- PROJECT OPTIONS -- # option(DBC_ENABLE_TESTS "Enable Unittests" ON) @@ -95,7 +95,6 @@ if(DBC_GENERATE_SINGLE_HEADER) endif() ## Installation -include(GNUInstallDirs) # install lib install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}) From 17b3e3dd121f3dc13f07a3cc0d9a19ce7b138ece Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Wed, 10 Sep 2025 21:52:33 -0400 Subject: [PATCH 45/47] Add manual workflow dispatch to CI pipeline --- .github/workflows/pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index f36b26d..0947cd6 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -1,6 +1,6 @@ name: Libdbc Pipeline -on: [push, workflow_call] +on: [push, workflow_call, workflow_dispatch] env: # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) From 316686831a1a064fedebdd77f8fd4e6d9b183db3 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Wed, 10 Sep 2025 21:54:48 -0400 Subject: [PATCH 46/47] Enable pull_request to trigger CI pipeline --- .github/workflows/pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 0947cd6..d24e09a 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -1,6 +1,6 @@ name: Libdbc Pipeline -on: [push, workflow_call, workflow_dispatch] +on: [push, pull_request, workflow_call, workflow_dispatch] env: # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) From 2c8acdbd2d1ea33545f99f9a0d23e10b7f8e0852 Mon Sep 17 00:00:00 2001 From: Devon Adair Date: Fri, 12 Sep 2025 10:29:36 -0400 Subject: [PATCH 47/47] Update windows runner to 2025 and mac runners to 15 (#35) --- .github/workflows/pipeline.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index d24e09a..3f96f40 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -83,7 +83,7 @@ jobs: strategy: fail-fast: false matrix: - os: [windows-2019, windows-2022] + os: [windows-2025, windows-2022] platform: [Win32, x64] build_type: [Debug, Release] std: [11] @@ -120,11 +120,12 @@ jobs: shell: cmd macos-builds: - name: macos ${{matrix.cxx}}, C++${{matrix.std}}, ${{matrix.build_type}} - runs-on: macos-12 + name: ${{matrix.os}}, ${{matrix.cxx}}, C++${{matrix.std}}, ${{matrix.build_type}} + runs-on: ${{matrix.os}} strategy: fail-fast: false matrix: + os: [macos-15-large] cxx: - g++ - clang++