From c4c24f5cd7e4c856bc92e275549194c8f550ce80 Mon Sep 17 00:00:00 2001 From: Uight Date: Tue, 20 Aug 2024 22:23:17 +0200 Subject: [PATCH] #72 #69 #37 #14 Redfine all Model classes to be readonly for public access. Use FinishUp method to calc useful properties. --- .gitignore | 1 + DbcParserLib.Tests/DbcBuilderTests.cs | 110 +-- DbcParserLib.Tests/DbcParserLib.Tests.csproj | 3 +- DbcParserLib.Tests/ExtensionMethodsTests.cs | 100 --- DbcParserLib.Tests/MessageTests.cs | 56 ++ DbcParserLib.Tests/MultiplexingInfoTests.cs | 77 +++ DbcParserLib.Tests/ParserTests.cs | 54 +- .../PropertiesDefaultParsingFailuresTests.cs | 4 +- .../PropertiesLineParserTests.cs | 20 +- .../PropertiesParsingFailuresTests.cs | 4 +- DbcParserLib.Tests/SignalLineParserTests.cs | 10 +- DbcParserLib/Dbc.cs | 22 - DbcParserLib/DbcBuilder.cs | 635 ++++++++++-------- DbcParserLib/DbcParserLib.csproj | 3 +- DbcParserLib/ExtensionsAndHelpers.cs | 88 +-- DbcParserLib/Model/CustomProperty.cs | 202 +++--- .../Model/CustomPropertyDefinition.cs | 389 ++++++----- DbcParserLib/Model/Dbc.cs | 30 + DbcParserLib/Model/EnvironmentVariable.cs | 107 ++- DbcParserLib/Model/Message.cs | 88 +-- DbcParserLib/Model/MultiplexingInfo.cs | 52 +- DbcParserLib/Model/Node.cs | 46 +- DbcParserLib/Model/Signal.cs | 142 ++-- DbcParserLib/Parser.cs | 1 + DbcParserLib/Parsers/SignalLineParser.cs | 8 +- Demo/Demo.csproj | 2 +- Demo/Form1.cs | 12 +- 27 files changed, 1167 insertions(+), 1099 deletions(-) create mode 100644 DbcParserLib.Tests/MessageTests.cs create mode 100644 DbcParserLib.Tests/MultiplexingInfoTests.cs delete mode 100644 DbcParserLib/Dbc.cs create mode 100644 DbcParserLib/Model/Dbc.cs diff --git a/.gitignore b/.gitignore index 96fb177..db050b2 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ *.suo *.user *.sln.docstates +.idea .vs # Build results diff --git a/DbcParserLib.Tests/DbcBuilderTests.cs b/DbcParserLib.Tests/DbcBuilderTests.cs index 892e850..6f3e9f6 100644 --- a/DbcParserLib.Tests/DbcBuilderTests.cs +++ b/DbcParserLib.Tests/DbcBuilderTests.cs @@ -105,8 +105,8 @@ public void MessageIsAdded() Assert.IsEmpty(dbc.Nodes); Assert.AreEqual(1, dbc.Messages.Count()); - Assert.AreEqual(1, dbc.Messages.First().ID); - Assert.IsFalse(dbc.Messages.First().IsExtID); + Assert.AreEqual(1, dbc.Messages.First().Value.ID); + Assert.IsFalse(dbc.Messages.First().Value.IsExtID); } [Test] @@ -119,8 +119,8 @@ public void ExtendedMessageIsAdded() Assert.IsEmpty(dbc.Nodes); Assert.AreEqual(1, dbc.Messages.Count()); - Assert.AreEqual(1, dbc.Messages.First().ID); - Assert.IsTrue(dbc.Messages.First().IsExtID); + Assert.AreEqual(1, dbc.Messages.First().Value.ID); + Assert.IsTrue(dbc.Messages.First().Value.IsExtID); } [Test] @@ -134,8 +134,8 @@ public void CommentIsAddedToMessage() Assert.IsEmpty(dbc.Nodes); Assert.AreEqual(1, dbc.Messages.Count()); - Assert.AreEqual(234, dbc.Messages.First().ID); - Assert.AreEqual("comment", dbc.Messages.First().Comment); + Assert.AreEqual(234, dbc.Messages.First().Value.ID); + Assert.AreEqual("comment", dbc.Messages.First().Value.Comment); } [Test] @@ -149,8 +149,8 @@ public void CommentIsNotAddedToMissingMessage() Assert.IsEmpty(dbc.Nodes); Assert.AreEqual(1, dbc.Messages.Count()); - Assert.AreEqual(234, dbc.Messages.First().ID); - Assert.IsNull(dbc.Messages.First().Comment); + Assert.AreEqual(234, dbc.Messages.First().Value.ID); + Assert.IsNull(dbc.Messages.First().Value.Comment); } [Test] @@ -178,14 +178,14 @@ public void SignalIsAddedToCurrentMessage() Assert.AreEqual(2, dbc.Messages.Count()); var messagesToArray = dbc.Messages.ToArray(); - Assert.AreEqual(234, messagesToArray[0].ID); - Assert.AreEqual(1, messagesToArray[0].Signals.Count()); - Assert.AreEqual("name1", messagesToArray[0].Signals.First().Name); - - Assert.AreEqual(235, messagesToArray[1].ID); - Assert.AreEqual(2, messagesToArray[1].Signals.Count()); - Assert.AreEqual("name2", messagesToArray[1].Signals.First().Name); - Assert.AreEqual("name3", messagesToArray[1].Signals.Skip(1).First().Name); + Assert.AreEqual(234, messagesToArray[0].Value.ID); + Assert.AreEqual(1, messagesToArray[0].Value.Signals.Count()); + Assert.AreEqual("name1", messagesToArray[0].Value.Signals.First().Value.Name); + + Assert.AreEqual(235, messagesToArray[1].Value.ID); + Assert.AreEqual(2, messagesToArray[1].Value.Signals.Count()); + Assert.AreEqual("name2", messagesToArray[1].Value.Signals.First().Value.Name); + Assert.AreEqual("name3", messagesToArray[1].Value.Signals.Skip(1).First().Value.Name); } [Test] @@ -213,9 +213,9 @@ public void CommentIsAddedToSignal() Assert.IsEmpty(dbc.Nodes); Assert.AreEqual(1, dbc.Messages.Count()); - Assert.AreEqual(234, dbc.Messages.First().ID); - Assert.AreEqual("name1", dbc.Messages.First().Signals.First().Name); - Assert.AreEqual("comment", dbc.Messages.First().Signals.First().Comment); + Assert.AreEqual(234, dbc.Messages.First().Value.ID); + Assert.AreEqual("name1", dbc.Messages.First().Value.Signals.First().Value.Name); + Assert.AreEqual("comment", dbc.Messages.First().Value.Signals.First().Value.Comment); } [Test] @@ -232,9 +232,9 @@ public void CommentIsNotAddedToMissingSignalMessageId() Assert.IsEmpty(dbc.Nodes); Assert.AreEqual(1, dbc.Messages.Count()); - Assert.AreEqual(234, dbc.Messages.First().ID); - Assert.AreEqual("name1", dbc.Messages.First().Signals.First().Name); - Assert.IsNull(dbc.Messages.First().Signals.First().Comment); + Assert.AreEqual(234, dbc.Messages.First().Value.ID); + Assert.AreEqual("name1", dbc.Messages.First().Value.Signals.First().Value.Name); + Assert.IsNull(dbc.Messages.First().Value.Signals.First().Value.Comment); } [Test] @@ -251,9 +251,9 @@ public void CommentIsNotAddedToMissingSignalName() Assert.IsEmpty(dbc.Nodes); Assert.AreEqual(1, dbc.Messages.Count()); - Assert.AreEqual(234, dbc.Messages.First().ID); - Assert.AreEqual("name1", dbc.Messages.First().Signals.First().Name); - Assert.IsNull(dbc.Messages.First().Signals.First().Comment); + Assert.AreEqual(234, dbc.Messages.First().Value.ID); + Assert.AreEqual("name1", dbc.Messages.First().Value.Signals.First().Value.Name); + Assert.IsNull(dbc.Messages.First().Value.Signals.First().Value.Comment); } [Test] @@ -271,11 +271,11 @@ public void TableValuesAreAddedToSignal() Assert.IsEmpty(dbc.Nodes); Assert.AreEqual(1, dbc.Messages.Count()); - Assert.AreEqual(234, dbc.Messages.First().ID); - Assert.AreEqual("name1", dbc.Messages.First().Signals.First().Name); - Assert.AreEqual(testValuesDict, dbc.Messages.First().Signals.First().ValueTableMap); - Assert.AreEqual(1, dbc.Messages.First().Signals.First().ValueTableMap.Keys.First()); - Assert.AreEqual("fake", dbc.Messages.First().Signals.First().ValueTableMap.Values.First()); + Assert.AreEqual(234, dbc.Messages.First().Value.ID); + Assert.AreEqual("name1", dbc.Messages.First().Value.Signals.First().Value.Name); + Assert.AreEqual(testValuesDict, dbc.Messages.First().Value.Signals.First().Value.ValueTableMap); + Assert.AreEqual(1, dbc.Messages.First().Value.Signals.First().Value.ValueTableMap.Keys.First()); + Assert.AreEqual("fake", dbc.Messages.First().Value.Signals.First().Value.ValueTableMap.Values.First()); } [Test] @@ -293,11 +293,11 @@ public void TableValuesWithExtendedMessageIdAreAddedToSignal() Assert.IsEmpty(dbc.Nodes); Assert.AreEqual(1, dbc.Messages.Count()); - Assert.AreEqual(message.ID, dbc.Messages.First().ID); - Assert.AreEqual("name1", dbc.Messages.First().Signals.First().Name); - Assert.AreEqual(testValuesDict, dbc.Messages.First().Signals.First().ValueTableMap); - Assert.AreEqual(1, dbc.Messages.First().Signals.First().ValueTableMap.Keys.First()); - Assert.AreEqual("fake", dbc.Messages.First().Signals.First().ValueTableMap.Values.First()); + Assert.AreEqual(message.ID, dbc.Messages.First().Value.ID); + Assert.AreEqual("name1", dbc.Messages.First().Value.Signals.First().Value.Name); + Assert.AreEqual(testValuesDict, dbc.Messages.First().Value.Signals.First().Value.ValueTableMap); + Assert.AreEqual(1, dbc.Messages.First().Value.Signals.First().Value.ValueTableMap.Keys.First()); + Assert.AreEqual("fake", dbc.Messages.First().Value.Signals.First().Value.ValueTableMap.Values.First()); } [Test] @@ -315,9 +315,9 @@ public void TableValueIsNotAddedToMissingSignalMessageId() Assert.IsEmpty(dbc.Nodes); Assert.AreEqual(1, dbc.Messages.Count()); - Assert.AreEqual(234, dbc.Messages.First().ID); - Assert.AreEqual("name1", dbc.Messages.First().Signals.First().Name); - Assert.IsEmpty(dbc.Messages.First().Signals.First().ValueTableMap); + Assert.AreEqual(234, dbc.Messages.First().Value.ID); + Assert.AreEqual("name1", dbc.Messages.First().Value.Signals.First().Value.Name); + Assert.IsEmpty(dbc.Messages.First().Value.Signals.First().Value.ValueTableMap); } [Test] @@ -335,9 +335,9 @@ public void TableValueIsNotAddedToMissingSignalName() Assert.IsEmpty(dbc.Nodes); Assert.AreEqual(1, dbc.Messages.Count()); - Assert.AreEqual(234, dbc.Messages.First().ID); - Assert.AreEqual("name1", dbc.Messages.First().Signals.First().Name); - Assert.IsEmpty(dbc.Messages.First().Signals.First().ValueTableMap); + Assert.AreEqual(234, dbc.Messages.First().Value.ID); + Assert.AreEqual("name1", dbc.Messages.First().Value.Signals.First().Value.Name); + Assert.IsEmpty(dbc.Messages.First().Value.Signals.First().Value.ValueTableMap); } [Test] @@ -357,11 +357,11 @@ public void NamedTableValuesAreAddedToSignal() Assert.IsEmpty(dbc.Nodes); Assert.AreEqual(1, dbc.Messages.Count()); - Assert.AreEqual(234, dbc.Messages.First().ID); - Assert.AreEqual("name1", dbc.Messages.First().Signals.First().Name); - Assert.AreEqual(testValuesDict, dbc.Messages.First().Signals.First().ValueTableMap); - Assert.AreEqual(1, dbc.Messages.First().Signals.First().ValueTableMap.Keys.First()); - Assert.AreEqual("fake", dbc.Messages.First().Signals.First().ValueTableMap.Values.First()); + Assert.AreEqual(234, dbc.Messages.First().Value.ID); + Assert.AreEqual("name1", dbc.Messages.First().Value.Signals.First().Value.Name); + Assert.AreEqual(testValuesDict, dbc.Messages.First().Value.Signals.First().Value.ValueTableMap); + Assert.AreEqual(1, dbc.Messages.First().Value.Signals.First().Value.ValueTableMap.Keys.First()); + Assert.AreEqual("fake", dbc.Messages.First().Value.Signals.First().Value.ValueTableMap.Values.First()); } [Test] @@ -381,9 +381,9 @@ public void NamedTableValueIsNotAddedToMissingSignalMessageId() Assert.IsEmpty(dbc.Nodes); Assert.AreEqual(1, dbc.Messages.Count()); - Assert.AreEqual(234, dbc.Messages.First().ID); - Assert.AreEqual("name1", dbc.Messages.First().Signals.First().Name); - Assert.IsEmpty(dbc.Messages.First().Signals.First().ValueTableMap); + Assert.AreEqual(234, dbc.Messages.First().Value.ID); + Assert.AreEqual("name1", dbc.Messages.First().Value.Signals.First().Value.Name); + Assert.IsEmpty(dbc.Messages.First().Value.Signals.First().Value.ValueTableMap); } [Test] @@ -403,9 +403,9 @@ public void NamedTableValueIsNotAddedToMissingSignalName() Assert.IsEmpty(dbc.Nodes); Assert.AreEqual(1, dbc.Messages.Count()); - Assert.AreEqual(234, dbc.Messages.First().ID); - Assert.AreEqual("name1", dbc.Messages.First().Signals.First().Name); - Assert.IsEmpty(dbc.Messages.First().Signals.First().ValueTableMap); + Assert.AreEqual(234, dbc.Messages.First().Value.ID); + Assert.AreEqual("name1", dbc.Messages.First().Value.Signals.First().Value.Name); + Assert.IsEmpty(dbc.Messages.First().Value.Signals.First().Value.ValueTableMap); } [Test] @@ -422,9 +422,9 @@ public void NamedTableValueIsNotAddedIfTableNameDoesNotExist() Assert.IsEmpty(dbc.Nodes); Assert.AreEqual(1, dbc.Messages.Count()); - Assert.AreEqual(234, dbc.Messages.First().ID); - Assert.AreEqual("name1", dbc.Messages.First().Signals.First().Name); - Assert.IsEmpty(dbc.Messages.First().Signals.First().ValueTableMap); + Assert.AreEqual(234, dbc.Messages.First().Value.ID); + Assert.AreEqual("name1", dbc.Messages.First().Value.Signals.First().Value.Name); + Assert.IsEmpty(dbc.Messages.First().Value.Signals.First().Value.ValueTableMap); } [Test] diff --git a/DbcParserLib.Tests/DbcParserLib.Tests.csproj b/DbcParserLib.Tests/DbcParserLib.Tests.csproj index 73142da..ac1092c 100644 --- a/DbcParserLib.Tests/DbcParserLib.Tests.csproj +++ b/DbcParserLib.Tests/DbcParserLib.Tests.csproj @@ -1,8 +1,7 @@ - net6.0 - + net8.0 false diff --git a/DbcParserLib.Tests/ExtensionMethodsTests.cs b/DbcParserLib.Tests/ExtensionMethodsTests.cs index e2f4ad4..526f30a 100644 --- a/DbcParserLib.Tests/ExtensionMethodsTests.cs +++ b/DbcParserLib.Tests/ExtensionMethodsTests.cs @@ -35,106 +35,6 @@ public void IntelTest() Assert.IsTrue(sig.Lsb()); } - [Test] - public void NoMultiplexingTest() - { - var sig = new Signal - { - Multiplexing = null, - }; - - var multiplexing = sig.MultiplexingInfo(); - Assert.AreEqual(MultiplexingRole.None, multiplexing.Role); - Assert.AreEqual(0, multiplexing.Group); - } - - [Test] - public void MultiplexorTest() - { - var sig = new Signal - { - Multiplexing = "M", - }; - - var multiplexing = sig.MultiplexingInfo(); - Assert.AreEqual(MultiplexingRole.Multiplexor, multiplexing.Role); - Assert.AreEqual(0, multiplexing.Group); - } - - [Test] - public void MultiplexedSingleDigitTest() - { - var sig = new Signal - { - Multiplexing = "m3", - }; - - var multiplexing = sig.MultiplexingInfo(); - Assert.AreEqual(MultiplexingRole.Multiplexed, multiplexing.Role); - Assert.AreEqual(3, multiplexing.Group); - } - - [Test] - public void ExtendedMultiplexingIsPartiallySupportedTest() - { - var sig = new Signal - { - Multiplexing = "m3M", - }; - - var multiplexing = sig.MultiplexingInfo(); - Assert.AreEqual(MultiplexingRole.Multiplexed, multiplexing.Role); - Assert.AreEqual(3, multiplexing.Group); - } - - [Test] - public void MultiplexedDoubleDigitTest() - { - var sig = new Signal - { - Multiplexing = "m12", - }; - - var multiplexing = sig.MultiplexingInfo(); - Assert.AreEqual(MultiplexingRole.Multiplexed, multiplexing.Role); - Assert.AreEqual(12, multiplexing.Group); - } - - [Test] - public void MultiplexedMessageTest() - { - var sig = new Signal - { - Multiplexing = "M", - }; - - var message = new Message(); - message.Signals.Add(sig); - - Assert.IsTrue(message.IsMultiplexed()); - } - - [Test] - public void MessageWithNoMutiplexorIsNotMultiplexedTest() - { - var sig = new Signal - { - Multiplexing = null, - }; - - var message = new Message(); - message.Signals.Add(sig); - - Assert.IsFalse(message.IsMultiplexed()); - } - - [Test] - public void EmptyMessageIsNotMultiplexedTest() - { - var message = new Message(); - Assert.IsFalse(message.IsMultiplexed()); - } - [TestCase("1 \"First\" 2 \"Second\" 3 \"Third\"")] [TestCase("1 \"First with spaces\" 2 \" Second \" 3 \"T h i r d\"")] [TestCase("1 \"First with spaces\" 2 \" \" 3 \"\"")] diff --git a/DbcParserLib.Tests/MessageTests.cs b/DbcParserLib.Tests/MessageTests.cs new file mode 100644 index 0000000..8980c36 --- /dev/null +++ b/DbcParserLib.Tests/MessageTests.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; +using DbcParserLib.Model; +using NUnit.Framework; + +namespace DbcParserLib.Tests; + +internal class MessageTests +{ + [Test] + public void MultiplexedMessageTest() + { + var sig = new Signal + { + multiplexing = "M", + Name = "Test" + }; + + var message = new Message + { + signals = new Dictionary + { + { "Test", sig } + } + }; + message.FinishUp(); + Assert.IsTrue(message.IsMultiplexed); + } + + [Test] + public void MessageWithNoMutiplexorIsNotMultiplexedTest() + { + var sig = new Signal + { + multiplexing = null, + Name = "Test" + }; + + var message = new Message + { + signals = new Dictionary + { + { "Test", sig } + } + }; + message.FinishUp(); + + Assert.IsFalse(message.IsMultiplexed); + } + + [Test] + public void EmptyMessageIsNotMultiplexedTest() + { + var message = new Message(); + Assert.IsFalse(message.IsMultiplexed); + } +} \ No newline at end of file diff --git a/DbcParserLib.Tests/MultiplexingInfoTests.cs b/DbcParserLib.Tests/MultiplexingInfoTests.cs new file mode 100644 index 0000000..4c7af9b --- /dev/null +++ b/DbcParserLib.Tests/MultiplexingInfoTests.cs @@ -0,0 +1,77 @@ +using DbcParserLib.Model; +using NUnit.Framework; + +namespace DbcParserLib.Tests; + +internal class MultiplexingInfoTests +{ + [Test] + public void NoMultiplexingTest() + { + var sig = new Signal + { + multiplexing = null, + Name = "Test" + }; + + var multiplexing = new MultiplexingInfo(sig); + Assert.AreEqual(MultiplexingRole.None, multiplexing.Role); + Assert.AreEqual(0, multiplexing.Group); + } + + [Test] + public void MultiplexorTest() + { + var sig = new Signal + { + multiplexing = "M", + Name = "Test" + }; + + var multiplexing = new MultiplexingInfo(sig); + Assert.AreEqual(MultiplexingRole.Multiplexor, multiplexing.Role); + Assert.AreEqual(0, multiplexing.Group); + } + + [Test] + public void MultiplexedSingleDigitTest() + { + var sig = new Signal + { + multiplexing = "m3", + Name = "Test" + }; + + var multiplexing = new MultiplexingInfo(sig); + Assert.AreEqual(MultiplexingRole.Multiplexed, multiplexing.Role); + Assert.AreEqual(3, multiplexing.Group); + } + + [Test] + public void ExtendedMultiplexingIsPartiallySupportedTest() + { + var sig = new Signal + { + multiplexing = "m3M", + Name = "Test" + }; + + var multiplexing = new MultiplexingInfo(sig); + Assert.AreEqual(MultiplexingRole.Multiplexed, multiplexing.Role); + Assert.AreEqual(3, multiplexing.Group); + } + + [Test] + public void MultiplexedDoubleDigitTest() + { + var sig = new Signal + { + multiplexing = "m12", + Name = "Test" + }; + + var multiplexing = new MultiplexingInfo(sig); + Assert.AreEqual(MultiplexingRole.Multiplexed, multiplexing.Role); + Assert.AreEqual(12, multiplexing.Group); + } +} \ No newline at end of file diff --git a/DbcParserLib.Tests/ParserTests.cs b/DbcParserLib.Tests/ParserTests.cs index 60c9ee6..1bf60d2 100644 --- a/DbcParserLib.Tests/ParserTests.cs +++ b/DbcParserLib.Tests/ParserTests.cs @@ -16,7 +16,7 @@ public void SimpleParseFileTest() var dbc = Parser.ParseFromPath(MainDbcFilePath); Assert.AreEqual(38, dbc.Messages.Count()); - Assert.AreEqual(485, dbc.Messages.SelectMany(m => m.Signals).Count()); + Assert.AreEqual(485, dbc.Messages.SelectMany(m => m.Value.Signals).Count()); Assert.AreEqual(15, dbc.Nodes.Count()); } [Test] @@ -31,7 +31,7 @@ public void ParseMessageWithStartBitGreaterThan255Test() var dbc = Parser.Parse(dbcString); Assert.AreEqual(1, dbc.Messages.Count()); - Assert.AreEqual(2, dbc.Messages.SelectMany(m => m.Signals).Count()); + Assert.AreEqual(2, dbc.Messages.SelectMany(m => m.Value.Signals).Count()); } [Test] @@ -41,7 +41,7 @@ public void ParsingTwiceClearsCollectionsTest() var dbc = Parser.ParseFromPath(MainDbcFilePath); dbc = Parser.ParseFromPath(MainDbcFilePath); Assert.AreEqual(38, dbc.Messages.Count()); - Assert.AreEqual(485, dbc.Messages.SelectMany(m => m.Signals).Count()); + Assert.AreEqual(485, dbc.Messages.SelectMany(m => m.Value.Signals).Count()); Assert.AreEqual(15, dbc.Nodes.Count()); } @@ -50,13 +50,13 @@ public void CheckMessagePropertiesTest() { var dbc = Parser.ParseFromPath(MainDbcFilePath); - var targetMessage = dbc.Messages.FirstOrDefault(x => x.ID == 309); + var targetMessage = dbc.Messages.FirstOrDefault(x => x.Value.ID == 309); Assert.IsNotNull(targetMessage); - Assert.AreEqual("ESP_135h", targetMessage.Name); - Assert.AreEqual("ESP", targetMessage.Transmitter); - Assert.AreEqual(5, targetMessage.DLC); - Assert.AreEqual(19, targetMessage.Signals.Count); + Assert.AreEqual("ESP_135h", targetMessage.Value.Name); + Assert.AreEqual("ESP", targetMessage.Value.Transmitter); + Assert.AreEqual(5, targetMessage.Value.DLC); + Assert.AreEqual(19, targetMessage.Value.Signals.Count); } [Test] @@ -64,12 +64,12 @@ public void CheckSignalPropertiesTest() { var dbc = Parser.ParseFromPath(MainDbcFilePath); - var targetMessage = dbc.Messages.FirstOrDefault(x => x.ID == 1006); + var targetMessage = dbc.Messages.FirstOrDefault(x => x.Value.ID == 1006); Assert.IsNotNull(targetMessage); - Assert.AreEqual(24, targetMessage.Signals.Count); + Assert.AreEqual(24, targetMessage.Value.Signals.Count); - var signal = targetMessage.Signals.FirstOrDefault(x => x.Name.Equals("UI_camBlockBlurThreshold")); + var signal = targetMessage.Value.Signals.FirstOrDefault(x => x.Value.Name.Equals("UI_camBlockBlurThreshold")).Value; Assert.IsNotNull(signal); Assert.AreEqual(DbcValueType.Unsigned, signal.ValueType); Assert.AreEqual(11, signal.StartBit); @@ -86,12 +86,12 @@ public void CheckOtherSignalPropertiesTest() { var dbc = Parser.ParseFromPath(MainDbcFilePath); - var targetMessage = dbc.Messages.FirstOrDefault(x => x.ID == 264); + var targetMessage = dbc.Messages.FirstOrDefault(x => x.Value.ID == 264); Assert.IsNotNull(targetMessage); - Assert.AreEqual(7, targetMessage.Signals.Count); + Assert.AreEqual(7, targetMessage.Value.Signals.Count); - var signal = targetMessage.Signals.FirstOrDefault(x => x.Name.Equals("DI_torqueMotor")); + var signal = targetMessage.Value.Signals.FirstOrDefault(x => x.Value.Name.Equals("DI_torqueMotor")).Value; Assert.IsNotNull(signal); Assert.AreEqual(DbcValueType.Signed, signal.ValueType); Assert.AreEqual("Nm", signal.Unit); @@ -142,12 +142,12 @@ public void SignalCommentIsProperlyAppliedWhenMultipleSignalsShareSameNameTest() for (var i = 0; i < messageIds.Length; ++i) { - var targetMessage = dbc.Messages.FirstOrDefault(x => x.ID == messageIds[i]); + var targetMessage = dbc.Messages.FirstOrDefault(x => x.Value.ID == messageIds[i]); Assert.IsNotNull(targetMessage); - Assert.AreEqual(signalCount[i], targetMessage.Signals.Count); + Assert.AreEqual(signalCount[i], targetMessage.Value.Signals.Count); - var signal = targetMessage.Signals.FirstOrDefault(x => x.Name.Equals("COUNTER_ALT")); + var signal = targetMessage.Value.Signals.FirstOrDefault(x => x.Value.Name.Equals("COUNTER_ALT")).Value; Assert.IsNotNull(signal); Assert.AreEqual("only increments on change", signal.Comment); } @@ -174,10 +174,10 @@ public void ManagingOtherKindOfCommentsTest() Assert.AreEqual(1, dbc.Messages.Count()); Assert.AreEqual(1, dbc.Nodes.Count()); - Assert.AreEqual("Message comment", dbc.Messages.First().Comment); + Assert.AreEqual("Message comment", dbc.Messages.First().Value.Comment); Assert.AreEqual("Node comment", dbc.Nodes.First().Comment); - var signal = dbc.Messages.Single().Signals.FirstOrDefault(x => x.Name.Equals("COUNTER_ALT")); + var signal = dbc.Messages.Single().Value.Signals.FirstOrDefault(x => x.Value.Name.Equals("COUNTER_ALT")).Value; Assert.IsNotNull(signal); Assert.AreEqual("only increments on change", signal.Comment); } @@ -205,10 +205,10 @@ second line Assert.AreEqual(1, dbc.Messages.Count()); Assert.AreEqual(1, dbc.Nodes.Count()); - Assert.AreEqual($"Message comment first line{Environment.NewLine}second line{Environment.NewLine}third line", dbc.Messages.First().Comment); + Assert.AreEqual($"Message comment first line{Environment.NewLine}second line{Environment.NewLine}third line", dbc.Messages.First().Value.Comment); Assert.AreEqual("Node comment", dbc.Nodes.First().Comment); - var signal = dbc.Messages.Single().Signals.FirstOrDefault(x => x.Name.Equals("COUNTER_ALT")); + var signal = dbc.Messages.Single().Value.Signals.FirstOrDefault(x => x.Value.Name.Equals("COUNTER_ALT")).Value; Assert.IsNotNull(signal); Assert.AreEqual("only increments on change", signal.Comment); } @@ -238,7 +238,7 @@ public void NamedValTableIsAppliedTest() Assert.AreEqual(1, dbc.Messages.Count()); Assert.AreEqual(0, dbc.Nodes.Count()); - var signal = dbc.Messages.Single().Signals.Single(); + var signal = dbc.Messages.Single().Value.Signals.Single().Value; Assert.IsNotNull(signal); Assert.AreEqual(expectedValueTableMap, signal.ValueTableMap); } @@ -266,7 +266,7 @@ public void ExplicitValTableIsAppliedTest() Assert.AreEqual(1, dbc.Messages.Count()); Assert.AreEqual(0, dbc.Nodes.Count()); - var signal = dbc.Messages.Single().Signals.Single(); + var signal = dbc.Messages.Single().Value.Signals.Single().Value; Assert.IsNotNull(signal); Assert.AreEqual(expectedValueTableMap, signal.ValueTableMap); } @@ -307,11 +307,11 @@ public void UserDefinedAttributesTest() Assert.AreEqual(70, node.CustomProperties["HexAttribute"].HexCustomProperty.Value); var message = dbc.Messages.First(); - Assert.AreEqual(2, message.CustomProperties.Count()); - Assert.AreEqual(7, message.CustomProperties["IntegerAttribute"].IntegerCustomProperty.Value); - Assert.AreEqual(0.5, message.CustomProperties["FloatAttribute"].FloatCustomProperty.Value); + Assert.AreEqual(2, message.Value.CustomProperties.Count()); + Assert.AreEqual(7, message.Value.CustomProperties["IntegerAttribute"].IntegerCustomProperty.Value); + Assert.AreEqual(0.5, message.Value.CustomProperties["FloatAttribute"].FloatCustomProperty.Value); - var signal = dbc.Messages.Single().Signals.FirstOrDefault(x => x.Name.Equals("COUNTER_ALT")); + var signal = dbc.Messages.Single().Value.Signals.FirstOrDefault(x => x.Value.Name.Equals("COUNTER_ALT")).Value; Assert.IsNotNull(signal); Assert.AreEqual(2, signal.CustomProperties.Count()); Assert.AreEqual("ThirdVal", signal.CustomProperties["EnumAttributeName"].EnumCustomProperty.Value); diff --git a/DbcParserLib.Tests/PropertiesDefaultParsingFailuresTests.cs b/DbcParserLib.Tests/PropertiesDefaultParsingFailuresTests.cs index 81ecde6..d3950c7 100644 --- a/DbcParserLib.Tests/PropertiesDefaultParsingFailuresTests.cs +++ b/DbcParserLib.Tests/PropertiesDefaultParsingFailuresTests.cs @@ -232,7 +232,7 @@ public void DefaultCustomPropertyEnumWithIntegerValuesIsParsed() var dbc = Parser.Parse(dbcString); Assert.AreEqual(1, dbc.Messages.Count()); - Assert.AreEqual("3", dbc.Messages.First().CustomProperties.Values.First().EnumCustomProperty.Value); + Assert.AreEqual("3", dbc.Messages.First().Value.CustomProperties.Values.First().EnumCustomProperty.Value); } [Test] @@ -246,7 +246,7 @@ public void DefaultCustomPropertyEnumWithIntegerValuesByIndexIsParsed() var dbc = Parser.Parse(dbcString); Assert.AreEqual(1, dbc.Messages.Count()); - Assert.AreEqual("3", dbc.Messages.First().CustomProperties.Values.First().EnumCustomProperty.Value); + Assert.AreEqual("3", dbc.Messages.First().Value.CustomProperties.Values.First().EnumCustomProperty.Value); } } } \ No newline at end of file diff --git a/DbcParserLib.Tests/PropertiesLineParserTests.cs b/DbcParserLib.Tests/PropertiesLineParserTests.cs index 70ba944..38ebd95 100644 --- a/DbcParserLib.Tests/PropertiesLineParserTests.cs +++ b/DbcParserLib.Tests/PropertiesLineParserTests.cs @@ -69,7 +69,7 @@ public void IntDefinitionCustomPropertyNoBoundariesIsParsedTest() Assert.IsTrue(ParseLine(@"BA_ ""AttributeName"" BO_ 2394947585 100;", msgCycleTimeLineParser, builder, nextLineProvider)); var dbc = builder.Build(); - Assert.AreEqual(true, dbc.Messages.First().CustomProperties.TryGetValue("AttributeName", out var customProperty)); + Assert.AreEqual(true, dbc.Messages.First().Value.CustomProperties.TryGetValue("AttributeName", out var customProperty)); Assert.AreEqual(100, customProperty!.IntegerCustomProperty.Value); } @@ -97,7 +97,7 @@ public void HexDefinitionCustomPropertyNoBoundariesIsParsedTest() Assert.IsTrue(ParseLine(@"BA_DEF_DEF_ ""AttributeName"" 150;", msgCycleTimeLineParser, builder, nextLineProvider)); var dbc = builder.Build(); - Assert.AreEqual(true, dbc.Messages.First().CustomProperties.TryGetValue("AttributeName", out var customProperty)); + Assert.AreEqual(true, dbc.Messages.First().Value.CustomProperties.TryGetValue("AttributeName", out var customProperty)); Assert.AreEqual(150, customProperty!.HexCustomProperty.Value); } @@ -125,7 +125,7 @@ public void FloatDefinitionCustomPropertyNoBoundariesIsParsedTest() Assert.IsTrue(ParseLine(@"BA_DEF_DEF_ ""AttributeName"" 150.0;", msgCycleTimeLineParser, builder, nextLineProvider)); var dbc = builder.Build(); - Assert.AreEqual(true, dbc.Messages.First().CustomProperties.TryGetValue("AttributeName", out var customProperty)); + Assert.AreEqual(true, dbc.Messages.First().Value.CustomProperties.TryGetValue("AttributeName", out var customProperty)); Assert.AreEqual(150, customProperty!.FloatCustomProperty.Value); } @@ -233,8 +233,8 @@ public void MsgCycleTimePropertyIsParsedTest() Assert.IsTrue(ParseLine(@"BA_ ""GenMsgCycleTime"" BO_ 2394947585 100;", msgCycleTimeLineParser, builder, nextLineProvider)); var dbc = builder.Build(); - Assert.AreEqual(true, dbc.Messages.First().CycleTime(out var cycleTime)); - Assert.AreEqual(100, cycleTime); + Assert.IsNotNull(dbc.Messages.First().Value.CycleTime); + Assert.AreEqual(100, dbc.Messages.First().Value.CycleTime); } [Test] @@ -253,9 +253,8 @@ public void SigInitialValueIntegerPropertyIsParsedTest() Assert.IsTrue(ParseLine(@"BA_ ""GenSigStartValue"" SG_ 2394947585 sig_name 40;", sigInitialValueLineParser, builder, nextLineProvider)); var dbc = builder.Build(); - Assert.AreEqual(true, dbc.Messages.First().Signals.First().InitialValue(out var initialValue)); - Assert.AreEqual(40, dbc.Messages.First().Signals.First().InitialValue); - Assert.AreEqual(40, initialValue); + Assert.NotNull(dbc.Messages.First().Value.Signals.First().Value.InitialValue); + Assert.AreEqual(40, dbc.Messages.First().Value.Signals.First().Value.InitialValue); } [Test] @@ -274,9 +273,8 @@ public void SigInitialValueHexPropertyIsParsedTest() Assert.IsTrue(ParseLine(@"BA_ ""GenSigStartValue"" SG_ 2394947585 sig_name 40;", sigInitialValueLineParser, builder, nextLineProvider)); var dbc = builder.Build(); - Assert.AreEqual(true, dbc.Messages.First().Signals.First().InitialValue(out var initialValue)); - Assert.AreEqual(40, dbc.Messages.First().Signals.First().InitialValue); - Assert.AreEqual(40, initialValue); + Assert.NotNull(dbc.Messages.First().Value.Signals.First().Value.InitialValue); + Assert.AreEqual(40, dbc.Messages.First().Value.Signals.First().Value.InitialValue); } [Test] diff --git a/DbcParserLib.Tests/PropertiesParsingFailuresTests.cs b/DbcParserLib.Tests/PropertiesParsingFailuresTests.cs index 3fd75a1..95bfb13 100644 --- a/DbcParserLib.Tests/PropertiesParsingFailuresTests.cs +++ b/DbcParserLib.Tests/PropertiesParsingFailuresTests.cs @@ -339,7 +339,7 @@ public void DefaultCustomPropertyEnumWithIntegerValuesIsParsed() var dbc = Parser.Parse(dbcString); Assert.AreEqual(1, dbc.Messages.Count()); - Assert.AreEqual("3", dbc.Messages.First().CustomProperties.Values.First().EnumCustomProperty.Value); + Assert.AreEqual("3", dbc.Messages.First().Value.CustomProperties.Values.First().EnumCustomProperty.Value); } [Test] @@ -353,7 +353,7 @@ public void DefaultCustomPropertyEnumWithIntegerValuesByIndexIsParsed() var dbc = Parser.Parse(dbcString); Assert.AreEqual(1, dbc.Messages.Count()); - Assert.AreEqual("3", dbc.Messages.First().CustomProperties.Values.First().EnumCustomProperty.Value); + Assert.AreEqual("3", dbc.Messages.First().Value.CustomProperties.Values.First().EnumCustomProperty.Value); } } } \ No newline at end of file diff --git a/DbcParserLib.Tests/SignalLineParserTests.cs b/DbcParserLib.Tests/SignalLineParserTests.cs index ea8e6d3..8bead50 100644 --- a/DbcParserLib.Tests/SignalLineParserTests.cs +++ b/DbcParserLib.Tests/SignalLineParserTests.cs @@ -75,7 +75,7 @@ public void FullLineIsParsed() Assert.AreEqual(0, signal.Offset); Assert.AreEqual(-10, signal.Minimum); Assert.AreEqual(35.6, signal.Maximum); - Assert.IsTrue(string.IsNullOrWhiteSpace(signal.Multiplexing)); + Assert.IsTrue(string.IsNullOrWhiteSpace(signal.multiplexing)); Assert.AreEqual("deg", signal.Unit); Assert.AreEqual("NEO", signal.Receiver.FirstOrDefault()); }); @@ -103,7 +103,7 @@ public void FullLineMultiplexedIsParsed() Assert.AreEqual(0, signal.Offset); Assert.AreEqual(-10, signal.Minimum); Assert.AreEqual(35.6, signal.Maximum); - Assert.AreEqual("m7", signal.Multiplexing); + Assert.AreEqual("m7", signal.multiplexing); Assert.AreEqual("deg", signal.Unit); Assert.AreEqual("NEO", signal.Receiver.FirstOrDefault()); }); @@ -131,7 +131,7 @@ public void FullLineMultipleReceiversIsParsed() Assert.AreEqual(0, signal.Offset); Assert.AreEqual(-10, signal.Minimum); Assert.AreEqual(35.6, signal.Maximum); - Assert.AreEqual("m7", signal.Multiplexing); + Assert.AreEqual("m7", signal.multiplexing); Assert.AreEqual("deg", signal.Unit); CollectionAssert.AreEqual(new[] { "NEO", "WHEEL", "TOP" }, signal.Receiver); @@ -160,7 +160,7 @@ public void FullLineMultipleReceiversWithSpacesIsParsed() Assert.AreEqual(0, signal.Offset); Assert.AreEqual(-10, signal.Minimum); Assert.AreEqual(35.6, signal.Maximum); - Assert.AreEqual("m7", signal.Multiplexing); + Assert.AreEqual("m7", signal.multiplexing); Assert.AreEqual("deg", signal.Unit); CollectionAssert.AreEqual(new[] { "NEO", "WHEEL", "TOP" }, signal.Receiver); @@ -185,7 +185,7 @@ public void ParseSignalWithDifferentColonSpaces() var dbc = Parser.Parse(dbcString); Assert.AreEqual(1, dbc.Messages.Count()); - Assert.AreEqual(3, dbc.Messages.SelectMany(m => m.Signals).Count()); + Assert.AreEqual(3, dbc.Messages.SelectMany(m => m.Value.Signals).Count()); } [TestCase("SG_ qGearboxOilMin : 0|16@1+ (0.1,0) [0|6553.5] \"l/min\" \"NATEC\"")] diff --git a/DbcParserLib/Dbc.cs b/DbcParserLib/Dbc.cs deleted file mode 100644 index a25473d..0000000 --- a/DbcParserLib/Dbc.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Collections.Generic; -using DbcParserLib.Model; -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("DbcParserLib.Tests")] -[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] -namespace DbcParserLib -{ - public class Dbc - { - public IEnumerable Nodes {get;} - public IEnumerable Messages {get;} - public IEnumerable EnvironmentVariables { get; } - - public Dbc(IEnumerable nodes, IEnumerable messages, IEnumerable environmentVariables) - { - Nodes = nodes; - Messages = messages; - EnvironmentVariables = environmentVariables; - } - } -} \ No newline at end of file diff --git a/DbcParserLib/DbcBuilder.cs b/DbcParserLib/DbcBuilder.cs index 93dd72e..e350a85 100644 --- a/DbcParserLib/DbcBuilder.cs +++ b/DbcParserLib/DbcBuilder.cs @@ -3,423 +3,506 @@ using DbcParserLib.Model; using DbcParserLib.Observers; -namespace DbcParserLib +namespace DbcParserLib; + +internal class ValuesTable { - internal class ValuesTable - { - public IReadOnlyDictionary ValueTableMap { get; set; } - } + public IReadOnlyDictionary ValueTableMap { get; set; } +} - internal class DbcBuilder : IDbcBuilder - { - private readonly IParseFailureObserver m_observer; - - private readonly ISet m_nodes = new HashSet(new NodeEqualityComparer()); - private readonly IDictionary m_messages = new Dictionary(); - private readonly IDictionary> m_signals = new Dictionary>(); - private readonly IDictionary m_environmentVariables = new Dictionary(); - - private readonly IDictionary m_namedTablesMap = new Dictionary(); - private readonly IDictionary> m_customProperties = new Dictionary>() { - {CustomPropertyObjectType.Node, new Dictionary()}, - {CustomPropertyObjectType.Message, new Dictionary()}, - {CustomPropertyObjectType.Signal, new Dictionary()}, +internal class DbcBuilder : IDbcBuilder +{ + private readonly IParseFailureObserver m_observer; + + private readonly ISet m_nodes = new HashSet(new NodeEqualityComparer()); + private readonly Dictionary m_messages = new Dictionary(); + private readonly IDictionary> m_signals = new Dictionary>(); + private readonly IDictionary m_environmentVariables = new Dictionary(); + + private readonly IDictionary m_namedTablesMap = new Dictionary(); + + private readonly IDictionary> m_customProperties = + new Dictionary>() + { + { CustomPropertyObjectType.Node, new Dictionary() }, + { CustomPropertyObjectType.Message, new Dictionary() }, + { CustomPropertyObjectType.Signal, new Dictionary() }, }; - private Message m_currentMessage; + private Message m_currentMessage; - public DbcBuilder(IParseFailureObserver observer) + public DbcBuilder(IParseFailureObserver observer) + { + m_observer = observer; + } + + public void AddNode(Node node) + { + if (m_nodes.Contains(node)) + { + m_observer.DuplicatedNode(node.Name); + } + else { - m_observer = observer; + m_nodes.Add(node); } + } - public void AddNode(Node node) + public void AddMessage(Message message) + { + if (m_messages.TryGetValue(message.ID, out var msg)) { - if(m_nodes.Contains(node)) - m_observer.DuplicatedNode(node.Name); - else - m_nodes.Add(node); + m_currentMessage = msg; + m_observer.DuplicatedMessage(message.ID); } + else + { + m_messages[message.ID] = message; + m_currentMessage = message; + m_signals[message.ID] = new Dictionary(); + } + } - public void AddMessage(Message message) + public void AddSignal(Signal signal) + { + if (m_currentMessage != null) { - if(m_messages.TryGetValue(message.ID, out var msg)) + signal.MessageID = m_currentMessage.ID; + if (m_signals[m_currentMessage.ID].TryGetValue(signal.Name, out _)) { - m_currentMessage = msg; - m_observer.DuplicatedMessage(message.ID); + m_observer.DuplicatedSignalInMessage(m_currentMessage.ID, signal.Name); } else { - m_messages[message.ID] = message; - m_currentMessage = message; - m_signals[message.ID] = new Dictionary(); + m_signals[m_currentMessage.ID][signal.Name] = signal; } } - - public void AddSignal(Signal signal) + else { - if (m_currentMessage != null) - { - signal.ID = m_currentMessage.ID; - if(m_signals[m_currentMessage.ID].TryGetValue(signal.Name, out _)) - m_observer.DuplicatedSignalInMessage(m_currentMessage.ID, signal.Name); - else - m_signals[m_currentMessage.ID][signal.Name] = signal; - } - else - m_observer.NoMessageFound(); + m_observer.NoMessageFound(); } + } - public void AddCustomProperty(CustomPropertyObjectType objectType, CustomPropertyDefinition customProperty) + public void AddCustomProperty(CustomPropertyObjectType objectType, CustomPropertyDefinition customProperty) + { + if (m_customProperties[objectType].TryGetValue(customProperty.Name, out _)) { - if(m_customProperties[objectType].TryGetValue(customProperty.Name, out _)) - m_observer.DuplicatedProperty(customProperty.Name); - else - m_customProperties[objectType][customProperty.Name] = customProperty; + m_observer.DuplicatedProperty(customProperty.Name); + } + else + { + m_customProperties[objectType][customProperty.Name] = customProperty; } + } - public void AddCustomPropertyDefaultValue(string propertyName, string value, bool isNumeric) + public void AddCustomPropertyDefaultValue(string propertyName, string value, bool isNumeric) + { + var found = false; + foreach (var objectType in m_customProperties.Keys) { - var found = false; - foreach(var objectType in m_customProperties.Keys) + if (m_customProperties[objectType].TryGetValue(propertyName, out var customProperty)) { - if (m_customProperties[objectType].TryGetValue(propertyName, out var customProperty)) - { - customProperty.SetCustomPropertyDefaultValue(value, isNumeric); - found = true; - } + customProperty.SetCustomPropertyDefaultValue(value, isNumeric); + found = true; } + } - if(!found) - m_observer.PropertyNameNotFound(propertyName); + if (!found) + { + m_observer.PropertyNameNotFound(propertyName); } + } - public void AddNodeCustomProperty(string propertyName, string nodeName, string value, bool isNumeric) + public void AddNodeCustomProperty(string propertyName, string nodeName, string value, bool isNumeric) + { + if (m_customProperties[CustomPropertyObjectType.Node].TryGetValue(propertyName, out var customProperty)) { - if(m_customProperties[CustomPropertyObjectType.Node].TryGetValue(propertyName, out var customProperty)) + var node = m_nodes.FirstOrDefault(n => n.Name.Equals(nodeName)); + if (node != null) { - var node = m_nodes.FirstOrDefault(n => n.Name.Equals(nodeName)); - if (node != null) + var property = new CustomProperty(customProperty); + if (!property.SetCustomPropertyValue(value, isNumeric)) { - var property = new CustomProperty(customProperty); - if(!property.SetCustomPropertyValue(value, isNumeric)) - return; - - if(node.CustomProperties.TryGetValue(propertyName, out _)) - m_observer.DuplicatedPropertyInNode(propertyName, node.Name); - else - node.CustomProperties[propertyName] = property; + return; + } + + if (node.customProperties.TryGetValue(propertyName, out _)) + { + m_observer.DuplicatedPropertyInNode(propertyName, node.Name); } else - m_observer.NodeNameNotFound(nodeName); + { + node.customProperties[propertyName] = property; + } } else - m_observer.PropertyNameNotFound(propertyName); + { + m_observer.NodeNameNotFound(nodeName); + } + } + else + { + m_observer.PropertyNameNotFound(propertyName); } + } - public void AddEnvironmentVariableCustomProperty(string propertyName, string variableName, string value, bool isNumeric) + public void AddEnvironmentVariableCustomProperty(string propertyName, string variableName, string value, bool isNumeric) + { + if (m_customProperties[CustomPropertyObjectType.Environment].TryGetValue(propertyName, out var customProperty)) { - if (m_customProperties[CustomPropertyObjectType.Environment].TryGetValue(propertyName, out var customProperty)) + if (m_environmentVariables.TryGetValue(variableName, out var envVariable)) { - if (m_environmentVariables.TryGetValue(variableName, out var envVariable)) + var property = new CustomProperty(customProperty); + if (!property.SetCustomPropertyValue(value, isNumeric)) { - var property = new CustomProperty(customProperty); - if(!property.SetCustomPropertyValue(value, isNumeric)) - return; - - if(envVariable.CustomProperties.TryGetValue(propertyName, out _)) - m_observer.DuplicatedPropertyInEnvironmentVariable(propertyName, envVariable.Name); - else - envVariable.CustomProperties[propertyName] = property; + return; + } + + if (envVariable.customProperties.TryGetValue(propertyName, out _)) + { + m_observer.DuplicatedPropertyInEnvironmentVariable(propertyName, envVariable.Name); } else - m_observer.EnvironmentVariableNameNotFound(variableName); + { + envVariable.customProperties[propertyName] = property; + } } else - m_observer.PropertyNameNotFound(propertyName); + { + m_observer.EnvironmentVariableNameNotFound(variableName); + } } + else + { + m_observer.PropertyNameNotFound(propertyName); + } + } - public void AddMessageCustomProperty(string propertyName, uint messageId, string value, bool isNumeric) + public void AddMessageCustomProperty(string propertyName, uint messageId, string value, bool isNumeric) + { + if (m_customProperties[CustomPropertyObjectType.Message].TryGetValue(propertyName, out var customProperty)) { - if (m_customProperties[CustomPropertyObjectType.Message].TryGetValue(propertyName, out var customProperty)) + if (m_messages.TryGetValue(messageId, out var message)) { - if (m_messages.TryGetValue(messageId, out var message)) + var property = new CustomProperty(customProperty); + if (!property.SetCustomPropertyValue(value, isNumeric)) + { + return; + } + + if (message.customProperties.TryGetValue(propertyName, out _)) { - var property = new CustomProperty(customProperty); - if(!property.SetCustomPropertyValue(value, isNumeric)) - return; - - if(message.CustomProperties.TryGetValue(propertyName, out _)) - m_observer.DuplicatedPropertyInMessage(propertyName, message.ID); - else - message.CustomProperties[propertyName] = property; + m_observer.DuplicatedPropertyInMessage(propertyName, message.ID); } else - m_observer.MessageIdNotFound(messageId); + { + message.customProperties[propertyName] = property; + } } else - m_observer.PropertyNameNotFound(propertyName); + { + m_observer.MessageIdNotFound(messageId); + } + } + else + { + m_observer.PropertyNameNotFound(propertyName); } + } - public void AddSignalCustomProperty(string propertyName, uint messageId, string signalName, string value, bool isNumeric) + public void AddSignalCustomProperty(string propertyName, uint messageId, string signalName, string value, bool isNumeric) + { + if (m_customProperties[CustomPropertyObjectType.Signal].TryGetValue(propertyName, out var customProperty)) { - if (m_customProperties[CustomPropertyObjectType.Signal].TryGetValue(propertyName, out var customProperty)) + if (TryGetValueMessageSignal(messageId, signalName, out var signal)) { - if (TryGetValueMessageSignal(messageId, signalName, out var signal)) + var property = new CustomProperty(customProperty); + if (!property.SetCustomPropertyValue(value, isNumeric)) + { + return; + } + + if (signal.customProperties.TryGetValue(propertyName, out _)) { - var property = new CustomProperty(customProperty); - if(!property.SetCustomPropertyValue(value, isNumeric)) - return; - - if(signal.CustomProperties.TryGetValue(propertyName, out _)) - m_observer.DuplicatedPropertyInSignal(propertyName, signal.Name); - else - signal.CustomProperties[propertyName] = property; + m_observer.DuplicatedPropertyInSignal(propertyName, signal.Name); } else - m_observer.SignalNameNotFound(messageId, signalName); + { + signal.customProperties[propertyName] = property; + } } else - m_observer.PropertyNameNotFound(propertyName); + { + m_observer.SignalNameNotFound(messageId, signalName); + } } - - public void AddSignalComment(uint messageId, string signalName, string comment) + else { - if (TryGetValueMessageSignal(messageId, signalName, out var signal)) - signal.Comment = comment; - else - m_observer.SignalNameNotFound(messageId, signalName); + m_observer.PropertyNameNotFound(propertyName); } + } - public void AddSignalValueType(uint messageId, string signalName, DbcValueType valueType) + public void AddSignalComment(uint messageId, string signalName, string comment) + { + if (TryGetValueMessageSignal(messageId, signalName, out var signal)) { - if (TryGetValueMessageSignal(messageId, signalName, out var signal)) - { - signal.ValueType = valueType; - } - else - m_observer.SignalNameNotFound(messageId, signalName); + signal.Comment = comment; + } + else + { + m_observer.SignalNameNotFound(messageId, signalName); } + } - public void AddNodeComment(string nodeName, string comment) + public void AddSignalValueType(uint messageId, string signalName, DbcValueType valueType) + { + if (TryGetValueMessageSignal(messageId, signalName, out var signal)) { - var node = m_nodes.FirstOrDefault(n => n.Name.Equals(nodeName)); - if (node != null) - node.Comment = comment; - else - m_observer.NodeNameNotFound(nodeName); + signal.ValueType = valueType; } + else + { + m_observer.SignalNameNotFound(messageId, signalName); + } + } - public void AddMessageComment(uint messageId, string comment) + public void AddNodeComment(string nodeName, string comment) + { + var node = m_nodes.FirstOrDefault(n => n.Name.Equals(nodeName)); + if (node != null) { - if (m_messages.TryGetValue(messageId, out var message)) - message.Comment = comment; - else - m_observer.MessageIdNotFound(messageId); + node.Comment = comment; } + else + { + m_observer.NodeNameNotFound(nodeName); + } + } - public void AddEnvironmentVariableComment(string variableName, string comment) + public void AddMessageComment(uint messageId, string comment) + { + if (m_messages.TryGetValue(messageId, out var message)) { - if (m_environmentVariables.TryGetValue(variableName, out var envVariable)) - envVariable.Comment = comment; - else - m_observer.EnvironmentVariableNameNotFound(variableName); + message.Comment = comment; } + else + { + m_observer.MessageIdNotFound(messageId); + } + } - public void AddEnvironmentVariable(string variableName, EnvironmentVariable environmentVariable) + public void AddEnvironmentVariableComment(string variableName, string comment) + { + if (m_environmentVariables.TryGetValue(variableName, out var envVariable)) { - if(m_environmentVariables.TryGetValue(variableName, out _)) - m_observer.DuplicatedEnvironmentVariableName(variableName); - else - m_environmentVariables[variableName] = environmentVariable; + envVariable.Comment = comment; + } + else + { + m_observer.EnvironmentVariableNameNotFound(variableName); } + } - public void AddEnvironmentDataVariable(string variableName, uint dataSize) + public void AddEnvironmentVariable(string variableName, EnvironmentVariable environmentVariable) + { + if (m_environmentVariables.TryGetValue(variableName, out _)) { - if (m_environmentVariables.TryGetValue(variableName, out var envVariable)) - { - envVariable.Type = EnvDataType.Data; - envVariable.DataEnvironmentVariable = new DataEnvironmentVariable() - { - Length = dataSize - }; - } - else - m_observer.EnvironmentVariableNameNotFound(variableName); + m_observer.DuplicatedEnvironmentVariableName(variableName); + } + else + { + m_environmentVariables[variableName] = environmentVariable; } + } - public void AddNodeEnvironmentVariable(string nodeName, string variableName) + public void AddEnvironmentDataVariable(string variableName, uint dataSize) + { + if (m_environmentVariables.TryGetValue(variableName, out var envVariable)) { - var node = m_nodes.FirstOrDefault(n => n.Name.Equals(nodeName)); - if (node != null) + envVariable.Type = EnvDataType.Data; + envVariable.DataEnvironmentVariable = new DataEnvironmentVariable() { - if(node.EnvironmentVariables.TryGetValue(variableName, out _)) - m_observer.DuplicatedEnvironmentVariableInNode(variableName, node.Name); - else - node.EnvironmentVariables[variableName] = m_environmentVariables[variableName]; - } - else - m_observer.NodeNameNotFound(nodeName); + Length = dataSize + }; + } + else + { + m_observer.EnvironmentVariableNameNotFound(variableName); } + } - public void AddNamedValueTable(string name, IReadOnlyDictionary dictValues) + public void AddNodeEnvironmentVariable(string nodeName, string variableName) + { + var node = m_nodes.FirstOrDefault(n => n.Name.Equals(nodeName)); + if (node != null) { - if(m_namedTablesMap.TryGetValue(name, out _)) - m_observer.DuplicatedValueTableName(name); + if (node.environmentVariables.TryGetValue(variableName, out _)) + { + m_observer.DuplicatedEnvironmentVariableInNode(variableName, node.Name); + } else { - m_namedTablesMap[name] = new ValuesTable() - { - ValueTableMap = dictValues, - }; + node.environmentVariables[variableName] = m_environmentVariables[variableName]; } } + else + { + m_observer.NodeNameNotFound(nodeName); + } + } - public void LinkTableValuesToSignal(uint messageId, string signalName, IReadOnlyDictionary dictValues) + public void AddNamedValueTable(string name, IReadOnlyDictionary dictValues) + { + if (m_namedTablesMap.TryGetValue(name, out _)) { - if (TryGetValueMessageSignal(messageId, signalName, out var signal)) + m_observer.DuplicatedValueTableName(name); + } + else + { + m_namedTablesMap[name] = new ValuesTable() { - signal.ValueTableMap = dictValues; - } - else - m_observer.SignalNameNotFound(messageId, signalName); + ValueTableMap = dictValues, + }; } + } - public void LinkTableValuesToEnvironmentVariable(string variableName, IReadOnlyDictionary dictValues) + public void LinkTableValuesToSignal(uint messageId, string signalName, IReadOnlyDictionary dictValues) + { + if (TryGetValueMessageSignal(messageId, signalName, out var signal)) { - if (m_environmentVariables.TryGetValue(variableName, out var envVariable)) - { - envVariable.ValueTableMap = dictValues; - } - else - m_observer.EnvironmentVariableNameNotFound(variableName); + signal.ValueTableMap = dictValues; + } + else + { + m_observer.SignalNameNotFound(messageId, signalName); } + } - public void LinkNamedTableToSignal(uint messageId, string signalName, string tableName) + public void LinkTableValuesToEnvironmentVariable(string variableName, IReadOnlyDictionary dictValues) + { + if (m_environmentVariables.TryGetValue(variableName, out var envVariable)) { - if (m_namedTablesMap.TryGetValue(tableName, out var valuesTable)) - { - LinkTableValuesToSignal(messageId, signalName, valuesTable.ValueTableMap); - } - else - m_observer.TableMapNameNotFound(tableName); + envVariable.ValueTableMap = dictValues; + } + else + { + m_observer.EnvironmentVariableNameNotFound(variableName); } + } - private bool TryGetValueMessageSignal(uint messageId, string signalName, out Signal signal) + public void LinkNamedTableToSignal(uint messageId, string signalName, string tableName) + { + if (m_namedTablesMap.TryGetValue(tableName, out var valuesTable)) { - if (m_signals.TryGetValue(messageId, out var signals) && signals.TryGetValue(signalName, out signal)) - { - return true; - } + LinkTableValuesToSignal(messageId, signalName, valuesTable.ValueTableMap); + } + else + { + m_observer.TableMapNameNotFound(tableName); + } + } - signal = null; - return false; + private bool TryGetValueMessageSignal(uint messageId, string signalName, out Signal signal) + { + if (m_signals.TryGetValue(messageId, out var signals) && signals.TryGetValue(signalName, out signal)) + { + return true; } - private void FillNodesNotSetCustomPropertyWithDefault() + signal = null; + return false; + } + + private void FillNodesNotSetCustomPropertyWithDefault() + { + var nodeCustomProperties = m_customProperties[CustomPropertyObjectType.Node]; + foreach (var customProperty in nodeCustomProperties) { - var nodeCustomProperties = m_customProperties[CustomPropertyObjectType.Node]; - foreach (var customProperty in nodeCustomProperties) + foreach (var node in m_nodes) { - foreach (var node in m_nodes) + if (!node.customProperties.TryGetValue(customProperty.Key, out _)) { - if (!node.CustomProperties.TryGetValue(customProperty.Key, out _)) - { - node.CustomProperties[customProperty.Key] = new CustomProperty(customProperty.Value); - node.CustomProperties[customProperty.Key].SetCustomPropertyValueFromDefault(); - } + node.customProperties[customProperty.Key] = new CustomProperty(customProperty.Value); + node.customProperties[customProperty.Key].SetCustomPropertyValueFromDefault(); } } } + } - private void FillMessagesNotSetCustomPropertyWithDefault() + private void FillMessagesNotSetCustomPropertyWithDefault() + { + var messageCustomProperties = m_customProperties[CustomPropertyObjectType.Message]; + foreach (var customProperty in messageCustomProperties) { - var messageCustomProperties = m_customProperties[CustomPropertyObjectType.Message]; - foreach (var customProperty in messageCustomProperties) + foreach (var message in m_messages.Values) { - foreach (var message in m_messages.Values) + FillSignalsNotSetCustomPropertyWithDefault(message.ID); + if (!message.customProperties.TryGetValue(customProperty.Key, out _)) { - FillSignalsNotSetCustomPropertyWithDefault(message.ID); - if (!message.CustomProperties.TryGetValue(customProperty.Key, out _)) - { - message.CustomProperties[customProperty.Key] = new CustomProperty(customProperty.Value); - message.CustomProperties[customProperty.Key].SetCustomPropertyValueFromDefault(); - } + message.customProperties[customProperty.Key] = new CustomProperty(customProperty.Value); + message.customProperties[customProperty.Key].SetCustomPropertyValueFromDefault(); } } } + } - private void FillSignalsNotSetCustomPropertyWithDefault(uint messageId) + private void FillSignalsNotSetCustomPropertyWithDefault(uint messageId) + { + var signalCustomProperties = m_customProperties[CustomPropertyObjectType.Signal]; + foreach (var customProperty in signalCustomProperties) { - var signalCustomProperties = m_customProperties[CustomPropertyObjectType.Signal]; - foreach (var customProperty in signalCustomProperties) + foreach (var signal in m_signals[messageId].Values) { - foreach (var signal in m_signals[messageId].Values) + if (!signal.customProperties.TryGetValue(customProperty.Key, out _)) { - if (!signal.CustomProperties.TryGetValue(customProperty.Key, out _)) - { - signal.CustomProperties[customProperty.Key] = new CustomProperty(customProperty.Value); - signal.CustomProperties[customProperty.Key].SetCustomPropertyValueFromDefault(); - } + signal.customProperties[customProperty.Key] = new CustomProperty(customProperty.Value); + signal.customProperties[customProperty.Key].SetCustomPropertyValueFromDefault(); } } } + } - public Dbc Build() - { - FillNodesNotSetCustomPropertyWithDefault(); - FillMessagesNotSetCustomPropertyWithDefault(); + public Dbc Build() + { + FillNodesNotSetCustomPropertyWithDefault(); + FillMessagesNotSetCustomPropertyWithDefault(); - foreach (var message in m_messages) + foreach (var message in m_messages) + { + if (m_signals.TryGetValue(message.Key, out var signals) && signals != null) { - message.Value.Signals.Clear(); - if(m_signals.TryGetValue(message.Key, out var signals) && signals != null) - message.Value.Signals.AddRange(signals.Values); - - message.Value.AdjustExtendedId(); + message.Value.signals = signals; } - - //TODO: uncomment once Immutable classes are used - //var nodes = new List(); - //foreach (var node in m_nodes) - //{ - // nodes.Add(node.CreateNode()); - //} - - //var messages = new List(); - //foreach (var message in m_messages.Values) - //{ - // messages.Add(message.CreateMessage()); - //} - - //var environmentVariables = new List(); - //foreach (var environmentVariable in m_environmentVariables.Values) - //{ - // environmentVariables.Add(environmentVariable.CreateEnvironmentVariable()); - //} - //return new Dbc(nodes, messages, environmentVariables); - - return new Dbc(m_nodes.ToArray(), m_messages.Values.ToArray(), m_environmentVariables.Values.ToArray()); } + + return new Dbc(m_nodes.ToArray(), m_messages, m_environmentVariables.Values.ToArray()); } +} internal class NodeEqualityComparer : IEqualityComparer +{ + public bool Equals(Node b1, Node b2) { - public bool Equals(Node b1, Node b2) - { - if (b2 == null && b1 == null) - return true; - else if (b1 == null || b2 == null) - return false; - else if (b1.Name == b2.Name) - return true; - else - return false; + if (b2 == null && b1 == null) + { + return true; } - - public int GetHashCode(Node bx) + else if (b1 == null || b2 == null) + { + return false; + } + else if (b1.Name == b2.Name) { - return bx.Name.GetHashCode(); + return true; } + else + { + return false; + } + } + + public int GetHashCode(Node bx) + { + return bx.Name.GetHashCode(); } } \ No newline at end of file diff --git a/DbcParserLib/DbcParserLib.csproj b/DbcParserLib/DbcParserLib.csproj index adda8ac..89fe829 100644 --- a/DbcParserLib/DbcParserLib.csproj +++ b/DbcParserLib/DbcParserLib.csproj @@ -2,7 +2,8 @@ Library - netstandard2.0;net461;net5.0;net6.0 + netstandard2.0;net462;net8.0 + 12.0 Emanuel Feru DbcParserLib is a .NET dbc file parser library for CAN bus network signals. This library can also be used to pack and unpack CAN signals. MIT diff --git a/DbcParserLib/ExtensionsAndHelpers.cs b/DbcParserLib/ExtensionsAndHelpers.cs index 459b8f4..3c82134 100644 --- a/DbcParserLib/ExtensionsAndHelpers.cs +++ b/DbcParserLib/ExtensionsAndHelpers.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using System.Collections.Generic; using DbcParserLib.Model; @@ -32,90 +31,25 @@ internal static ulong BitMask(this Signal signal) return (ulong.MaxValue >> (64 - signal.Length)); } - private const string MultiplexorLabel = "M"; - private const string MultiplexedLabel = "m"; - - public static MultiplexingInfo MultiplexingInfo(this Signal signal) - { - if(string.IsNullOrWhiteSpace(signal.Multiplexing)) - return new MultiplexingInfo(MultiplexingRole.None); - - if(signal.Multiplexing.Equals(MultiplexorLabel)) - return new MultiplexingInfo(MultiplexingRole.Multiplexor); - - if(signal.Multiplexing.StartsWith(MultiplexedLabel)) - { - var substringLength = signal.Multiplexing.Length - (signal.Multiplexing.EndsWith(MultiplexorLabel) ? 2 : 1); - - if(int.TryParse(signal.Multiplexing.Substring(1, substringLength), out var group)) - return new MultiplexingInfo(MultiplexingRole.Multiplexed, group); - } - - return new MultiplexingInfo(MultiplexingRole.Unknown); - } - - public static bool IsMultiplexed(this Message message) - { - return message.Signals.Any(s => s.MultiplexingInfo().Role == MultiplexingRole.Multiplexor); - } - - internal static void AdjustExtendedId(this Message message) - { - // For extended ID bit 31 is always 1 - if(message.ID >= 0x80000000) - { - message.IsExtID = true; - message.ID -= 0x80000000; - } - } - internal static bool TryParseToDict(this string records, out IReadOnlyDictionary dict) { return StringToDictionaryParser.ParseString(records, out dict); } - - public static bool CycleTime(this Message message, out int cycleTime) + + internal static bool AreDoublesEqual(double a, double b, double epsilon = 1e-10) { - cycleTime = 0; - - if (message.CustomProperties.TryGetValue("GenMsgCycleTime", out var property)) - { - cycleTime = property.IntegerCustomProperty.Value; - return true; - } - else - return false; + return Math.Abs(a - b) < epsilon; } - - internal static bool InitialValue(this Signal signal, out double initialValue) + + internal static bool IsDoubleZero(double a, double epsilon = 1e-10) { - initialValue = 0; - - if (signal.CustomProperties.TryGetValue("GenSigStartValue", out var property)) - { - double value = 0; - switch (property.CustomPropertyDefinition.DataType) - { - case CustomPropertyDataType.Float: - value = property.FloatCustomProperty.Value; - break; - case CustomPropertyDataType.Hex: - value = property.HexCustomProperty.Value; - break; - case CustomPropertyDataType.Integer: - value = property.IntegerCustomProperty.Value; - break; - default: - return false; - } - - initialValue = value * signal.Factor + signal.Offset; - return true; - } - else - return false; + return Math.Abs(a) < epsilon; + } + + public static bool IsWholeNumber(double value) + { + return IsDoubleZero(value % 1); } - } internal class StringToDictionaryParser diff --git a/DbcParserLib/Model/CustomProperty.cs b/DbcParserLib/Model/CustomProperty.cs index c982a11..2193f2a 100644 --- a/DbcParserLib/Model/CustomProperty.cs +++ b/DbcParserLib/Model/CustomProperty.cs @@ -1,114 +1,126 @@ -namespace DbcParserLib.Model +namespace DbcParserLib.Model; + +public class CustomProperty { - public class CustomProperty + public CustomPropertyDefinition CustomPropertyDefinition { get; } + public CustomPropertyValue IntegerCustomProperty { get; private set; } + public CustomPropertyValue HexCustomProperty { get; private set; } + public CustomPropertyValue FloatCustomProperty { get; private set; } + public CustomPropertyValue StringCustomProperty { get; internal set; } + public CustomPropertyValue EnumCustomProperty { get; internal set; } + + public CustomProperty(CustomPropertyDefinition customPropertyDefinition) { - public readonly CustomPropertyDefinition CustomPropertyDefinition; - public CustomPropertyValue IntegerCustomProperty { get; set; } - public CustomPropertyValue HexCustomProperty { get; set; } - public CustomPropertyValue FloatCustomProperty { get; set; } - public CustomPropertyValue StringCustomProperty { get; set; } - public CustomPropertyValue EnumCustomProperty { get; set; } + CustomPropertyDefinition = customPropertyDefinition; + } - public CustomProperty(CustomPropertyDefinition customPropertyDefinition) + public bool SetCustomPropertyValue(string value, bool isNumeric) + { + switch (CustomPropertyDefinition.DataType) { - CustomPropertyDefinition = customPropertyDefinition; - } + case CustomPropertyDataType.Integer: + if (!CustomPropertyDefinition.TryGetIntegerValue(value, isNumeric, out var integerValue)) + { + return false; + } - public bool SetCustomPropertyValue(string value, bool isNumeric) - { - switch (CustomPropertyDefinition.DataType) - { - case CustomPropertyDataType.Integer: - if(!CustomPropertyDefinition.TryGetIntegerValue(value, isNumeric, out var integerValue)) - return false; + IntegerCustomProperty = new CustomPropertyValue() + { + Value = integerValue + }; + break; - IntegerCustomProperty = new CustomPropertyValue() - { - Value = integerValue - }; - break; + case CustomPropertyDataType.Hex: + if (!CustomPropertyDefinition.TryGetHexValue(value, isNumeric, out var hexValue)) + { + return false; + } - case CustomPropertyDataType.Hex: - if(!CustomPropertyDefinition.TryGetHexValue(value, isNumeric, out var hexValue)) - return false; + HexCustomProperty = new CustomPropertyValue() + { + Value = hexValue + }; + break; - HexCustomProperty = new CustomPropertyValue() - { - Value = hexValue - }; - break; + case CustomPropertyDataType.Float: + if (!CustomPropertyDefinition.TryGetFloatValue(value, isNumeric, out var floatValue)) + { + return false; + } - case CustomPropertyDataType.Float: - if(!CustomPropertyDefinition.TryGetFloatValue(value, isNumeric, out var floatValue)) - return false; - FloatCustomProperty = new CustomPropertyValue() - { - Value = floatValue - }; - break; + FloatCustomProperty = new CustomPropertyValue() + { + Value = floatValue + }; + break; - case CustomPropertyDataType.String: - if(!CustomPropertyDefinition.IsString(isNumeric)) - return false; - StringCustomProperty = new CustomPropertyValue() - { - Value = value - }; - break; + case CustomPropertyDataType.String: + if (!CustomPropertyDefinition.IsString(isNumeric)) + { + return false; + } - case CustomPropertyDataType.Enum: - if(!CustomPropertyDefinition.TryGetEnumValue(value, isNumeric, out var enumValue)) - return false; + StringCustomProperty = new CustomPropertyValue() + { + Value = value + }; + break; - EnumCustomProperty = new CustomPropertyValue() - { - Value = enumValue - }; - break; - } - return true; - } + case CustomPropertyDataType.Enum: + if (!CustomPropertyDefinition.TryGetEnumValue(value, isNumeric, out var enumValue)) + { + return false; + } - public void SetCustomPropertyValueFromDefault() - { - switch (CustomPropertyDefinition.DataType) - { - case CustomPropertyDataType.Integer: - IntegerCustomProperty = new CustomPropertyValue() - { - Value = CustomPropertyDefinition.IntegerCustomProperty.Default - }; - break; - case CustomPropertyDataType.Hex: - HexCustomProperty = new CustomPropertyValue() - { - Value = CustomPropertyDefinition.HexCustomProperty.Default - }; - break; - case CustomPropertyDataType.Float: - FloatCustomProperty = new CustomPropertyValue() - { - Value = CustomPropertyDefinition.FloatCustomProperty.Default - }; - break; - case CustomPropertyDataType.String: - StringCustomProperty = new CustomPropertyValue() - { - Value = CustomPropertyDefinition.StringCustomProperty.Default - }; - break; - case CustomPropertyDataType.Enum: - EnumCustomProperty = new CustomPropertyValue() - { - Value = CustomPropertyDefinition.EnumCustomProperty.Default - }; - break; - } + EnumCustomProperty = new CustomPropertyValue() + { + Value = enumValue + }; + break; } + + return true; } - public class CustomPropertyValue + public void SetCustomPropertyValueFromDefault() { - public T Value { get; set; } + switch (CustomPropertyDefinition.DataType) + { + case CustomPropertyDataType.Integer: + IntegerCustomProperty = new CustomPropertyValue() + { + Value = CustomPropertyDefinition.IntegerCustomProperty.Default + }; + break; + case CustomPropertyDataType.Hex: + HexCustomProperty = new CustomPropertyValue() + { + Value = CustomPropertyDefinition.HexCustomProperty.Default + }; + break; + case CustomPropertyDataType.Float: + FloatCustomProperty = new CustomPropertyValue() + { + Value = CustomPropertyDefinition.FloatCustomProperty.Default + }; + break; + case CustomPropertyDataType.String: + StringCustomProperty = new CustomPropertyValue() + { + Value = CustomPropertyDefinition.StringCustomProperty.Default + }; + break; + case CustomPropertyDataType.Enum: + EnumCustomProperty = new CustomPropertyValue() + { + Value = CustomPropertyDefinition.EnumCustomProperty.Default + }; + break; + } } } + +public class CustomPropertyValue +{ + public T Value { get; internal set; } +} \ No newline at end of file diff --git a/DbcParserLib/Model/CustomPropertyDefinition.cs b/DbcParserLib/Model/CustomPropertyDefinition.cs index 5cac531..65b8367 100644 --- a/DbcParserLib/Model/CustomPropertyDefinition.cs +++ b/DbcParserLib/Model/CustomPropertyDefinition.cs @@ -2,240 +2,269 @@ using System.Linq; using DbcParserLib.Observers; -namespace DbcParserLib.Model +namespace DbcParserLib.Model; + +public class CustomPropertyDefinition { - public class CustomPropertyDefinition + private readonly IParseFailureObserver observer; + public string Name { get; internal set; } + public CustomPropertyDataType DataType { get; internal set; } + public NumericCustomPropertyDefinition IntegerCustomProperty { get; internal set; } + public NumericCustomPropertyDefinition HexCustomProperty { get; internal set; } + public NumericCustomPropertyDefinition FloatCustomProperty { get; internal set; } + public StringCustomPropertyDefinition StringCustomProperty { get; internal set; } + public EnumCustomPropertyDefinition EnumCustomProperty { get; internal set; } + + public CustomPropertyDefinition(IParseFailureObserver observer) { - private readonly IParseFailureObserver m_observer; - public string Name { get; set; } - public CustomPropertyDataType DataType { get; set; } - public NumericCustomPropertyDefinition IntegerCustomProperty { get; set; } - public NumericCustomPropertyDefinition HexCustomProperty { get; set; } - public NumericCustomPropertyDefinition FloatCustomProperty { get; set; } - public StringCustomPropertyDefinition StringCustomProperty { get; set; } - public EnumCustomPropertyDefinition EnumCustomProperty { get; set; } + this.observer = observer; + } - public CustomPropertyDefinition(IParseFailureObserver observer) + public void SetCustomPropertyDefaultValue(string value, bool isNumeric) + { + switch (DataType) { - m_observer = observer; + case CustomPropertyDataType.Integer: + if (!TryGetIntegerValue(value, isNumeric, out var integerValue)) + { + return; + } + + IntegerCustomProperty.Default = integerValue; + break; + + case CustomPropertyDataType.Hex: + if (!TryGetHexValue(value, isNumeric, out var hexValue)) + { + return; + } + + HexCustomProperty.Default = hexValue; + break; + + case CustomPropertyDataType.Float: + if (!TryGetFloatValue(value, isNumeric, out var floatValue)) + { + return; + } + + FloatCustomProperty.Default = floatValue; + break; + + case CustomPropertyDataType.String: + if (!IsString(isNumeric)) + { + return; + } + + StringCustomProperty.Default = value; + break; + + case CustomPropertyDataType.Enum: + if (!TryGetEnumValue(value, isNumeric, out var enumValue)) + { + return; + } + + EnumCustomProperty.Default = enumValue; + break; } + } - public void SetCustomPropertyDefaultValue(string value, bool isNumeric) + internal bool TryGetIntegerValue(string value, bool isNumeric, out int integerValue) + { + integerValue = 0; + if (!isNumeric) { - switch (DataType) - { - case CustomPropertyDataType.Integer: - if(!TryGetIntegerValue(value, isNumeric, out var integerValue)) - return; - IntegerCustomProperty.Default = integerValue; - break; - - case CustomPropertyDataType.Hex: - if(!TryGetHexValue(value, isNumeric, out var hexValue)) - return; - HexCustomProperty.Default = hexValue; - break; - - case CustomPropertyDataType.Float: - if(!TryGetFloatValue(value, isNumeric, out var floatValue)) - return; - FloatCustomProperty.Default = floatValue; - break; - - case CustomPropertyDataType.String: - if(!IsString(isNumeric)) - return; - StringCustomProperty.Default = value; - break; - - case CustomPropertyDataType.Enum: - if(!TryGetEnumValue(value, isNumeric, out var enumValue)) - return; - EnumCustomProperty.Default = enumValue; - break; - } + observer.PropertySyntaxError(); + return false; } - internal bool TryGetIntegerValue(string value, bool isNumeric, out int integerValue) + if (!int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, + out integerValue)) { - integerValue = 0; - if (!isNumeric) - { - m_observer.PropertySyntaxError(); - return false; - } - - if (!int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, - out integerValue)) - { - m_observer.PropertySyntaxError(); - return false; - } - - if (CanAcceptAllValue(CustomPropertyDataType.Integer)) - return true; - - if (integerValue < IntegerCustomProperty.Minimum || integerValue > IntegerCustomProperty.Maximum) - { - m_observer.PropertyValueOutOfBound(Name, value); - return false; - } + observer.PropertySyntaxError(); + return false; + } + if (CanAcceptAllValue(CustomPropertyDataType.Integer)) + { return true; } - internal bool TryGetHexValue(string value, bool isNumeric, out int hexValue) + if (integerValue < IntegerCustomProperty.Minimum || integerValue > IntegerCustomProperty.Maximum) { - hexValue = 0; - if (!isNumeric) - { - m_observer.PropertySyntaxError(); - return false; - } + observer.PropertyValueOutOfBound(Name, value); + return false; + } - if (!int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, - out hexValue)) - { - m_observer.PropertySyntaxError(); - return false; - } + return true; + } - if (CanAcceptAllValue(CustomPropertyDataType.Hex)) - return true; + internal bool TryGetHexValue(string value, bool isNumeric, out int hexValue) + { + hexValue = 0; + if (!isNumeric) + { + observer.PropertySyntaxError(); + return false; + } - if (hexValue < HexCustomProperty.Minimum || hexValue > HexCustomProperty.Maximum) - { - m_observer.PropertyValueOutOfBound(Name, value); - return false; - } + if (!int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, + out hexValue)) + { + observer.PropertySyntaxError(); + return false; + } + if (CanAcceptAllValue(CustomPropertyDataType.Hex)) + { return true; } - internal bool TryGetFloatValue(string value, bool isNumeric, out float floatValue) + if (hexValue < HexCustomProperty.Minimum || hexValue > HexCustomProperty.Maximum) { - floatValue = 0; - if (!isNumeric) - { - m_observer.PropertySyntaxError(); - return false; - } - - if (!float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, - out floatValue)) - { - m_observer.PropertySyntaxError(); - return false; - } - - if (CanAcceptAllValue(CustomPropertyDataType.Float)) - return true; + observer.PropertyValueOutOfBound(Name, value); + return false; + } - if (floatValue < FloatCustomProperty.Minimum || floatValue > FloatCustomProperty.Maximum) - { - m_observer.PropertyValueOutOfBound(Name, value); - return false; - } + return true; + } - return true; + internal bool TryGetFloatValue(string value, bool isNumeric, out float floatValue) + { + floatValue = 0; + if (!isNumeric) + { + observer.PropertySyntaxError(); + return false; } - internal bool IsString(bool isNumeric) + if (!float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, + out floatValue)) { - if (isNumeric) - { - m_observer.PropertySyntaxError(); - return false; - } + observer.PropertySyntaxError(); + return false; + } + if (CanAcceptAllValue(CustomPropertyDataType.Float)) + { return true; } - internal bool TryGetEnumValue(string value, bool isNumeric, out string enumValue) + if (floatValue < FloatCustomProperty.Minimum || floatValue > FloatCustomProperty.Maximum) { - enumValue = null; - if (isNumeric) - { - if (!TryGetEnumValueFromIndex(value, out enumValue)) - { - return false; - } - } - else - { - if (!EnumCustomProperty.Values.Contains(value)) - { - m_observer.PropertyValueOutOfBound(Name, value); - return false; - } - enumValue = value; - } - return true; + observer.PropertyValueOutOfBound(Name, value); + return false; } - private bool TryGetEnumValueFromIndex(string value, out string enumValue) + return true; + } + + internal bool IsString(bool isNumeric) + { + if (isNumeric) { - enumValue = null; + observer.PropertySyntaxError(); + return false; + } - if (!int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var index)) - { - m_observer.PropertySyntaxError(); - return false; - } + return true; + } - if (index < 0 || index >= EnumCustomProperty.Values.Length) + internal bool TryGetEnumValue(string value, bool isNumeric, out string enumValue) + { + enumValue = null; + if (isNumeric) + { + if (!TryGetEnumValueFromIndex(value, out enumValue)) { - m_observer.PropertyValueOutOfIndex(Name, value); return false; } - - enumValue = EnumCustomProperty.Values[index]; - return true; } - - private bool CanAcceptAllValue(CustomPropertyDataType dataType) + else { - switch (dataType) + if (!EnumCustomProperty.Values.Contains(value)) { - case CustomPropertyDataType.Integer: - return IntegerCustomProperty.Minimum == 0 && IntegerCustomProperty.Maximum == 0; - case CustomPropertyDataType.Hex: - return HexCustomProperty.Minimum == 0 && HexCustomProperty.Maximum == 0; - case CustomPropertyDataType.Float: - return FloatCustomProperty.Minimum == 0 && FloatCustomProperty.Maximum == 0; - case CustomPropertyDataType.String: - case CustomPropertyDataType.Enum: - default: - return false; + observer.PropertyValueOutOfBound(Name, value); + return false; } + + enumValue = value; } - } - public class NumericCustomPropertyDefinition - { - public T Maximum { get; set; } - public T Minimum { get; set; } - public T Default { get; set; } + return true; } - public class StringCustomPropertyDefinition + private bool TryGetEnumValueFromIndex(string value, out string enumValue) { - public string Default { get; set; } - } + enumValue = null; - public class EnumCustomPropertyDefinition - { - public string Default { get; set; } - public string[] Values { get; set; } - } + if (!int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var index)) + { + observer.PropertySyntaxError(); + return false; + } - public enum CustomPropertyObjectType - { - Node, Message, Signal, Environment + if (index < 0 || index >= EnumCustomProperty.Values.Length) + { + observer.PropertyValueOutOfIndex(Name, value); + return false; + } + + enumValue = EnumCustomProperty.Values[index]; + return true; } - public enum CustomPropertyDataType + private bool CanAcceptAllValue(CustomPropertyDataType dataType) { - Integer, Hex, Float, String, Enum + switch (dataType) + { + case CustomPropertyDataType.Integer: + return IntegerCustomProperty.Minimum == 0 && IntegerCustomProperty.Maximum == 0; + case CustomPropertyDataType.Hex: + return HexCustomProperty.Minimum == 0 && HexCustomProperty.Maximum == 0; + case CustomPropertyDataType.Float: + return ExtensionsAndHelpers.AreDoublesEqual(FloatCustomProperty.Minimum, 0) && ExtensionsAndHelpers.AreDoublesEqual(FloatCustomProperty.Maximum, 0); + case CustomPropertyDataType.String: + case CustomPropertyDataType.Enum: + default: + return false; + } } } + +public class NumericCustomPropertyDefinition +{ + public T Maximum { get; internal set; } + public T Minimum { get; internal set; } + public T Default { get; internal set; } +} + +public class StringCustomPropertyDefinition +{ + public string Default { get; internal set; } +} + +public class EnumCustomPropertyDefinition +{ + public string Default { get; internal set; } + public string[] Values { get; internal set; } +} + +public enum CustomPropertyObjectType +{ + Node, + Message, + Signal, + Environment +} + +public enum CustomPropertyDataType +{ + Integer, + Hex, + Float, + String, + Enum +} \ No newline at end of file diff --git a/DbcParserLib/Model/Dbc.cs b/DbcParserLib/Model/Dbc.cs new file mode 100644 index 0000000..ea578eb --- /dev/null +++ b/DbcParserLib/Model/Dbc.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("DbcParserLib.Tests")] +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] +namespace DbcParserLib.Model; + +public class Dbc +{ + public IEnumerable Nodes { get; } + public IReadOnlyDictionary Messages { get; } + public IEnumerable EnvironmentVariables { get; } + + public Dbc(IEnumerable nodes, Dictionary messages, IEnumerable environmentVariables) + { + Nodes = nodes; + Messages = messages; + EnvironmentVariables = environmentVariables; + + FinishUp(); + } + + private void FinishUp() + { + foreach (var message in Messages.Values) + { + message.FinishUp(); + } + } +} \ No newline at end of file diff --git a/DbcParserLib/Model/EnvironmentVariable.cs b/DbcParserLib/Model/EnvironmentVariable.cs index 2dcd358..38bb311 100644 --- a/DbcParserLib/Model/EnvironmentVariable.cs +++ b/DbcParserLib/Model/EnvironmentVariable.cs @@ -1,75 +1,46 @@ using System.Collections.Generic; -namespace DbcParserLib.Model -{ - public class ImmutableEnvironmentVariable - { - public EnvDataType Type { get; } - public string Name { get; } - public string Unit { get; } - public string Comment { get; } - public EnvAccessibility Access { get; } - public IReadOnlyDictionary ValueTableMap { get; } - public IReadOnlyDictionary CustomProperties { get; } - public NumericEnvironmentVariable IntegerEnvironmentVariable { get; } - public NumericEnvironmentVariable FloatEnvironmentVariable { get; } - public DataEnvironmentVariable DataEnvironmentVariable { get; } - - internal ImmutableEnvironmentVariable(EnvironmentVariable environmentVariable) - { - //TODO: remove explicit cast (CustomProperty in Message class should be Dictionary instead IDictionary) - CustomProperties = (IReadOnlyDictionary)environmentVariable.CustomProperties; - Type = environmentVariable.Type; - Name = environmentVariable.Name; - Unit = environmentVariable.Unit; - Comment = environmentVariable.Comment; - Access = environmentVariable.Access; - ValueTableMap = environmentVariable.ValueTableMap; - IntegerEnvironmentVariable = environmentVariable.IntegerEnvironmentVariable; - FloatEnvironmentVariable = environmentVariable.FloatEnvironmentVariable; - DataEnvironmentVariable = environmentVariable.DataEnvironmentVariable; - } - } - - public class EnvironmentVariable - { - public EnvDataType Type { get; set; } - public string Name { get; set; } - public string Unit { get; set; } - public string Comment { get; set; } - public EnvAccessibility Access { get; set; } - public IReadOnlyDictionary ValueTableMap { get; set; } - - public readonly IDictionary CustomProperties = new Dictionary(); - public NumericEnvironmentVariable IntegerEnvironmentVariable { get; set; } - public NumericEnvironmentVariable FloatEnvironmentVariable { get; set; } - public DataEnvironmentVariable DataEnvironmentVariable { get; set; } +namespace DbcParserLib.Model; - internal ImmutableEnvironmentVariable CreateEnvironmentVariable() - { - return new ImmutableEnvironmentVariable(this); - } - } - - public class NumericEnvironmentVariable - { - public T Minimum { get; set; } - public T Maximum { get; set; } - public T Default { get; set; } - } +public class EnvironmentVariable +{ + public EnvDataType Type { get; internal set; } + public string Name { get; internal set; } + public string Unit { get; internal set; } + public string Comment { get; internal set; } + public EnvAccessibility Access { get; internal set; } + public IReadOnlyDictionary ValueTableMap { get; internal set; } + public IReadOnlyDictionary CustomProperties => customProperties; + internal readonly Dictionary customProperties = new (); + public NumericEnvironmentVariable IntegerEnvironmentVariable { get; internal set; } + public NumericEnvironmentVariable FloatEnvironmentVariable { get; internal set; } + public DataEnvironmentVariable DataEnvironmentVariable { get; internal set; } +} - public class DataEnvironmentVariable - { - public uint Length { get; set; } - } +public class NumericEnvironmentVariable +{ + public T Minimum { get; set; } + public T Maximum { get; set; } + public T Default { get; set; } +} - public enum EnvDataType - { - Integer, Float, String, Data - } +public class DataEnvironmentVariable +{ + public uint Length { get; set; } +} - public enum EnvAccessibility - { - Unrestricted, Read, Write, ReadWrite - } +public enum EnvDataType +{ + Integer, + Float, + String, + Data } + +public enum EnvAccessibility +{ + Unrestricted, + Read, + Write, + ReadWrite +} \ No newline at end of file diff --git a/DbcParserLib/Model/Message.cs b/DbcParserLib/Model/Message.cs index 018806f..e219235 100644 --- a/DbcParserLib/Model/Message.cs +++ b/DbcParserLib/Model/Message.cs @@ -1,57 +1,57 @@ using System.Collections.Generic; +using System.Linq; -namespace DbcParserLib.Model +namespace DbcParserLib.Model; + +public class Message { - internal class ImmutableMessage - { - public uint ID { get; } - public bool IsExtID { get; } - public string Name { get; } - public ushort DLC { get; } - public string Transmitter { get; } - public string Comment { get; } - public int CycleTime { get; } - public IReadOnlyList Signals { get; } - public IReadOnlyDictionary CustomProperties { get; } + public uint ID { get; internal set; } + public bool IsExtID { get; internal set; } + public string Name { get; internal set; } + public ushort DLC { get; internal set; } + public string Transmitter { get; internal set; } + public string Comment { get; internal set; } + public bool IsMultiplexed { get; private set; } + public int? CycleTime { get; private set; } + public IReadOnlyDictionary Signals => signals; + internal Dictionary signals = new (); + public IReadOnlyDictionary CustomProperties => customProperties; + internal readonly Dictionary customProperties = new (); - internal ImmutableMessage(Message message, IReadOnlyList signals) + internal void FinishUp() + { + AdjustExtendedId(); + var hasCycleTime = TryGetCycleTime(out var cycleTime); + CycleTime = hasCycleTime ? cycleTime : null; + + foreach (var signal in signals.Values) { - message.CycleTime(out var cycleTime); - - ID = message.ID; - IsExtID = message.IsExtID; - Name = message.Name; - DLC = message.DLC; - Transmitter = message.Transmitter; - Comment = message.Comment; - CycleTime = cycleTime; - Signals = signals; + signal.FinishUp(); + signal.MessageID = ID; + } + IsMultiplexed = signals.Values.Any(s => s.Multiplexing.Role == MultiplexingRole.Multiplexor); + } + + private bool TryGetCycleTime(out int cycleTime) + { + cycleTime = 0; - //TODO: remove explicit cast (CustomProperty in Message class should be Dictionary instead IDictionary) - CustomProperties = (IReadOnlyDictionary)message.CustomProperties; + if (customProperties.TryGetValue("GenMsgCycleTime", out var property)) + { + cycleTime = property.IntegerCustomProperty.Value; + return true; } + + return false; } - public class Message + private void AdjustExtendedId() { - public uint ID; - public bool IsExtID; - public string Name; - public ushort DLC; - public string Transmitter; - public string Comment; - - public List Signals = new List(); - public IDictionary CustomProperties = new Dictionary(); - - internal ImmutableMessage CreateMessage() + // For extended ID bit 31 is always 1 + if (ID >= 0x80000000) { - var signals = new List(); - foreach(var signal in Signals) - { - signals.Add(signal.CreateSignal()); - } - return new ImmutableMessage(this, signals); + IsExtID = true; + ID -= 0x80000000; } } -} +} \ No newline at end of file diff --git a/DbcParserLib/Model/MultiplexingInfo.cs b/DbcParserLib/Model/MultiplexingInfo.cs index 3ca733f..7536a15 100644 --- a/DbcParserLib/Model/MultiplexingInfo.cs +++ b/DbcParserLib/Model/MultiplexingInfo.cs @@ -1,24 +1,50 @@ -namespace DbcParserLib.Model +namespace DbcParserLib.Model; + +public class MultiplexingInfo { - public struct MultiplexingInfo + private const string MultiplexorLabel = "M"; + private const string MultiplexedLabel = "m"; + + public MultiplexingRole Role { get; } + public int Group { get; } + + public MultiplexingInfo(Signal signal) { - public MultiplexingInfo(MultiplexingRole role) - : this(role, 0) + Role = ParseMultiplexingInfo(signal, out var group); + Group = group; + } + + private static MultiplexingRole ParseMultiplexingInfo(Signal signal, out int multiplexingGroup) + { + multiplexingGroup = 0; + if (string.IsNullOrWhiteSpace(signal.multiplexing)) { + return MultiplexingRole.None; } - public MultiplexingInfo(MultiplexingRole role, int group) + if (signal.multiplexing.Equals(MultiplexorLabel)) { - Role = role; - Group = group; + return MultiplexingRole.Multiplexor; } - public MultiplexingRole Role {get;} - public int Group {get;} - } + if (signal.multiplexing.StartsWith(MultiplexedLabel)) + { + var substringLength = signal.multiplexing.Length - (signal.multiplexing.EndsWith(MultiplexorLabel) ? 2 : 1); - public enum MultiplexingRole - { - None, Unknown, Multiplexed, Multiplexor + if (int.TryParse(signal.multiplexing.Substring(1, substringLength), out multiplexingGroup)) + { + return MultiplexingRole.Multiplexed; + } + } + + return MultiplexingRole.Unknown; } } + +public enum MultiplexingRole +{ + None, + Unknown, + Multiplexed, + Multiplexor +} \ No newline at end of file diff --git a/DbcParserLib/Model/Node.cs b/DbcParserLib/Model/Node.cs index 6e70884..8883ebd 100644 --- a/DbcParserLib/Model/Node.cs +++ b/DbcParserLib/Model/Node.cs @@ -1,39 +1,15 @@ using System.Collections.Generic; -namespace DbcParserLib.Model -{ - internal class ImmutableNode - { - public string Name { get; } - public string Comment { get; } - public IReadOnlyDictionary CustomProperties { get; } - public IReadOnlyDictionary EnvironmentVariables { get; } - - internal ImmutableNode(Node node, IReadOnlyDictionary environmentVariables) - { - Name = node.Name; - Comment = node.Comment; - //TODO: remove explicit cast (CustomProperty in Node class should be Dictionary instead IDictionary) - CustomProperties = (IReadOnlyDictionary)node.CustomProperties; - EnvironmentVariables = environmentVariables; - } - } +namespace DbcParserLib.Model; - public class Node - { - public string Name; - public string Comment; - public IDictionary CustomProperties = new Dictionary(); - public readonly IDictionary EnvironmentVariables = new Dictionary(); - - internal ImmutableNode CreateNode() - { - var environmentVariables = new Dictionary(); - foreach (var environmentVariable in EnvironmentVariables) - { - environmentVariables.Add(environmentVariable.Key, environmentVariable.Value.CreateEnvironmentVariable()); - } - return new ImmutableNode(this, environmentVariables); - } - } +public class Node +{ + public string Name { get; internal set; } + public string Comment { get; internal set; } + + public IReadOnlyDictionary CustomProperties => customProperties; + internal readonly Dictionary customProperties = new (); + + public IReadOnlyDictionary EnvironmentVariables => environmentVariables; + internal readonly Dictionary environmentVariables = new (); } \ No newline at end of file diff --git a/DbcParserLib/Model/Signal.cs b/DbcParserLib/Model/Signal.cs index d84f7e2..d6f4bee 100644 --- a/DbcParserLib/Model/Signal.cs +++ b/DbcParserLib/Model/Signal.cs @@ -1,87 +1,87 @@ using System.Collections.Generic; -namespace DbcParserLib.Model +namespace DbcParserLib.Model; + +public class Signal { - internal class ImmutableSignal - { - public uint ID { get; } - public string Name { get; } - public ushort StartBit { get; } - public ushort Length { get; } - public byte ByteOrder { get; } - public DbcValueType ValueType { get; } - public double InitialValue { get; } - public double Factor { get; } - public bool IsInteger { get; } - public double Offset { get; } - public double Minimum { get; } - public double Maximum { get; } - public string Unit { get; } - public string[] Receiver { get; } - public IReadOnlyDictionary ValueTableMap { get; } - public string Comment { get; } - public string Multiplexing { get; } - public IReadOnlyDictionary CustomProperties { get; } + public uint MessageID { get; internal set; } + public string Name { get; internal set; } + public ushort StartBit { get; internal set; } + public ushort Length { get; internal set; } + public byte ByteOrder { get; internal set; } = 1; + public DbcValueType ValueType { get; internal set; } = DbcValueType.Signed; + public bool IsInteger { get; private set; } + public double Factor { get; internal set; } = 1; + public double Offset { get; internal set; } + public bool HasScaling { get; private set; } + public double Minimum { get; internal set; } + public double Maximum { get; internal set; } + public bool HasLimits { get; private set; } + public string Unit { get; internal set; } + public string[] Receiver { get; internal set; } + public IReadOnlyDictionary ValueTableMap { get; internal set; } = new Dictionary(); + public string Comment { get; internal set; } + public MultiplexingInfo Multiplexing { get; private set; } + internal string multiplexing; + public IReadOnlyDictionary CustomProperties => customProperties; + internal readonly Dictionary customProperties = new(); + public double? InitialValue { get; private set; } - internal ImmutableSignal(Signal signal) - { - ID = signal.ID; - Name = signal.Name; - StartBit = signal.StartBit; - Length = signal.Length; - ByteOrder = signal.ByteOrder; - ValueType = signal.ValueType; - InitialValue = signal.InitialValue; - Factor = signal.Factor; - IsInteger = signal.IsInteger; - Offset = signal.Offset; - Minimum = signal.Minimum; - Maximum = signal.Maximum; - Unit = signal.Unit; - Receiver = signal.Receiver; - ValueTableMap = signal.ValueTableMap; - Comment = signal.Comment; - Multiplexing = signal.Multiplexing; - CustomProperties = signal.CustomProperties; - } + internal void FinishUp() + { + InitialValue = null; + var hasInitialValue = TryGetInitialValue(out var initialValue); + InitialValue = hasInitialValue ? initialValue : null; + Multiplexing = new MultiplexingInfo(this); + HasScaling = ExtensionsAndHelpers.IsDoubleZero(Offset) && ExtensionsAndHelpers.AreDoublesEqual(Factor, 1.0); + HasLimits = !ExtensionsAndHelpers.IsDoubleZero(Minimum) || !ExtensionsAndHelpers.IsDoubleZero(Maximum); + IsInteger = CheckIsInteger(); } - public class Signal + private bool TryGetInitialValue(out double? initialValue) { - public uint ID; - public string Name; - public ushort StartBit; - public ushort Length; - public byte ByteOrder = 1; - public DbcValueType ValueType = DbcValueType.Signed; - public double Factor = 1; - public bool IsInteger = false; - public double Offset; - public double Minimum; - public double Maximum; - public string Unit; - public string[] Receiver; - public IReadOnlyDictionary ValueTableMap = new Dictionary(); - public string Comment; - public string Multiplexing; - public readonly Dictionary CustomProperties = new Dictionary(); - public double InitialValue + initialValue = null; + + if (!customProperties.TryGetValue("GenSigStartValue", out var property)) { - get - { - this.InitialValue(out var initialValue); - return initialValue; - } + return false; } - internal ImmutableSignal CreateSignal() + double value; + switch (property.CustomPropertyDefinition.DataType) { - return new ImmutableSignal(this); + case CustomPropertyDataType.Float: + value = property.FloatCustomProperty.Value; + break; + case CustomPropertyDataType.Hex: + value = property.HexCustomProperty.Value; + break; + case CustomPropertyDataType.Integer: + value = property.IntegerCustomProperty.Value; + break; + default: + return false; } - } - public enum DbcValueType + initialValue = value * Factor + Offset; + return true; + } + + private bool CheckIsInteger() { - Signed, Unsigned, IEEEFloat, IEEEDouble + if (ValueType is not (DbcValueType.Signed or DbcValueType.Unsigned)) + { + return false; + } + + return ExtensionsAndHelpers.IsWholeNumber(Factor) && ExtensionsAndHelpers.IsWholeNumber(Offset); } } + +public enum DbcValueType +{ + Signed, + Unsigned, + IEEEFloat, + IEEEDouble +} \ No newline at end of file diff --git a/DbcParserLib/Parser.cs b/DbcParserLib/Parser.cs index f4ec32b..7c06fd7 100644 --- a/DbcParserLib/Parser.cs +++ b/DbcParserLib/Parser.cs @@ -1,5 +1,6 @@ using System.IO; using System.Collections.Generic; +using DbcParserLib.Model; using DbcParserLib.Parsers; using DbcParserLib.Observers; diff --git a/DbcParserLib/Parsers/SignalLineParser.cs b/DbcParserLib/Parsers/SignalLineParser.cs index a9b3d32..f8d3d25 100644 --- a/DbcParserLib/Parsers/SignalLineParser.cs +++ b/DbcParserLib/Parsers/SignalLineParser.cs @@ -31,13 +31,12 @@ public bool TryParse(string line, IDbcBuilder builder, INextLineProvider nextLin var factorStr = match.Groups[7].Value; var sig = new Signal { - Multiplexing = match.Groups[2].Value, + multiplexing = match.Groups[2].Value, Name = match.Groups[1].Value, StartBit = ushort.Parse(match.Groups[3].Value, CultureInfo.InvariantCulture), Length = ushort.Parse(match.Groups[4].Value, CultureInfo.InvariantCulture), ByteOrder = byte.Parse(match.Groups[5].Value, CultureInfo.InvariantCulture), // 0 = MSB (Motorola), 1 = LSB (Intel) ValueType = (match.Groups[6].Value == SignedSymbol ? DbcValueType.Signed : DbcValueType.Unsigned), - IsInteger = IsInteger(factorStr), Factor = double.Parse(match.Groups[7].Value, CultureInfo.InvariantCulture), Offset = double.Parse(match.Groups[8].Value, CultureInfo.InvariantCulture), Minimum = double.Parse(match.Groups[9].Value, CultureInfo.InvariantCulture), @@ -53,10 +52,5 @@ public bool TryParse(string line, IDbcBuilder builder, INextLineProvider nextLin return true; } - - private static bool IsInteger(string str) - { - return int.TryParse(str, out _); - } } } diff --git a/Demo/Demo.csproj b/Demo/Demo.csproj index 20a713f..e535203 100644 --- a/Demo/Demo.csproj +++ b/Demo/Demo.csproj @@ -2,7 +2,7 @@ WinExe - net6.0-windows + net8.0-windows true diff --git a/Demo/Form1.cs b/Demo/Form1.cs index e3e7cce..f90c34b 100644 --- a/Demo/Form1.cs +++ b/Demo/Form1.cs @@ -5,6 +5,7 @@ using System.Reflection; using System.Windows.Forms; using DbcParserLib; +using DbcParserLib.Model; using DbcParserLib.Observers; /* @@ -124,9 +125,10 @@ public void PopulateView(Dbc dbc) dtMessages.Columns.Add("DLC"); dtMessages.Columns.Add("Transmitter"); dtMessages.Columns.Add("CycleTime"); - foreach (var msg in dbc.Messages) + foreach (var msg in dbc.Messages.Values) { - msg.CycleTime(out var cycleTime); + var messageCycleTime = msg.CycleTime; + var cycleTime = messageCycleTime ?? -1 ; dtMessages.Rows.Add("0x" + msg.ID.ToString("X"), msg.Name, msg.DLC, msg.Transmitter, cycleTime); } @@ -149,12 +151,12 @@ public void PopulateView(Dbc dbc) { dtSignals.Columns.Add(node.Name); } - foreach (var msg in dbc.Messages) + foreach (var msg in dbc.Messages.Values) { - foreach (var sig in msg.Signals) + foreach (var sig in msg.Signals.Values) { var valueTableString = string.Join("\n", sig.ValueTableMap); - dtSignals.Rows.Add("0x" + sig.ID.ToString("X"), sig.Name, sig.StartBit, sig.Length, sig.ByteOrder, sig.ValueType, sig.InitialValue, sig.Factor, sig.Offset, sig.Minimum, sig.Maximum, sig.Unit, valueTableString, sig.Comment); + dtSignals.Rows.Add("0x" + sig.MessageID.ToString("X"), sig.Name, sig.StartBit, sig.Length, sig.ByteOrder, sig.ValueType, sig.InitialValue, sig.Factor, sig.Offset, sig.Minimum, sig.Maximum, sig.Unit, valueTableString, sig.Comment); int rowIdx = dtSignals.Rows.Count - 1; int colIdx = dtSignals.Columns.IndexOf(msg.Transmitter);